Innostuin tällä viikolla tutkimaan miten Facebook-verkostoja olisi mahdollista kerätä ja visualisoida vastaavalla tavalla kuten olen aikaisemmin visualisoinut Twitter-verkostoja sekä keitä @TuomasEnbuske seuraa. Enemmän tai vähemmän tunnetusti Facebook on kitsaampi jakamaan tietojaan Graph-rajapintansa kautta kuin mitä Twitter oman rajapintansa kautta, mutta rohkaistuin kuitenkin yrittämään tehtyäni ensin Olli Parviaisen kanssa kansanedustajien kaveruusverkoston sekä nähtyäni miten Jens Finnäs oli onnistunut tekemään vastaavanlaisen toteutuksen Ruotsin parlamentista.
Graph-rajapinta
Facebook:lla on siis olemassa Graph-niminen rajapinta, joka mahdollistaa Facebook-datan käsittelyn koneellisesti. Lähinnä rajapinta on varmasti tarkoitettu erilaisille Facebook-applikaatioille, mutta sitä on mahdollista käyttää myös muuten. Yksinkertainen Graph-rajapintakysely, joka palauttaa halutun käyttäjän (tässä tapauksessa allekirjoittaneen) tiedot (kuten ID, sukupuoli, nimi, jne.) voidaan suorittaa syöttämällä seuraava osoite selaimeen:
graph.facebook.com/teelmo.
Rajapintaa voidaan kutsua yhtälailla käyttäjän käyttäjänimellä kuin Facebook:n käyttäjä-ID-arvolla. Toisin sanoen kysely:
graph.facebook.com/635279474,
tuottaa saman vastauksen. Tiedot ovat haettavissa Graph-rajapinnan kautta kenestä tahansa Facebook-profiilista huolimatta siitä miten suljettu tai avoin profiili on. Rajapinnalta on mahdollista kysyä myös monia muita asioita, mutta esimerkiksi satunnaisen käyttäjän Facebook-kavereiden hakeminen ei ole mahdollista edes vaikka olisit kyseisen käyttäjän kaveri. Muiden kuin itsensä kavereiden hakeminen onnistuu rajapinnan kautta jos käyttäjä on sallinut tietojensa jakamisen applikaatiolle, jonka ylläpitäjä olet. Omat Facebook-kaverit rajapinnan kautta saa haettua.
Python + MongoDB = voitto
Kuten edellä näytettiin on Graph-rajapintaa mahdollista selata käsipelillä selaimen avulla, mutta käsiteltäessä suurempia datajoukkoja tulee tiedon keräämisestä tällä tavoin raskasta. Näin ollen erinäiset ohjelmointikielet ja niillä rakennetut scriptit eli lyhyet kertaalleen ajettavat ohjelmakoodit tulevat apuun. Käytetyllä ohjelmointikielellä ei ole suurta merkitystä vaan valinta kannattaa tehdä sen pohjalta, joka on itselle tutuin ja luontevin. Hyviä vaihtoehtoja kuitenkin ovat ainakin Python, Ruby ja Facebook:n tapauksessa etenkin PHP, koska suurin osa Facebook:n koodiesimerkeistä on kirjoitettu sillä. Itse valitsin kuitenkin Pythonin, koska halusin jatkojalostaa omaa Python osaamistani.
Pythonille löytyy useampia Facebook Graph API -kirjastoja, mutta ainakin pyFaceGraph-nimisen kirjaston avulla Graph-rajapinnan käyttö on todella yksinkertaista. Tässä yksinkertainen koodin pätkä, joka hakee käyttäjän tiedot kirjaston avulla jos käyttäjän tietoja ei ole jo aikaisemmin haettu ja tallennettu tietokantaan.
>>> from facegraph import Graph
>>> g = Graph()
>>> ...
>>> username = 'teelmo'
>>> # Check that username is not already in MongoDB
>>> if not users.find({"data.username": fusername}).count():
>>> user = g[username]()
>>> print user.id
'635279474'
Tietojen tallentamisessa hyödynsin MongoDB:tä, joka on NoSQL-tietokanta. MongoDB soveltuu käytettäväksi tämänkaltaisissa scripteissä, jotka hakevat tietoa netistä, koska tiedon eheydestä eikä rakenteesta tarvitse välittää samalla tavalla kuin käytettäessä esimerkiksi MySQL:ää tai muuta SQL-pohjaista tietokannanhallintajärjestelmää. MongoDB hyödyntää tiedon tallentamisessa JSON-formaattia, joka on myös formaatti, jossa Graph-rajapinta palauttaa hakutulokset.
Kuvassa 1 nähdään miten scripti hakee annettujen käyttäjien tietoja Graph-rajapinnalta. Tässä tapauksessa suurin osa haettavista käyttäjistä on jo aikaisemmin noudettu lokaaliin tietokantaan, mutta yhden käyttäjän osalta tiedot haetaan Graph-rajapinnasta.
Pythonilla ja MongoDB:llä toteutettu keräin, joka hakee annettujen käyttäjien tiedot Facebookin Graph-rajapinnasta. (Kuva 1) |
Käyttäjien tiedot kyllä, mutta miten yhteydet?
Graph-rajapinnan tarjoamat toiminnallisuudet on listattu täällä. Rajapinnan avulla saadaan siis kysyttyä suoraan mm. käyttäjien, tapahtumien ja sivujen tietoja. Käyttäjien välisiä yhteyksiä, tapahtumaan osallistujia tai sivujen tykkääjiä ei rajapinnan perustoiminnallisuuksilla kuitenkaan saa haettua.
Apuun tulee kuitenkin Graph-rajapintaa laajentava Facebook Query Language (FQL). FQL mahdollistaa Graph-rajapinnan kautta saatavien tietojen hakemisen SQL:n kaltaisella kyselykielellä. Esimerkiksi Facebook:n käyttäjä-ID:tä vastaava käyttäjänimi on mahdollista hakea seuraavalla kyselyllä:
SELECT username FROM user WHERE uid = 635279474
Käyttäjien välisten kaveruussuhteiden kyseleminen on mahdollista friend-taulusta. On huomioitavaa, että kaveruussuhteita on mahdollista kysyä myös sellaisten käyttäjien välillä, jotka muuten ovat piilottaneet profiilinsa. FQL:ää on mahdollista kokeilla erityisellä Graph API Explorer -työkalulla. FQL:n käyttäminen edellyttää OAuth-tunnistautumista ja ns. "Access token" täytyy välittää kyselyiden mukana.
Toteutin myös yhteyksien hakemisen Python-scriptillä. Apuna käytin Pythonille löytyvää requests-kirjastoa. Tässä yksinkertaisuudessaan ja lyhykäisyydessään FQL-kyselyn toteuttava koodinpätkä:
>>> import requests
>>> ...
>>> fql_query = "SELECT uid2 FROM friend WHERE uid1 = 635279474 and uid2 = %d" % uid2
>>> fql = "/fql?q=%s&access_token=%s" % (fql_query, access_token)
>>> try:
>>> r = requests.get(domain + fql)
>>> except:
>>> print "Error occured"
FQL-kysely palauttaa ne käyttäjä-ID-arvot, jotka täsmäävät annettuun hakuun. Eli hakiessani olenko kaveri käyttäjien A, B ja C kanssa palauttaa Facebook niiden käyttäjien ID:t, joiden kanssa haetuista olen kaveri.
Tulokset kirjoitin .gexf-muodossa ja visualisoinnin tein Gephi-nimisellä verkostojen visualisointiohjelmalla. Gephi:n käyttöön en mene tässä sen syvällisemmin, koska olen käsitellyt sitä jo aiemmin tässä blogissa ja tyydynkin vain viittaamaan Olli Parviaiseen luomiin ohjeistuksiin.
Summa summarum
Yhteenvetona voitaneen todeta, että Facebook:sta on mahdollista muodostaa kaveruusverkostoja vastaavasti kuin aikaisemmin olen näyttänyt Twitter:stä. Facebook:n kohdalla joutuu hieman enemmän tekemään käsityötä datan keräämisessä, mutta lopputulos on täysin vastaava. Erona Twitter-verkostoihin on, että Facebook:sta kerätyistä kaveruusverkostoista muodostuu paljon rypästeisempiä (Kuva 2). Eri ryhmät kuten lapsuuden ystävät, koulukaverit, työkaverit ja sukulaiset ovat hyvin vähän tekemisissä toistensa kanssa, mutta ovat linkittyneet keskenään hyvin paljon.
Facebook-kaveriverkostoni. Eri ryhmät erottuvat toisistaan erittäin selkeästi. Solmuja verkostossa on 206 ja yhteyksiä 1878. (Kuva 2) |
Twitter-seuraajaverkostoni. Ihmiset ovat verkostoituneet keskenään hyvin tiheästi. Solmuja verkostossa 149 ja yhteyksiä 1209. (Kuva 3) |
Stay tuned!
"Ryömin juuri kaikkia @TuomasEnbuske:n seuraajia Keitä me kaikki ollaan Seuraavaksi @alexstubb Siinä taitaakin olla kaikki suom. Twitteristit" - https://twitter.com/#!/teelmo/status/185680267548168192