Adatok lekérdezése a webről

Már minden mást megpróbáltál, és még mindig nem sikerült rátenned a kezed az általad kívánt adatokra. Megtaláltad az adatokat a weben, de sajnos letöltési lehetőségek nem állnak rendelkezésre, a másolás-beillesztés pedig nem sikerült. Ne félj, még mindig lehet mód arra, hogy kinyerd az adatokat. Például ezt teheted:

  • Kinyerheted az adatokat webes API-kon keresztül, ilyenek az online adatbázisok és sok modern webalkalmazás (beleértve a Twittert, Facebookot és sok mást) által biztosított felületek. Ez fantasztikus módszer arra, hogy hozzáférj a kormányzati vagy kereskedelmi adatokhoz, valamint a közösségi média oldalakról származó adatokhoz.
  • Kinyerhetsz adatokat a PDF-fájlokból. Ez nagyon nehéz, mert a PDF egy nyomtatókhoz készült nyelv, és nem tárol sok információt azoknak az adatoknak a szerkezetéről, amelyeket egy dokumentumon belül megjelenít. Az információk PDF-fájlokból való kinyerése túllépi ennek a könyvnek a kereteit, de van néhány olyan eszköz és útmutató, amelyek segíthetnek neked ennek elvégzésében.
  • Kinyerheted a weboldalak képernyőn látható adatait (screen scrape). A képernyő tartalmának kinyerése (screen scraping) során strukturált tartalmat nyersz ki egy normális weboldalról egy scraping program segítségével, vagy egy kis kódrészlet megírásával. Bár ez a módszer nagyon hatékony és sok helyen lehet használni, szükséges hozzá érteni valamennyire azt is, hogyan működik a web.

Mindezekkel a nagyszerű technikai lehetőségekkel együtt ne feledkezz meg az egyszerű opciókról: gyakran érdemes egy kis időt eltölteni géppel olvasható adatokat tartalmazó fájlok keresésével, vagy felhívni azt az intézményt, amely az általad keresett adatokat tárolja.

Ebben a fejezetben végigmegyünk az adatok HTML-alapú weboldal képernyőről való kinyerésének egy nagyon alapvető példáján.

Mik azok a géppel olvasható adatok?

A legtöbb ilyen módszer célja, hogy hozzáférést szerezz a gép számára olvasható adatokhoz. Géppel feldolgozható adatokat azért hoznak létre, hogy a számítógép dolgozza fel ahelyett, hogy egy emberi felhasználónak mutatnád meg őket. Az ilyen adatok szerkezete a tartalmazott információkhoz kapcsolódik, és nem a végső megjelenítésüknek a módjához. A gép számára könnyen olvasható formátumokra példák a CSV, XML, JSON és Excel fájlok, míg az olyan formátumok, mint a Word-dokumentumok, HTML-oldalak és PDF-fájlok inkább az információk vizuális elrendezésére valók. A PDF például olyan nyelv, amely közvetlenül a nyomtatódhoz beszél, inkább törődik egy oldalon található vonalak és pontok pozíciójával, mintsem a megkülönböztethető karakterekkel.

Mire való az adatok kinyerése a weboldalakról?

Mindenki megtette már ezt: elmész egy weboldalra, látsz egy érdekes táblázatot, és megpróbálod átmásolni Excelbe, így hozzáadhatsz néhány számot, vagy eltárolhatod későbbi felhasználásra. Ez gyakran mégsem igazán működik, vagy az általad keresett információkat számos weboldalon szórták szét. A kézi másolás gyorsan nagyon fárasztóvá válhat, így van értelme annak, hogy ehhez egy kis programkódot használjunk.

A képernyőtartalom kinyerésének előnye az, hogy virtuálisan bármely weboldallal megteheted – az időjárás-előrejelzésektől a kormányzati költekezésig, még akkor is, ha az a weboldal nem rendelkezik a nyers adatok eléréséhez szükséges API-val.

Mit tudsz és mit nem tudsz képernyőtartalomból kinyerni

Persze vannak arra vonatkozó korlátozások, hogy mit lehet képernyőtartalomból kinyerni. Néhány tényező, amelyek megnehezítik egy oldal képernyőtartalmának kinyerését:

  • Rosszul formázott HTML-kód kevés vagy nem strukturált információval, ilyenek például a régebbi kormányzati weboldalak.
  • Olyan hitelesítési rendszerek, amelyek megakadályozzák az automatikus hozzáférést, pl. a CAPTCHA-kódok és a fizetős hozzáférés.
  • Munkamenet-alapú rendszerek, amelyek böngésző sütiket használnak annak nyomon követésére, hogy mit csinált a felhasználó.
  • A teljes cikklisták és a helyettesítő karakteres keresési lehetőségek hiánya.
  • A szerver rendszergazdái blokkolják a tömeges hozzáférést (bulk access).

A korlátozások másik fajtáját a jogi akadályok jelentik: néhány országban elismerik azt az adatbázisokhoz kapcsolódó jogot, amely korlátozza, hogy újra felhasználd az online közzétett információkat. Dönthetsz úgy, hogy figyelmen kívül hagyod az engedélyezést és mindenképpen felhasználod az adatokat – a helyi jogrendszertől függ, hogy vannak-e újságíróként különleges jogosultságaid. A szabadon elérhető kormányzati adatok képernyőtartalmának kinyerése rendben lehet, de inkább kétszer is ellenőrizd, hogy szabad-e mielőtt nyilvánosságra hozod őket. A kereskedelmi szervezetek – és bizonyos nem kormányzati szervezetek – kevésbé türelmesek, és megpróbálhatnak feljelenteni amiatt, hogy „szabotálod” a rendszerüket. Más információk közzététele sértheti az egyének magánszférához való jogát, és ezáltal az adatvédelmi törvényeket vagy a szakmai etikát is.

Olyan eszközök, amelyek segítenek neked a kinyerésben

Sok olyan program van, ami segít a weboldalakról nagymennyiségű információt kinyerni, vannak erre böngésző bővítményeket és néhány webes szolgáltatás is. A böngésződtől függően az olyan eszközök, mint a Readability (amely segít szöveget kinyerni egy weboldalból) vagy a DownThemAll (amely lehetővé teszi, hogy egyszerre sok fájlt tölts le), segít neked automatizálni az unalmas feladatokat, míg a Chrome Scraper nevű bővítményét kifejezetten arra fejlesztették, hogy táblázatokat nyerjenek ki weboldalakról. Az olyan fejlesztői bővítmények, mint a FireBug (a Firefoxhoz ugyanaz a dolog, amely már benne van a Chrome-ban, Safariban és az IE-ben) lehetővé teszi számodra, hogy pontosan kövesd, hogy egy weboldal hogyan épül fel és milyen kommunikáció történik a böngésződ és a kiszolgáló között.

A ScraperWiki egy olyan weboldal, amely segít számos programozási nyelven adatkinyerő programokat kódolni, beleértve a Python, Ruby és PHP nyelveket. Ha a kinyerést a számítógépeden lévő programozási környezet beállításának kellemetlenségei nélkül szeretnéd elkezdeni, akkor ez egy járható út. Más webszolgáltatások, mint például a Google Táblázatok és a Yahoo! Pipes, szintén lehetővé teszik, hogy információt nyerj ki weboldalakról.

Hogyan működik egy scraper program?

A webes scraper programok általában olyan kis kódrészletek, amelyeket Python, Ruby, vagy PHP programozási nyelven írtak. A megfelelő nyelv kiválasztása nagyrészt annak a kérdése, hogy melyik közösséghez van hozzáférésed: ha van valaki a szerkesztőségedben vagy városodban, aki már dolgozik ezek közül valamelyik nyelvvel, akkor van értelme annak, hogy te is ugyanazt a nyelvet használd.

Míg a korábban említett kattintással kijelölést támogató scraper eszközök hasznosak lehetnek az indulásnál, az igazán bonyolult rész ott kezdődik, hogy a megfelelő oldalakat és ezeken az oldalakon a megfelelő elemeket jelöld meg, mikor megpróbálod kinyerni a kívánt információt. Ezek a feladatok nem a programozásról, hanem a weboldal és az azt kiszolgáló adatbázis felépítésének megértéséről szólnak.

Amikor a böngésződ megjelenít egy weboldalt, szinte mindig két technológiát alkalmaz: a HTTP egy módszer arra, hogy kommunikáljon a szerverrel, és hogy olyan konkrét erőforrásokat kérjen le, mint például a dokumentumok, képek vagy videók. A HTML pedig az a nyelv, amelyen a weboldalakat szerkesztik.

Egy weblap anatómiája

Minden HTML-oldal szakaszok hierarchiájaként épül fel (amelyeket a HTML „címkék” határoznak meg). Egy nagy szakasz sok kisebbet fog tartalmazni – például egy táblázat, amelynek sok kisebb része van: sorok és cellák. Sokféle címke (tag) van, amelyek különböző funkciókat hajtanak végre – néhányuk szakaszokat, mások táblázatokat, képeket vagy linkeket hoznak létre. A címkéknek lehetnek további tulajdonságai is (pl. lehetnek egyedi azonosítók) és „osztályoknak” (class) nevezett csoportokhoz tartozhatnak, amely lehetővé teszi, hogy megjelöljük őket és rámutassunk egy dokumentumban lévő egyedi elemekre. A megfelelő elemek ilyen módon való kiválasztása és a tartalmuk kinyerése a kulcs egy scraper program megírásánál.

Ha a weboldalon lévő elemeket tekintjük: minden felbontható szakaszokon belüli szakaszokra.

Hogy adatokat nyerj ki a weboldalakról, szükséged lesz arra, hogy egy kicsit tanulj az elemek különböző típusairól, amelyek egy HTML-dokumentumban lehetnek. Például a <table> elem egy egész táblázatot takar, amelynek vannak <tr> (táblázatsor) elemei a soraihoz, amelyek viszont <td> (táblázatadatok) elemeket tartalmaznak minden egyes cellához. A leggyakoribb elemtípus, amellyel találkozni fogsz, a <div>, amely alapvetően bármilyen tartalomblokkot jelenthet. A legegyszerűbb módja annak, hogy ezeket az elemeket szemléltesd az, ha használod a fejlesztői eszköztárat a böngésződben: ezek lehetővé teszik, hogy az egeret a weboldal bármely része fölé vidd, és megnézd a mögötte lévő kódot.

A címkék úgy működnek, mint a könyv végei, amelyek jelzik egy egység kezdetét és végét. Például jelzik egy dőlt vagy kiemelt szövegrész kezdetét és jelzik annak a szakasznak a végét. Ilyen egyszerű.

57. ábra: A Nemzetközi Atomenergia Ügynökség (IAEA) portálja (news.iaea.org)
57. ábra: A Nemzetközi Atomenergia-ügynökség (IAEA) portálja (news.iaea.org)

Példa: nukleáris balesetek összeszedése Pythonnal

A NEWS a Nemzetközi Atomenergia-ügynökség (NAÜ) portálja, amely a nemzetközi sugárzással kapcsolatos eseményekről ír (és komoly esélye van arra, hogy tagságot nyerjen a Furcsa Címek Klubjában!). A weboldal az eseményeket egy egyszerű blogszerű oldalon sorolja fel, amelyből könnyen kinyerhetők az információk.

Kezdetnek hozz létre egy új Pythonban írt scraper programot a ScraperWiki oldalon, kapni fogsz egy szövegterületet, amely többnyire üres, kivéve némi vázként használható kódot. Egy másik böngésző ablakban nyisd meg a NAÜ oldalt, és nyisd meg a fejlesztői eszköztárat a böngésződben. Az „Elemek (Elements)” nézetben próbáld megtalálni az egyik hírelemcímhez tartozó HTML-elemet. A böngésződ fejlesztői eszköztára segít neked abban, hogy a weboldalon található elemekhez megtaláld az őket felépítő HTML-kódot.

Ennek az oldalnak a vizsgálata ki fogja adni, hogy a címek egy <table> elemen belül található <h4> elemek. Minden egyes esemény egy <tr> sor, amely egy leírást és egy dátumot is tartalmaz. Ha az összes esemény címét ki szeretnénk nyerni, meg kell találnunk a módját annak, hogy sorban kijelöljük a táblázatban lévő egyes sorokat, miközben lekérdezzük a címelemekben lévő összes szöveget.

Annak érdekében, hogy ezt a folyamatot lefordítsuk kódra, magunknak is tisztában kell lennünk a szóban forgó összes lépéssel. Hogy érzékeltessük azt, hogy milyen lépéseket szükséges megtenni, játsszunk egy egyszerű játékot: a ScraperWiki ablakodban próbálj meg magadnak egyéni utasításokat írni minden egyes olyan dologhoz, amit meg fogsz tenni, miközben megírod ezt adatkinyerő programot, egy receptben található lépésekhez hasonlóan (előtagként tégy minden egyes sor elé egy hash jelet (#), ez megmondja a Python-nak, hogy ez még nem az igazi számítógépes kód). Például:

# Keress meg minden sort a táblában
# Az Unicorn nem folyhat túl a bal oldalon.

Próbálj meg annyira pontos lenni, amennyire csak tudsz, és ne feltételezd azt, hogy a program mindent tud arról az oldalról, amelyről megpróbálsz adatot kinyerni.

Ha már leírtál némi kódszerűséget, hasonlítsd ezt össze az első scraper programodhoz szükséges kóddal:

import scraperwiki
from lxml import html

Ebben az első részben már meglévő funkciókat importálunk könyvtárakból – előre megírt kódrészletekből. A ScraperWiki segít nekünk abban, hogy weboldalakat töltsünk le, míg az lxml egy HTML-dokumentumok strukturált elemzésére szolgáló eszköz. Jó hír: ha a ScraperWikivel írsz Python-alapú adatkinyerő programot, akkor ez a két sor mindig ugyanaz lesz.

url = “http://www-news.iaea.org/EventList.aspx”
doc_text = scraperwiki.scrape(url)
doc = html.fromstring(doc_text)

Ezután a kód készít egy nevet (változó): url, és értékként hozzárendeli a NAÜ-oldal linkjét (url). Ez megmondja az adatkinyerő programnak, hogy ez a dolog létezik, és ezt szeretnénk figyelni. Ne feledd, hogy maga a link idézőjelek között van, mert nem a programkód része, hanem egy string, azaz karakterek sorozata.

Ezután az url változót egy függvény, a scraperwiki.scrape bemeneteként használjuk. Egy függvény bizonyos meghatározott feladatokat lát el, ebben az esetben egy weboldalt fog letölteni. Amikor ez készen van, akkor a kimenetét hozzá fogja rendelni egy másik változóhoz, a doc_text-hez. A doc_text most a weboldal tényleges szövegét fogja tárolni – nem a vizuális formát, amit a böngésződben látsz, hanem a forráskódot, amely az összes címkét tartalmazza. Mivel ezt a formátumot nem túl könnyű elemezni, egy másik függvényt, a html.fromstring-et fogjuk használni arra, hogy létrehozzon egy olyan különleges ábrázolási módot, ahol könnyen megjelölhetjük az elemeket, ez az úgynevezett dokumentum-objektummodell (DOM).

for row in doc.cssselect(“#tblEvents tr”):
link_in_header = row.cssselect(“h4 a”).pop()
event_title = link_in_header.text
print event_title

Ebben az utolsó lépésben a DOM-ot használjuk arra, hogy megtaláljuk az egyes sorokat a táblánkban, és kinyerjük az esemény címét a fejlécéből. Két új fogalmat használunk: a „for ciklust” és az elemkiválasztást (.cssselect). A for ciklus lényegében azt teszi, amire a neve is utal; végig fog haladni az elemek listáján, miközben mindegyikhez hozzárendel egy ideiglenes álnevet (ebben az esetben sort), majd lefuttat minden beljebb tagolt utasítást az egyes elemekre.

A másik új fogalom, az elemkiválasztás, különleges nyelvet használ arra, hogy elemeket találjon a dokumentumban. A CSS szelektorokat rendszerint arra használjuk, hogy elrendezési információkat adjunk a HTML-elemekhez és használhatók arra is, hogy pontosan kiválasszunk egy elemet egy oldalról. Ebben az esetben (a 6. sorban) kiválasztjuk a #tblEvents tr-szelektort, amely a táblaelemben lévő minden egyes <tr> elemet össze fog hasonlítani az ID tblEvents-szel (a hash egyszerűen az ID-t jelzi). Jegyezd meg, hogy ez <tr> elemek listáját fogja visszaadni.

Amint az a következő sorban látható  7. sor), ahol másik szelektort alkalmazunk arra, hogy megtaláljuk bármely <a> elemet (amely egy hiperhivatkozás) egy <h4> elemen (egy címen) belül. Itt csak egyetlen elemet szeretnénk megnézni (soronként csak egy cím van), így le ezt kell emelnünk a .pop() függvénnyel rendelkező szelektorunk által visszaadott lista tetejéről.

Ne feledd, hogy a DOM-ban lévő néhány elem tényleges szöveget tartalmaz, azaz olyan szöveget, amely nem része semmilyen jelölő nyelvnek, amelyekhez úgy férhetünk hozzá, hogy a 8. sorban látott [element].text szintaxist használjuk. Végül a 9. sorban kinyomtatjuk azt a szöveget a ScraperWiki konzoljára. Ha a futtatásra kattintasz az adatkinyerő programodban, a kisebb ablaknak el kellene indulnia, miközben felsorolja a NAÜ weboldalról származó eseményneveket.

58. ábra: így működik egy scraper (ScraperWiki)
58. ábra: így működik egy scraper (ScraperWiki)

Most egy egyszerű adatkinyerő programot láthatsz működés közben: ez letölti a weboldalt, átalakítja azt a DOM-formátumúra, majd lehetővé teszi számodra, hogy kiválassz és kinyerj bizonyos tartalmat. Ha adott ez a váz, megpróbálhatsz megoldani néhány fennmaradó problémát a ScraperWiki és a Python dokumentáció használatával:

  • Meg tudod találni az egyes események címéhez tartozó linkeket?
  • Ki tudod választani azt a kis szakaszt a CSS osztálynevének használatával, amely tartalmazza a dátumot és a helyet, és ki tudod nyerni az elem szövegét?
  • A ScraperWiki egy kis adatbázist kínál minden egyes adatkinyerő programhoz, így tárolhatod az eredményeket; kimásolhatod a releváns példát a dokumentációikból és alkalmazhatod, így fogod tudni lementeni az eseménycímeket, linkeket és dátumokat.
  • Az eseménylista sok oldalból áll; ki tudsz nyerni több oldalt, hogy a történelmi eseményeket is megkapd?

Miközben ezeken a kihívásokon dolgozol, nézz körül a ScraperWikin is: sok hasznos példa van a meglévő adatkinyerő programokban – és elég gyakran az adatok is nagyon izgalmasak. Ilyen módon nem kell a nulláról elkezdened a scraperedet: csak válassz ki egyet, amely hasonló, készíts egy saját másolatot belőle, és alkalmazd a problémádra.

Friedrich Lindenberg, Open Knowledge Foundation