Már volt szó korábban az API-k használatáról a New York Times és a Guardian adatai kapcsán. Az API (alkalmazásprogramozási interfész) egy olyan szabványosított felület, amin keresztül hozzá lehet férni egy másik program funkcióihoz – anélkül, hogy részletesen ismernünk kéne azok működését. Minket ez elsősorban a webes alkalmazások miatt érdekel : sok oldal lehetővé teszi, hogy megkerülve a webes felületet férjünk hozzá az adatokhoz, vagy akár interakcióba lépjünk velük (közismert példa a facebook-os alkalmazás).
A Wikipedia is szabadon hozzáférhető a web megkerülésével, és ez valójában mindenkinek jó: a fejlesztők pontosan olyan adatokat kapnak, amilyet kívánnak, a Wikipedia szervereinek pedig nem kell azon erőlködniük, hogy emberi fogyasztásra alkalmassá tegyék az adathalmazt (ezzel csökken a terhelés). A Wikipedia MediaWiki szoftveren fut, így az ő API-ját lehet használni (dokumentáció itt és itt ) Ez egy elég okos rendszer, mi csak a legegyszerűbb dolgot fogjuk megcsinálni: kiolvasunk egy oldalt, nyers szöveg formátumban (emlékezzünk, hogy a Wikipedia alapból formázott HTML-t ad).
Ez egy egyszerű HTTP híváson keresztül történik:
Az összes Wikipedián (így a magyaron is) az API-motor a fenti címen található (mutatis mutandis). A bűvös szó itt az action=raw paraméter, ami HTML helyett “nyers” szöveget szolgáltat. Csakhogy, a kapott nyers szöveg nem igazán nyers:
'''Elephants''' are large land [[mammal]]s in two [[Genus|genera]] of the [[family (biology)|family]]
Így ezt is tisztítani kell, azonban ez formátum sokkal egyszerűbb, mint egy HTML. Lássuk, hogyan valósítjuk meg python-ban a tisztítást:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import division | |
import re | |
import urllib2 | |
from urllib2 import HTTPError | |
import sys | |
def url_olvas(url): | |
opener = urllib2.build_opener() | |
opener.addheaders = [('User-agent', 'Mozilla/5.0')] | |
try: | |
infile = opener.open(url) | |
except HTTPError, e: | |
print e.code | |
exit() | |
page = infile.read() | |
sorok=re.split("\n",page) | |
page="<ujsor>".join(sorok) | |
return page | |
def wiki_olvas_main(args): | |
page=url_olvas("http://en.wikipedia.org/w/index.php?title="+args[1]+"&action=raw") | |
while True: | |
m=re.match("(.*?)\{\{.*?(\{\{.*?\}\}.*?){0,}\}\}(.*)",page) | |
if (m): page=m.group(1)+""+m.group(3) | |
else: break | |
page=re.sub("{.*?}","",page) | |
page=re.sub("<ref.*?>.*?</ref>","",page) | |
page=re.sub("\[\[File:(.*?)(\[\[.*?\]\].*?){0,}\]\]","",page) | |
page=re.sub("\[\[Image:(.*?)(\[\[.*?\]\].*?){0,}\]\]","",page) | |
while True: | |
m=re.match("(.*?)'''(.*?)'''(.*)",page) | |
if (m): page=m.group(1)+"<b>"+m.group(2)+"</b>"+m.group(3) | |
else: break | |
while True: | |
m=re.match("(.*?)''(.*?)''(.*)",page) | |
if (m): page=m.group(1)+"<i>"+m.group(2)+"</i>"+m.group(3) | |
else: break | |
while True: | |
m=re.match("(.*?)====(.*?)====(.*)",page) | |
if (m): page=m.group(1)+"<h4>"+m.group(2)+"</h4>"+m.group(3) | |
else: break | |
while True: | |
m=re.match("(.*?)===(.*?)===(.*)",page) | |
if (m): page=m.group(1)+"<h3>"+m.group(2)+"</h3>"+m.group(3) | |
else: break | |
while True: | |
m=re.match("(.*?)==(.*?)==(.*)",page) | |
if (m): page=m.group(1)+"<br><h2>"+m.group(2)+"</h2><br>"+m.group(3) | |
else: break | |
while True: | |
m=re.match("(.*)\[\[(.*?)\|(.*?)\]\](.*)",page) | |
if (m): page=m.group(1)+"<a href=\"http://en.wikipedia.org/wiki/"+m.group(2)+"\">"+m.group(3)+"</a>"+m.group(4) | |
else: break | |
while True: | |
m=re.match("(.*)\[\[(.*?)\]\](.*)",page) | |
if (m): page=m.group(1)+"<a href=\"http://en.wikipedia.org/wiki/"+m.group(2)+"\">"+m.group(2)+"</a>"+m.group(3) | |
else: break | |
page=re.sub("<ujsor>","\n",page) | |
print "<html><body><h1>" | |
print args[1] | |
print "</h1><br>" | |
print page | |
print "</body></html>" | |
wiki_olvas_main(sys.argv) |
A program HTML formátumban adja vissza a megtisztított szöveget (így jobban áttekinthetők a linkek, címek, stb). Ez természetesen a megfelelő részek egyszerű átírásával/törlésével pillanatok alatt átalakítható. A jelenlegi változat parancsorból, paraméterként olvassa be a kívánt oldalt, vagyis elindítani így tudjuk (linux parancssorból):
python wikiOlvas.py Humanities > eredmeny.html
Az url_olvas() funkció kizárólag a HTML kérést bonyolítja, míg a wiki_olvas_main() végzi a tisztítást. A fő program funkcióba szervezésének az oka csupán annyi, hogy így a kódot modulként is használhatjuk ( from wikiOlvas import * ).
A program tehát csak annyit csinál, hogy eltávolít a HTML kérésből beérkező adatokból minden “nem szöveg”-nek értékelt adatot (képeket, hivatkozásokat, stb.) Ezek jellemzően kapcsos vagy szögletes zárójelek közé vannak zárva. Az ilyen munkához a legjobb ötlet – szerintem – a reguláris kifejezések (regular expression) használata. Ezek legfőbb erőssége abban rejlik, hogy a “mit-cserélj-mire” jellegű kifejezések nagyon tág keretek között írhatók le (ezt használom például a linkek feldolgozásánál, ahol úgy kell kivenni egy részt a szövegfolyamból, hogy annak egy része mégis megmaradjon). Egyébként, reguláris kifejezések írása külön művészet, aminek az alapjaival mindenképpen érdemes megismerkedni, ha szövegekkel dolgozunk.
Kis programunk tehát megtisztítja az API-tól lekért “nyers” szöveget (és azt sem tökéletesen, mert a Wikipedia belső formázási szabályai is elég bonyolultak). Ennél az API persze sokkal többre képes: lekérhetünk egyszerre több oldalt is, számos formátumban (mondjuk, XML-ben), vagy akár API-n át bele is írhatunk a Wikipédiába. A mi programunk egyik érdekes, és elég könnyen megvalósítható fejlesztése lehet a linkeket összegyűjtő, majd azokon (rekurzívan) tovább haladó változat. Így gyűjthetünk sok-sok szöveget, számolhatunk hivatkozásokat, vagy akár rajzolhatunk hálókat az egymáshoz kapcsolódó témákról – amit csak nem szégyenlünk.
Az API csak örül, hisz éppen erre való.
Nincsenek megjegyzések:
Megjegyzés küldése