!!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 [[https://2.python-requests.org/en/master/ | 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 [[https://progeopik.cs.ut.ee/osa1.html | moodulite paigaldamise juhised]].

Sellest peatükist arusaamiseks on vaja läbida õpiku esimesed 2 peatükki ning tutvuda 10. peatüki [[https://progeopik.cs.ut.ee/10_andmestruktuurid.html#sonastikud | 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.

(:codestart python gutter='false':)
>>> 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"...'
(:codeend:)

Väljastatud HTML-kood ei ole kasutajale ega programmile hästi loetav. Pythoniga on võimalik HTML-koodi parsida kasutades mooduleid [[https://www.crummy.com/software/BeautifulSoup/bs4/doc/ | BeautifulSoup]] või [[https://lxml.de/ | 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 [[https://progeopik.cs.ut.ee/10_andmestruktuurid.html#sonastikud | sõnastikega]]. 

Üks JSON objekt näeb välja selline:

(:codestart python gutter='false':)
tudeng = {
    "nimi": "Algo",
    "vanus": 19,
    "oskab_pythonit": true,
    "hobid": ["Python", "Netflix"]
}
(:codeend:)

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/ | https://exchangeratesapi.io/]], mis annab meile praegused valuutakursid. Proovime kätte saada EUR/USD kursi. 

(:codestart python gutter='false':)
>>> 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
(:codeend:)

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 | 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.

(:codestart python gutter='false':)
>>> 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
(:codeend:)

Proovi teha päring valuutakursside ajaloole: [[https://api.exchangeratesapi.io/history | 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/ | 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/ | https://rel.ink/api/links/]] ja andma kaasa "@@url@@" parameetriga aadressi, mida tahame lühendada.

(:codestart python gutter='false':)
>>> 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'}
(:codeend:)

[[https://rel.ink/9mvm2g | https://rel.ink/9mvm2g]] viib nüüd aadressile [[https://progeopik.cs.ut.ee/ | https://progeopik.cs.ut.ee/]]. 

!!!Rakendusliideste nimekiri
Internetis leidub palju rakendusliideseid, mis tagastavad JSON-vormingus andmeid. Mõned näited:

* Valuutakursid: [[https://exchangeratesapi.io/ | https://exchangeratesapi.io/]]
** Praegused kursid euro suhtes: [[https://api.exchangeratesapi.io/latest | https://api.exchangeratesapi.io/latest]] 
* Internetiaadresside lühendamine: [[https://rel.ink/ | https://rel.ink/]]        
* Juhuslik "yes" või "no" ja vastav gif: [[https://yesno.wtf/api | https://yesno.wtf/api]]
* Chuck Norrise naljad: [[https://api.chucknorris.io/ | https://api.chucknorris.io/]]
** Juhuslik nali: [[https://api.chucknorris.io/jokes/random | https://api.chucknorris.io/jokes/random]]
* Ilmaennustus (ilma Eestita): [[https://www.metaweather.com/api/ | https://www.metaweather.com/api/]]
** Ilm Helsingis: [[https://www.metaweather.com/api/location/565346/ | https://www.metaweather.com/api/location/565346/]]
* Pokémonide andmed: [[https://pokeapi.co/ | https://pokeapi.co/]]
** Pikachu: [[https://pokeapi.co/api/v2/pokemon/pikachu | https://pokeapi.co/api/v2/pokemon/pikachu]] 
* Koeratõud ja nende pildid: [[https://dog.ceo/dog-api/documentation/ | https://dog.ceo/dog-api/documentation/]]
** Juhuslik pilt: [[https://dog.ceo/api/breeds/image/random | https://dog.ceo/api/breeds/image/random]]
* Kasside faktid: [[https://alexwohlbruck.github.io/cat-facts/docs/ | https://alexwohlbruck.github.io/cat-facts/docs/]]
** Juhuslik fakt: [[https://cat-fact.herokuapp.com/facts/random | https://cat-fact.herokuapp.com/facts/random]] 
* Nimepäevad: [[https://api.abalin.net/documentation | https://api.abalin.net/documentation]] 
** Tänased eesti nimepäevad: [[https://api.abalin.net/today?country=ee | 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/ | https://developer.wordnik.com/]]
* Ilmaennustus OpenWeatherMap (Eestiga): [[https://openweathermap.org/api | https://openweathermap.org/api]]
* Google Translate: [[https://cloud.google.com/translate/docs/apis | https://cloud.google.com/translate/docs/apis]]
* Spotify: [[https://developer.spotify.com/ | https://developer.spotify.com/]] 

Sellistele teenustele tehakse tavaliselt eraldi Pythoni moodulid, et neid oleks kergem kasutada: 

* Sõnastik: [[https://github.com/wordnik/wordnik-python | wordnik-python]]
* OpenWeatherMap: [[https://github.com/csparpa/pyowm | pyowm]]
* Google Translate: [[https://pypi.org/project/googletrans/ | googletrans]]
* Spotify: [[https://spotipy.readthedocs.io/en/latest/ | spotipy]]
* Twitter: [[https://python-twitter.readthedocs.io/en/latest/ | python-twitter]]
* Facebook Messenger: [[https://fbchat.readthedocs.io/en/stable/ | fbchat]]
* Reddit: [[https://praw.readthedocs.io/en/latest/ | praw]]

Mahukad nimekirjad rakendusliidestest:

* [[https://github.com/public-apis/public-apis | https://github.com/public-apis/public-apis]] 
* [[https://any-api.com/ | https://any-api.com/]]
* [[https://apilist.fun/ | https://apilist.fun/]] 
* [[https://public-apis.xyz/ | https://public-apis.xyz/]]

!!!Enesekontrolliküsimused
(:includeurl https://courses.cs.ut.ee/LTAT.03.001/2020_fall/uploads/Main/silmaring2_1.html width=100% height="230px" border="0" :)
(:includeurl https://courses.cs.ut.ee/LTAT.03.001/2020_fall/uploads/Main/silmaring2_2.html width=100% height="230px" border="0" :)
(:includeurl https://courses.cs.ut.ee/LTAT.03.001/2020_fall/uploads/Main/silmaring2_3.html width=100% height="230px" border="0" :)

!!!Ülesanded
1. Kirjuta valuutakalkulaator, kuhu sisestatakse nii baasvaluuta, soovitud valuuta ja raha kogus. 

Näide:

(:codestart python gutter='false':)
>>> %Run valuutaarvutaja.py
Sisesta baasvaluuta: GBP
Sisesta teine valuuta: IDR
Sisesta kogus: 1
1 GBP on väärt 18262.95 IDR
(:codeend:)

2. Kirjuta programm, mis küsib kasutajalt sisendit, kasutab mõnda huvitavat rakendusliidest ning väljastab vastavalt sisendile rakendusliidesest saadud infot.
