Wikiprojekti:Avoin kulttuuridata hyötykäyttöön/Botin ohjelmoiminen

Wikipediasta
Siirry navigaatioon Siirry hakuun

Botin luominen Porin taidemuseon tarpeisiin[muokkaa | muokkaa wikitekstiä]

Botit ovat yksi tapa hakea tai muokata Wikidata-sivuston tai myös vaikkapa Wikipedia-sivuston tietoja. Muita tapoja ovat esimerkiksi jonkin web-työkalun käyttö tai käsin tietojen muokkaaminen suoraan Wikidata-sivustolle. Botti on hyödyllinen, jos jokin tehtävä pitää tehdä usein tai se on erityisen suuri töinen ja botti ei tarvitse juurikaan tai lainkaan ihmisen ohjausta.

Wikidata-sivustoa varten botin voi ohjelmoida periaatteessa millä tahansa ohjelmointikielellä ja hyödyntää esimerkiksi MediaWikin ohjelmointi-rajapintaa eli API:a (Aplication Programming Interface). Käytännössä kuitenkin botti kannattaa yleensä ohjelmoida jonkin ohjelmointikehyksen päälle. Tällä oppitunnilla näytetään miten botti rakennetaan Pywikibot (core) -kehyksen päälle. Pywikibot on mm. siksi hyvä kehys, että se tarjoaa helpon tavan noudattaa bot-käytäntöjä ja API-etikettiä. Pywikibotin päälle ohjelmat toteutetaan Python-ojelmointikielellä, joten tämä oppitunti olettaa, että Python-ohjelmointikieli on ainakin jossakin määrin tuttu. Tämän oppitunnin koodi on Pythonin 3 -versiolla kokeiltua.

Pywikibot -asentaminen[muokkaa | muokkaa wikitekstiä]

Ennen Pywikibotin asennusta on syytä luoda bottia varten oma wiki-tunnuksensa, jonka luomisen osalta on oma ohjeensa: https://www.wikidata.org/wiki/Wikidata:Bots#Bot_accounts

Pywikibotin asentamiseen on myös hyvät omat ohjeensa: Manuaali:Pywikibot/Asennus. Ohjeen Pywikibotin konfigurointi -kohdassa kannattaa kuitenkin huomata, että kun ajat komennon python pwb.py login, niin valitse ensimmäisellä kerralla perhettä (family) kysyttäessä 'wikidata' ja kieltä kysyttäessä 'test'. Tämä lisää test.wikidata.org-sivuston botti-kokeiluja varten Pywikibotin asetuksiin. Botin testaaminen huolella ennen oikeaa käyttöä on erittäin tärkeää ja test.wikidata.org-sivusto mahdollistaa yhden tavan testata botin toimintaa. Käyttäjätunnukseksi anna edellä bottia varten luomasi käyttäjätunnus. Kun haluat botin tulevaisuudessa tekevän myös muokkauksia www.wikidata.org-sivustolle, niin kysyttäessä muiden projektien lisäämisestä ("Do you want to add any other projects? ([y]es, [N]o)"), vastaa kyllä ja tällä ketaa perheeksi edelleen 'wikidata', mutta kieltä kysyttäessä nyt myös 'wikidata'. Käyttäjätunnus on sama kuin test.wikidata.org-sivuston kanssa.

Yksinkertaisen skriptin kirjoittaminen[muokkaa | muokkaa wikitekstiä]

Pywikibotin skriptit kirjoitetaan Pywikibotin scripts-hakemistoon ja ne ajetaan komentoikkunassa Pywikibotin asennushakemistosta komennolla python pwb.py [skriptin nimi]. Kirjoita haluamallasi tekstieditorilla (esim. Notepad++ tai Emacs) seuraava sisältö tiedostoon 'simple_script.py':

#!/usr/bin/python3

import pywikibot

site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, u"Q18658728")
pywikibot.output(item.title())
item.get()
pywikibot.output(item.labels['en'])

Aja skripti python pwb.py simple_script. Komentoikkunaan tulostuu:

Q18658728
Eetu Salin

Skriptissä ensiksi luodaan site-muuttuja, jolla määrätään että tietoja haetaan www.wikidata.org-sivustolta. Seuraavalla rivillä repo = site.data_repository() luodaan repo-muuttuja, jota käytetään esimerkiksi Wikidatan kohteiden hakemiseen. Jos käytettävä sivusto olisi esimerkiksi Wikipedia, niin repo-muuttujaa ei tarvittaisi vaan sivuja voitaisiin hakea suoraan site-muuttujan avulla. Rivillä item = pywikibot.ItemPage(repo, u"Q18658728") sitten haetaankin yksi kohde, jonka ID on "Q18658728". Tulostus skripteistä tulisi tehdä pywikibot.output()-metodilla. Haetun Wikidatan kohteen "otsikon" eli ID tulostetaan rivillä pywikibot.output(item.title()). Kun haluat hakea tarkempia tietoja kohteesta, niin ennen niiden hakemista pitää kutsua item.get() -metodia. Tämän jälkeen esimerkiksi kohteen englanninkielisen nimen hakeminen ja tulostus tapahtuu kuten koodissa rivillä pywikibot.output(item.labels['en']) tapahtuu.

Tämä yksinkertainen skripti sisälsi monta oleellista perusasiaa Wikidata-skriptien toteutukseen liittyen. Seuraavassa kohdassa luot skriptin, joka hakee ja tulostaa paljon erilaista tietoa Wikidata-kohteista.

Wikidata-kohteiden tietojen hakeminen botilla[muokkaa | muokkaa wikitekstiä]

Kannattaa katsoa myös hyvä Wikidata:Pywikibot - Python 3 Tutorial/Data Harvest-tutoriaali.

Luo explore_wikidata.py -tiedosto ja kirjoita siihen seuraava sisältö:

#!/usr/bin/python3

import pywikibot

site = pywikibot.Site("wikidata", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, u"Q18658728") # Eetu Salin

pywikibot.output(item)
pywikibot.output(item.title())
item_dict = item.get()
pywikibot.output(item_dict)
pywikibot.output(item.text)
pywikibot.output(item.properties())
pywikibot.output(item_dict.keys())
pywikibot.output(item_dict['claims'])
pywikibot.output(item.claims)
pywikibot.output(item.claims.keys())
pywikibot.output(item.claims['P577'])
pywikibot.output(item.claims['P577'][0])
pywikibot.output(item.claims['P577'][0].id)
pywikibot.output(item.claims['P577'][0].type)
pywikibot.output(item.claims['P577'][0].qualifiers)
pywikibot.output(item.claims['P577'][0].sources)
pywikibot.output(item.claims['P577'][0].getTarget())
pywikibot.output(item.claims['P577'][0]._formatValue())
pywikibot.output(item.claims['P577'][0].toJSON())

property_page = pywikibot.PropertyPage(repo, 'P625')
pywikibot.output("property P625 type: " + property_page.getType())
property_page.get()
pywikibot.output("property P625 English labels: " + property_page.labels['en'])

Kun ajat skriptin python pwb.py explore_wikidata, niin komentoikkunaan tulostuu paljon erilaista tietoa ensiksi yhdestä Wikidata-kohteesta ja sen jälkeen vielä pari asiaa yhdestä Wikidata-ominaisuudesta. Mitä yhteneväisyyksiä huomaat joillakin tulostuksilla? Olisiko vielä muita mahdollisuuksia saada tulostettuja tietoja (vinkki tutustu edellä mainittuun Wikidata:Pywikibot - Python 3 Tutorial/Data Harvest-tutoriaaliin)?

Tietojen hakeminen on toki hyödyllistä, mutta tietojen muokkaaminen botilla on ehkä vielä tärkeämpi asia, joten seuraava kohta käsitteleekin kohteiden muokkaamista.

Wikidata-kohteiden muokkaaminen botilla[muokkaa | muokkaa wikitekstiä]

Kuten edellä jo mainittiin, on muokkauksessa erittäin tärkeää ottaa huomioon bot-käytännöt ja API-etiketti ja eri Wikeillä on luonnollisesti omia käytäntöjään. Ennen kuin muokkauksia tekee oikeille Wikidata-kohteille, niin on koodi mm. testattava huolellisesti. Testaukseen voi käyttää esimerkiksi tämän kohdan esimerkissäkin hyödynnettettävää test.wikidata.org-sivustoa, jonka kohteita voi muokata vapaasti. Lisäksi varsinaisella www.wikidata.org-sivustolla on kolmekin hiekkalaatikkoa, joihin voi tehdä lisäyksiä kokeilumielessä (Wikidata Sandbox, Second Wikidata sandbox, Third sandbox). Periaatteessa myös Wikidata-ohjelmiston (tai ehkä oikeammin Wikibase-ohjelmiston) voi asentaa omalle tietokoneelle ja hakea Wikidatassa olevat tiedot oman tietokoneen tietokantaan. Käytännössä tämä vaihtoehto voi kuitenkin olla hankala toteuttaa mm. tältä osin dokumentaation laadun takia ja myös tietokannan koon vuoksi.

Tällä oppitunnilla luot skriptin, joka lisää test.wikidata.org -sivuston yhdelle kohteelle koordinaatit, jos kohteella ei niitä jo ole. Kohteiden muokkauksen osalta kannattaa tutustua myös esimerkiksi Projekt:Botacademy 2015/Pywikibot part 2-ohjeisiin, Wikidata:Pywikibot - Python 3 Tutorial-ohjeisiin ja useisiin esimerkkeihin sivulla Wikidata:Creating a bot.

Luo edit_item_coords.py -tiedosto ja kirjoita siihen seuraava sisältö:

#!/usr/bin/python3

import pywikibot

site = pywikibot.Site("test", "wikidata")
repo = site.data_repository()
item = pywikibot.ItemPage(repo, "Q2228")

if item.exists():
        # Property P125 defines coordinate location on test.wikidata.org site
        if 'P125' in item.claims:
                pywikibot.output("Coordinates already defined")
                pywikibot.output(item.claims['P125'][0].type)
                pywikibot.output(item.claims['P125'][0].getTarget())
        else:
                pywikibot.output("Adding coordinates")
                claim = pywikibot.Claim(repo, 'P125')
                target = pywikibot.Coordinate(61.473103, 21.781216, precision=0.0001)
                claim.setTarget(target)
                item.addClaim(claim)

Koodissa on paljon ennestään tuttua. Uusi osuus on neljällä viimeisellä rivillä. Ensiksi rivillä claim = pywikibot.Claim(repo, 'P125') luodaan uusi väite-muuttuja. Väitehän on osa kohteen yhtä esitystä (ks. Wikipedia:Wikiprojekti Avoin kulttuuridata hyötykäyttöön/Käsitteistö ja Wikidata:Introduction). Tässä tapauksessa väitteeseen liittyvän ominaisuuden ID on P125, joka määrittelee koordinaattisijainnin. Sivustolla www.wikidata.org vastaavan ominaisuuden ID olisi P625. Näiden kahden sivuston ominaisuuksien ja kohteiden ID:t ovat siis yleensä erilaisia, koska test.wikidata.org-sivusto sisältää kohteita ja ominaisuuksia paljon vähemmän. Saatat myös joutua itse lisäämään kohteita ja ominaisuuksia test.wikidata.org-sivustolle testausta varten.

Rivillä target = pywikibot.Coordinate(61.473103, 21.781216, precision=0.0001) luodaan koordinaatti-muuttuja, joka asetetaan seuraavalla rivillä claim.setTarget(target) väitteen kohteeksi. Vasta viimeisellä rivillä item.addClaim(claim) muutos viedään test.wikidata.org-sivustolle. Skriptiä ajaessa on myös mahdollista, että komentoikkunaan tulostuu "Sleeping for X.Y seconds". Tämä tarkoittaa sitä, että Pywikibot rajoittaa test.wikidata.org-sivustolle aiheutuvaa taakkaa eli huolehtii puolestasi asiasta.

Edellinen väitteen lisääminen on yksi tapa muokata kohteita. Esimerkiksi Wikipedia linkkien ja kohteen nimen muokkaaminen tapahtuvat hieman toisin. Niistä on kuitenkin hyviä esimerkkejä em. mainituilla sivuistoilla ja myös seuraavan kohdan botti käyttää erilaisia tapoja kohteiden muokkaamiseen.

Porin julkisen taiteen tietoja wikidata.org-sivuille[muokkaa | muokkaa wikitekstiä]

Porin taidemuseolla on ollut tarve saada alueen julkisista veistoksista tiedot Wikidata-tietokantaan. Sieltä tietoja voi sitten edelleen näyttää esimerkiksi Wikipedia-sivuilla tai hyödyntää missä tahansa tietoja tarvitsevassa sovelluksessa, koska tieto on avointa. Porin julkisen taiteen tietoja on tällä hetkellä tallennettu paitsi Wikidata-kohteiksi, niin myös osittain Google-taulukkoon. Kaiken veistoksia koskevan tiedon Wikidataan vieminen on käsin erittäin työlästä vaikka kohteita ei olekaan kuin reilu 40. Tässä oppitunnin kohdassa näytetään miten tietojen vientiä helpottamaan voidaan toteuttaa botti.

Esimerkki-skripti löytyy GitHubista. Jos ajat skriptin, niin huomaa muokata sitä niin, että muokkaukset tapahtuvat test.wikidata.org-sivustolle. Skripti on Pywikibotin toiminnallisuuksien osalta jo sinulle pitkälti tuttu. Uusia asioita voi olla Pythonin erilaisten kirjastojen hyödyntäminen. Näistä saa hyvin tietoa virallisesta Python-dokumentaatiosta, Requests-kirjaston dokumentaatiosta ja vaikkapa csv-kirjaston osalta Using the CSV module in Python -tutoriaalista. Tässä käymme tarkemmin läpi ne skriptin ominaisuudet, jotka liittyvät Pywikibotin käyttöön ja joita ei ole vielä edellä käyty läpi.

Kuten skriptiä tutkimalla huomaat, luetaan em. mainitun Google-taulukon tiedot rivi kerrallaan läpi. Mikäli taulukon rivin patsaasta on jotakin tietoa Wikidatassa eli kunkin taulukon rivin ensimmäisellä sarakkeella on linkki Wikidata-kohteeseen, niin skriptissä verrataan taulukon rivin tietoja Wikidata-kohteen tietoihin ja lisätään puuttuvia tietoja Wikidataan. Skritpi ei luo uusia kohteita, mutta sekin olisi toki mahdollista ainakin Wikimedia API:a käyttämällä.

Osa taulukon kohdelinkeistä ohjataan Wikidata-sivustolla toiselle sivulle. Sen takia skriptissä on kohta:

if item.isRedirectPage():
    item = item.getRedirectTarget()

Koordinaatit lisäävä skriptin osa on jo edeltä tuttu. Sen jälkeen on kommentoitu pois osuus, jolla lisättäisiin kohteille "instance of" (P31) -ominaisuudet "public art" (Q557141) ja "sculpture" (Q860861). Näitä ei lisätä, koska skriptin toteuttaja on halunnut välttää mahdollisen väärän tiedon lisäämisen kohteille. Seuraavaksi lisätään maatieto ennestään tutulla tavalla. Sitten on taas skriptin osuus kommentoitu pois, jolla lisättäisiin publication date (P577) -ominaisuus. Tämä osa on kommentoitu pois samasta syystä kuin aiempi skriptin osuus eli on haluttu välttää mahdollisen väärän tiedon lisääminen Wikidataan.

Wikipedia-linkin lisääminen tapahtuu rivillä:

item.setSitelink(sitelink={'site': 'fiwiki', 'title': page_title}, summary=u'Set sitelink')

Koska Google-sheetin linkit ovat suomenkieliseen Wikipediaan, annetaan site-parametrille arvo fiwiki. Englanninkielisen Wikipedian tapauksessa parametrin arvo olisi enwiki. Parametrin title arvo on parsittu Google-sheetin linkistä edellä olevassa koodissa korvaamalla "_"-merkit välilyönneillä ja korvaamalla koodinvaihtomerkit unicode-merkeillä.

Suomenkielisen nimen lisääminen tapahtuu rivillä:

item.editLabels(labels={'fi': row[3]}, summary=u'Add Finnish label')

Parametrin fi-arvo saadaan siis taulukon kunkin rivin neljänneltä eli NIMI-sarakkeelta.

Uusin asia on skriptin lopussa, jossa käytetään ns. sivu-generaattoria (page generator). Sivu-generaattorit ovat Pywikibotin tapa tarjota pääsy suureen määrään sivuja eli Wikidatan tapauksessa kohteita. Tässä skriptissä tosin sivu-generaattoria on käytetty hieman epätyypillisesti, koska sillä koitetaan hakea vain yksi Wikidata-kohde eli veistoksen tekijä, joka on annettu Google-taulukon kunkin rivin viidennellä sarakkeella. Skriptin kohta on seuraava:

gen = WikibaseSearchItemPageGenerator(row[4], language="fi", site=site)
    if gen:
        items = list(enumerate(gen))
        if len(items) == 1:
            pywikibot.output(u'adding creator claim')
            item_id = items[0][1].title()
            addItemClaim(item, creator_property, item_id)

WikibaseSearchItemPageGenerator on sivu-generaattori, jolla voidaan etsiä Wikidata-sivuja kohteen nimen perusteella eli tässä tapauksessa kohteita haetaan tekijä-tiedon eli Google-taulukon kunkin rivin viidennen sarakkeen perusteella. Muuttuja gen sisältää haun tulokset ja gen-muuttujan arvot tyypillisesti käytäisiin silmukassa läpi. Tässä kuitenkin ollaan kiinnostuneita tuloksesta vain, jos niitä on yksi. Tämän takia koodissa tarkistetaan, että tuloksia on vain yksi ja jos näin on, niin vuorossa olevan taulukon rivin Wikidata-kohteelle lisätään gen-muuttujan sisältämän tekijä-kohteen tieto. Kohde-tiedon lisääminen tapahtuukin taas ennestään tutulla tavalla.

Olet nyt saanut peruskäsityksen botin ohjelmoimisesta Pywikibottia hyödyntäen. Sinulla on myös tietämystä botteihin liittyvästä etiikasta ja käytännöistä. Lisäksi olet oppinut miten voit botin avulla hakea ja kirjoittaa tietoja Wikidata-sivustolla.

Onneksi olkoon! Suoritit menestyksekkäästi oppitunnin Botin ohjelmoiminen!!

Huomioitavaa Pywikibotin käytöstä[muokkaa | muokkaa wikitekstiä]

Pywikibotin API-dokumentaatio:n ja alla olevien linkkien lisäksi kannattaa Pywikibotiin tutustuessa tutkia sen lähdekoodeja. Esimerkiksi Linuxissa komennolla grep -rn Coordinate . selviää, että Coordinate-luokka on määritelty tiedostossa "__init__.py", jota tutkimalla selviää ko. luokan tarkempi toiminnallisuus.

Yleistä:

Teknistä tietoa:

Art hacking: