Wikipédia:Pywikibot/A Pywikibot interaktív használata

Tudnivalók

A Pywikibot keretrendszert alapvetően a kész scriptek futtatására vagy saját scriptek fejlesztésére használhatjuk, de van egy érdekes interaktív használati módja is. Ez alkalmi feladatok megoldására lehet hasznos olyanoknak, akik jártasak a Python programozási nyelvben, és kicsit mélyebben ismerik a keretrendszert. Akkor érdemes ehhez a módszerhez folyamodni, ha a kódot nem szándékozunk újrahasznosítani, illetve ki akarjuk használni a felület interaktivitását a kísérletezéshez.

  • Tartsd szem előtt, hogy ez itt nem egy mindenre kiterjedő leírás, csak egy esettanulmány, amiből ihletet nyerhetsz.
  • Mivel az interaktív használat célja a gyors barkácsmunka, ezek a hevenyészett utasítások nem követik a PEP8-at vagy más formai útmutatót, nem a kód szépsége volt a lényeg, hiszen csak egyszeri használatra készült. A szóközöket azért kitettem, hogy olvashatóbb legyen.
  • A kódhoz vezető kísérletek itt nem láthatóak, csak az eredmény. Természetesen hazugság lenne azt állítani, hogy a sorok ilyen letisztultan pattantak ki egymás után a szerző fejéből, a tesztkiírásokat mellőztem, hogy a lényeg látsszék.

Előkészületek szerkesztés

  • Feltételezzük, hogy van egy telepített Pywikibot-példányod, és botként be vagy jelentkezve benne.
  • Állj abba a könyvtárba (pl. Total Commanderrel), ahova a botot telepítetted.
  • Innen indíts el egy Python-értelmezőt (pl. egy parancssori ablakban add ki a python parancsot, vagy indítsd el az IDLE-t).

A sorok elején álló >>> jeleket a Python akkor jeleníti meg, ha új parancsot vár, a ... jeleket pedig akkor, ha egy be nem fejezett parancs folytatását. A végén üres enterrel tudjuk jelezni, hogy kész a ciklus vagy a függvény.

A feladat szerkesztés

Olvassuk be a Kategória:Magyar vonatkozású kisbolygók cikkeit, és határozzuk meg a kisbolygók névadóját, majd hozzuk létre ezekből a cikkekből a Kategória:Magyarok, akikről kisbolygót neveztek el kategóriát!

A megoldás szerkesztés

A megoldás a Pywikibot 2023 elején aktuális 8.0.0 verziójában készült. Mivel menet közben sokat kell kézzel javítgatni, az interakciót választjuk. Az feltűnik, hogy az infoboxban megjelenő névadó általában nem az oldal szövegéből, hanem a Wikidatából jön, de nem minden esetben. Ezért ahol lehet, onnan vesszük a nevet, de ebből néhány esetben átirányítás lesz.

Előkészületként létrehozzuk a kategóriánkat reprezentáló objektumot:

>>> import pywikibot as p
>>> site = p.Site()
>>> cat = p.Category(site, 'Magyar vonatkozású kisbolygók')

Végigmegyünk a kategória lapjain, és keressük a P138 (névadó) tulajdonság értékét. A próbák azt mutatják, hogy nem mindig van ilyen, ilyen esetben kiírjuk a lap címét kézi feldolgozásra. Ha van névadó magyar címkével, akkor hozzáfűzzük a készülő lapunk szövegéhez.

>>> text = ''
>>> for m in cat.members():
...   claim = m.get_best_claim('P138')
...   try:
...     item = claim.getTarget()
...   except AttributeError:
...     print(m.title())
...     continue
...   try:
...     hu = item.labels['hu']
...     text += '* [[' + hu + ']]\n'
...   except KeyError:
...     pass
...

A kész szöveget kiírhatjuk egy lapra:

>>> page = p.Page(site, 'user:BinBot/try')
>>> page.put(text, 'Magyarok, akikről kisbolygót neveztek el')

Íme, az eredmény. Most jön a kézi munka, némi Excel-támogatással: nem emberről szóló lapok és duplikátumok törlése, átirányítások, egyértelműsítések javítása. Közben hozzáadjuk azokat a kisbolygókat a laphoz, amelyekhez nem találtunk névadót a Wikidatán, és ezért kiírtuk a címüket a képernyőre. A legegyszerűbb a Pythont hívni segítségül (habár kiírhattuk volna rögtön ebben a formátumban is):

>>> text = """
... 14181 Koromházi
... 68144 Mizser
... 72071 Gábor
... 73511 Lovas
... 75555 Wonaszek
... 75823 Csokonai
... 82656 Puskás
... # Van még jó sok, de rövidítettem, hogy a lényeget lássuk.
.... """
newtext = ['* [[' + s + ']]\n' for s in text.split('\n')]
>>> for sor in newtext:
...   print(sor)
...

Ezekhez manuálisan kell nevet keresni. Amikor végül elkészült a listánk, és van több mint 150 cikk rajta, kiléphetünk az interaktív környezetből, és használjuk a Pywikibot category scriptjét a kategóriák hozzáadásához:

python pwb.py category add -links:user:BinBot/try

A script indítés után fogja kérni a hozzáadandó kategória nevét.

Elavult példa szerkesztés

Az itt látható kód a ma már nyugdíjazott compat (leánykori nevén trunk) verzióban készült. A most támogatott core verzióban értelemszerű módosításokkal használható. Például import wikipedia helyett import pywikibot kellene az elejére. A gondolatmenetet mutatja.

A feladat szerkesztés

A Szerkesztő:Bináris/Kék és zöld görög katolikusok oldalon fel van sorolva egy csomó cikk címe #[[Cím]] alakban. Írjuk oda mindegyik után zárójelben a lapra mutató hivatkozások számát!

A megoldás szerkesztés

>>> import wikipedia as w # Interaktív használathoz kényelmesebb egy betű, mint egy beszédes szép név.

'''Ez a három sor az alapeljárás, ahogy az alapértelmezett wikinkből megszerezhetjük egy cikk szövegét:'''
>>> site = w.getSite()
>>> p = w.Page(site, u'Szerkesztő:Bináris/Kék és zöld görög katolikusok')
>>> text = p.get()

'''
A bot kódját böngészve megtudhatjuk, hogy a Page objektum getReferences() metódusa sorolja fel a lapra hivatkozó más lapokat.
Sajnos ez egy generátor, aminek nincs mérete, ezért egy iskolás megszámlálási tétellel gyorsan összeütünk egy rn (refnumber) függvényt a hivatkozó lapok számának meghatározására. Persze aki zsonglőrködni akar, ezt meg is „spórolhatná” a lenti ciklusban egy lambdafüggvénnyel, de a legtöbb embernek valószínűleg gyorsabb ezzel az „álmunkból felverve is” módszerrel.
'''
>>> def rn(p):
...   i = 0
...   for x in p.getReferences():
...     i += 1
...   return i
...

'''
Szükségünk lesz egy reguláris kifejezésre, hogy kinyerjük a címeket.
A mintán belül zárójelezzük a keresett tartalmat, az lesz a group(1), míg a teljes megtalált string a #[[...]] csomagolással együtt a group(0) vagy röviden group(). Az u betűt megszokásból teszem ki, itt nincs jelentősége.
'''
>>> import re
>>> r = re.compile(ur'#\[\[(.*?)\]\]')

'''
Most egy ciklussal végigmegyünk a lap szövegében található címeken. A group(1) a listázott cím, amihez kreálunk egy lapobjektumot, és az előbb definiált rn függvénnyel meghatározzuk a rá mutató hivatkozások számát. Egyet levonunk, mert maga ez a lap, ahova a listát írtuk, nem érdekel.
Ezután egy szövegcserével zárójelben a felsorolt cím mögé írjuk a keresett számot. Ehhez nem reguláris kifejezést használunk, mert itt már nem a minta összes előfordulását keressük, hanem a konkrét megtalált címet.
'''
>>> for t in r.finditer(text):
...   cim = t.group(1)
...   pp = w.Page(site, cim)
...   num = rn(pp) - 1
...   old = t.group()
...   new = old + (" (%d)" % num)
...   text = text.replace(old, new)
...

'''
Végül elmentjük. A mentés a bejelentkezett bot nevében történik. Válaszként meglepően sok üzenetet kapunk, amit a scriptek el szoktak nyomni.
''''
>>> p.put(text, u'Hivatkozások száma')
Updating page [[Szerkesztő:Bináris/Kék és zöld görög katolikusok]] via API
(302, 'OK', {u'pageid': 1467324, u'title': u'Szerkeszt\u0151:Bin\xe1ris/K\xe9k \xe9s z\xf6ld g\xf6r\xf6g katolikusok', u'newtimestamp': u'2017-05-09T13:35:23Z', u'contentmodel': u'wikitext', u'result': u'Success', u'oldrevid': 18726976, u'newrevid': 18728308})

Erre igazán kár lett volna programot fejleszteni! Legközelebb valami más feladat lesz, de hasonló eszközökkel oldhatjuk meg.

Az eredmény szerkesztés

 

További felhasználási ötletek szerkesztés