2. Rakendusliidesed
Õpiku teises peatükis räägiti enda arvuti failide lugemisest, aga alati ei pruugi vajalikud andmed olla enda failides olemas. Võibolla on vaja saada ajakohast infot muutuvate andmete kohta, näiteks ilmaennustused või valuutakursid. Võibolla on vaja midagi tõlkida Google Translate'iga, teha midagi Spotify andmetega, saada mingi sõna definitsioon või postitada midagi Twitterisse.
Sarnaselt lokaalsete failide lugemisega on võimalik lugeda veebilehti. Kõik veebilehed on justkui failid kellegi teise arvutis, mida veebilehitseja oskab graafiliseks liideseks teha. Suvaliste veebilehtede lugemine võib osutuda keeruliseks, aga Internetis on olemas palju selliseid lehti, mis on mõeldud programmidega lugemiseks. Neid nimetatakse rakendusliidestesks (ingl. k API ehk Application Programming Interface). Siin peatükis uurime, kuidas avada veebilehti nagu faile ja saada rakendusliidestelt andmeid.
Ettevalmistus
Enne jätkamist tuleb paigaldada moodul requests. Seda saab teha käsuga pip install requests
. Katsetamiseks kirjuta Pythonis import requests
. Kui erindit ei visata, on moodul paigaldatud. Kui ei ole kindel, kuidas mooduleid installida, siis on õpikus moodulite paigaldamise juhised.
Sellest peatükist arusaamiseks on vaja läbida õpiku esimesed 2 peatükki ning tutvuda 10. peatüki sõnastiku andmestruktuuriga.
Veebilehtede lugemine
Pythoniga veebilehtede lugemise teeb väga lihtsaks moodul requests
ja selle funktsioon get()
, mis tagastab päringu objekti. Selle päringu lähtekoodi sõnena saab kätte väljagae text
. Avame näiteks Tartu Ülikooli veebilehe ja väljastame selle lähtekoodi.
>>> import requests >>> päring = requests.get("https://ut.ee/") >>> päring.text '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML+RDFa 1.1//EN">\n<html lang="et"...'
Väljastatud HTML-kood ei ole kasutajale ega programmile hästi loetav. Pythoniga on võimalik HTML-koodi parsida kasutades mooduleid BeautifulSoup või lxml, aga siin me HTML-iga rohkem ei tegele. Vaatame hoopis rakendusliideseid, mis teevad programmidele andmete kättesaamise lihtsaks.
JSON-vorming
Et teha andmed programmile kergesti loetavaks, kasutavad paljud rakendusliidesed JSON-vormingut. See vorming lubab sõnedes hoida JavaScripti objekte (sealt nimi JavaScript Object Notation), mis on väga sarnased Pythoni sõnastikega.
Üks JSON objekt näeb välja selline:
tudeng = { "nimi": "Algo", "vanus": 19, "oskab_pythonit": true, "hobid": ["Python", "Netflix"] }
Requests moodul oskab sellised leheküljed lugeda Pythoni sõnastikeks meetodiga json()
.
Näiteks saab tudengi nime saab kätte koodiga tudeng["nimi"]
ja esimese hobi saab kätte koodiga tudeng["hobid"][0]
. Väärtusteks võib olla ka teine JSON-objekt ehk sõnastik. Milline näeks tudeng
välja siis, kui võtme "hinded"
all oleks sõnastik hinnetega? Kuidas siis saada kätte aine "Programmeerimine"
hinne?
Rakendusliideste pärimine
Leiame ühe rakendusliidese, mis tagastab JSON-vormingus informatsiooni ja proovime seda lugeda. Üks selline on näiteks https://exchangeratesapi.io/, mis annab meile praegused valuutakursid. Proovime kätte saada EUR/USD kursi.
>>> import requests >>> aadress = "https://api.exchangeratesapi.io/latest" >>> päring = requests.get(aadress) >>> vastus = päring.json() >>> vastus {'rates': {'CAD': 1.5623, 'HKD': 8.3849, 'ISK': 152.2, 'PHP': 55.593, 'DKK': 7.4731, 'HUF': 356.06, 'CZK': 27.606, 'AUD': 1.8635, 'RON': 4.8445, 'SEK': 11.1523, 'IDR': 17187.09, 'INR': 81.14, 'BRL': 5.6037, 'RUB': 86.9346, 'HRK': 7.608, 'JPY': 118.63, 'THB': 35.076, 'CHF': 1.0535, 'SGD': 1.5643, 'PLN': 4.5604, 'BGN': 1.9558, 'TRY': 7.0625, 'CNY': 7.6849, 'NOK': 12.3165, 'NZD': 1.8903, 'ZAR': 18.68, 'USD': 1.0801, 'MXN': 26.2955, 'ILS': 3.9802, 'GBP': 0.92985, 'KRW': 1364.14, 'MYR': 4.7686}, 'base': 'EUR', 'date': '2020-03-19'} >>> vastus["rates"]["USD"] 1.0801
Tihti on vaja päringuid täpsustada. Näiteks eelmises näites tagastati meile kõikide valuutade väärtused euro suhtes, aga kuidas täpsustada baasvaluutat? Nagu dokumentatsioon meile ütleb, tuleb pärida aadressi https://api.exchangeratesapi.io/latest?base=USD. See on tegelikult sama aadress mis enne, aga lisatud on parameeter "base"
väärtusega "USD"
.
Parameetreid saab manuaalselt aadressi taha küsimärgiga lisada, nagu on näidisaadressilt näha. Lihtsam on lisada parameetrite sõnastik päringule kaasa. Eriti siis, kui peab lisama mitu parameetrit või kui parameetrite väärtused sisaldavad sümboleid.
>>> import requests >>> aadress = "https://api.exchangeratesapi.io/latest" >>> parameetrid = {"base": "USD"} >>> päring = requests.get(aadress, params=parameetrid) >>> päring.url 'https://api.exchangeratesapi.io/latest?base=USD' >>> vastus = päring.json() >>> vastus["base"] 'USD' >>> vastus["rates"]["EUR"] 0.9258402
Proovi teha päring valuutakursside ajaloole: https://api.exchangeratesapi.io/history. Vaata dokumentatsioonist, millised parameetrid juurde lisama peab.
POST-päringud
Siiani oleme veebilehtede lugemisel tegelikult taustal teinud GET-päringuid. See on lihtsalt päring, mis annab veebilehele teada, et me tahame saada selle sisu. Neid kasutatakse siis, kui me ainult pärime ja tulemusena midagi ei muudeta. Kui serveris midagi muudetakse, kasutatakse POST-päringuid. POST-päringutega saadetakse veebilehtedele andmeid ilma, et neid aadressi taha lisatakse. Ka nende päringutega saadetakse üldiselt midagi vastu.
Lühendame näiteks internetiaadressi, kasutades teenust https://rel.ink/. Selle käigus tehakse serverisse kirje, et pikale aadressile vastab uus väiksem aadress, mille tõttu peab tegema POST-päringu. Rakendusliidese dokumentatsioonis on kirjas, et peab tegema POST-päringu aadressile https://rel.ink/api/links/ ja andma kaasa "url
" parameetriga aadressi, mida tahame lühendada.
>>> import requests >>> aadress = "https://rel.ink/api/links/" >>> andmed = {"url": "https://progeopik.cs.ut.ee/"} >>> päring = requests.post(aadress, data=andmed) >>> päring.json() {'hashid': '9mvm2g', 'url': 'https://progeopik.cs.ut.ee/', 'created_at': '2020-03-20T16:47:21.317166Z'}
https://rel.ink/9mvm2g viib nüüd aadressile https://progeopik.cs.ut.ee/.
Rakendusliideste nimekiri
Internetis leidub palju rakendusliideseid, mis tagastavad JSON-vormingus andmeid. Mõned näited:
- Valuutakursid: https://exchangeratesapi.io/
- Praegused kursid euro suhtes: https://api.exchangeratesapi.io/latest
- Internetiaadresside lühendamine: https://rel.ink/
- Juhuslik "yes" või "no" ja vastav gif: https://yesno.wtf/api
- Chuck Norrise naljad: https://api.chucknorris.io/
- Juhuslik nali: https://api.chucknorris.io/jokes/random
- Ilmaennustus (ilma Eestita): https://www.metaweather.com/api/
- Ilm Helsingis: https://www.metaweather.com/api/location/565346/
- Pokémonide andmed: https://pokeapi.co/
- Koeratõud ja nende pildid: https://dog.ceo/dog-api/documentation/
- Juhuslik pilt: https://dog.ceo/api/breeds/image/random
- Kasside faktid: https://alexwohlbruck.github.io/cat-facts/docs/
- Juhuslik fakt: https://cat-fact.herokuapp.com/facts/random
- Nimepäevad: https://api.abalin.net/documentation
- Tänased eesti nimepäevad: https://api.abalin.net/today?country=ee
Paljud rakendusliidesed ei ole avalikult kättesaadavad ning nõuavad autentimist, et päringuid piirata. Nende kasutamiseks peab registreerima kasutajaks ning iga päringuga kaasa saatma kasutajaga seotud võtme.
Mõned näited autentimisega rakendusliidestest:
- Sõnastik: https://developer.wordnik.com/
- Ilmaennustus OpenWeatherMap (Eestiga): https://openweathermap.org/api
- Google Translate: https://cloud.google.com/translate/docs/apis
- Spotify: https://developer.spotify.com/
Sellistele teenustele tehakse tavaliselt eraldi Pythoni moodulid, et neid oleks kergem kasutada:
- Sõnastik: wordnik-python
- OpenWeatherMap: pyowm
- Google Translate: googletrans
- Spotify: spotipy
- Twitter: python-twitter
- Facebook Messenger: fbchat
- Reddit: praw
Mahukad nimekirjad rakendusliidestest:
- https://github.com/public-apis/public-apis
- https://any-api.com/
- https://apilist.fun/
- https://public-apis.xyz/
Enesekontrolliküsimused
Ülesanded
Ülesanne 1
Kirjuta valuutakalkulaator, kuhu sisestatakse nii baasvaluuta, soovitud valuuta ja raha kogus.
Näide:
>>> %Run valuutaarvutaja.py Sisesta baasvaluuta: GBP Sisesta teine valuuta: IDR Sisesta kogus: 1 1 GBP on väärt 18262.95 IDR
Ülesanne 2
Kirjuta programm, mis küsib kasutajalt sisendit, kasutab mõnda huvitavat rakendusliidest ning väljastab vastavalt sisendile rakendusliidesest saadud infot.