Lekcja 13 - API i request (notatki)

Lekcja 13 - API i request (notatki)

API

API (ang. Application Programming Interface) - skodyfikowany sposób komunikacji między aplikacjami tzn. jakie zasady stosujemy w przekazywaniu danych i jakich programów używamy by je odczytać.

REST API - ogólny zestaw reguł jakie powinno zawierać nasze API. Jedną z dużych wad restowych API jest wyświetlanie tylko tych informacji, które przewidział autor (często nie da się zawęzić wyniku). Ponadto nie podaje informacji w jakim formacie powinny być dostarczane dane, choć najczęściej jest to JSON. Mniej elastyczny jest np. SOAP (tu dane dostarczane są w XML).

Jak uzyskać dane o API? Na podstronie Github można znaleźć zestaw darmowych API, wraz z informacją czy konieczna jest autoryzacja. Podobnie działa też Rapid. Zawsze można też sięgnąć do dokumentacji danej strony internetowej. Wiele stron korzysta ze Swaggera (narzędzie do dokumentowania API) i takiej końcówki możemy szukać na stronie.

API można przeglądać przez przeglądarkę. Jednak gdy prosimy o konkretniejsze dane adres url staje się dłuższy i małoczytelny. Pomocą w testowaniu i pisaniu kodu mogą być różne narzędzia internetowe takie jak Postman, Insomnia czy Hoppscotch. W tym ostatnim można wygenerować odpowiedni kod do pythona poprzez kliknięcie Generate kod, a następnie z rozwijanego menu wybrać python request.

Ćwiczenia

Wymyśl zadanie wymagające odpytania API

import requests
url = "https://wolnelektury.pl/api/authors/charles-dickens/books"
response = requests.get(url)
print(response.json())

Wyświetl utwory Charlesa Dickensa

import requests
url = "https://swapi.dev/api/starships/2"
response = requests.get(url)
print(response.json())

Wyświetl drugą stronę z informacjami na temat statków w StarWars

import requests
url = "https://api.jikan.moe/v4/anime"
querystring = {"sfw":"true","min_score":"8.5"}
response = requests.get(url, params=querystring)
print(response.json())

Wyszukaj anime o ocenach min. 8.5 i odfiltrowujac wyniki dla doroslych (sfw)

Python request

W jaki sposób pobrać dane z innej aplikacji do naszego pythona? Dzięki Requests (pełna dokumentacja pod linkiem).

import requests

url = "https://api.frankfurter.app/latest"

params = {"amount":"10","from":"PLN","to":"EUR"}

odpowiedz = requests.get(url, params=params)
type(print(f"Bazowa odpowiedz jest typu {type(odpowiedz)}"))

po_metodzie_json = odpowiedz.json()

print(f"Po metodzie .json : {type(po_metodzie_json)}")

print(po_metodzie_json)

print(f"{po_metodzie_json["amount"]} PLN zamienione na EUR to {po_metodzie_json["rates"]["EUR"]}")

Ćwiczenie

Wyciągnij z serwisu Open Meteo dane dotyczące temperatury, prędkości wiatru i wilgotności na danej długości i szerokości geograficznej. Potem wyświetl te dane za pomocą streamlita. Pamiętaj, że musisz wpierw zainstalować bibliotekę do map w pythonie - folium, poprzez wpisanie w terminalu pip install streamlit-folium. Możesz wpływać na wygląd mapy, więcej pod linkami:

Folium — Folium 0.17.0 documentation
Leaflet — an open-source JavaScript library for interactive maps
Leaflet is a modern, lightweight open-source JavaScript library for mobile-friendly interactive maps.

import requests
import pandas as pd
import streamlit as st
from streamlit_folium import st_folium
import folium

url = "https://api.open-meteo.com/v1/forecast"

lat = "52.52"
lon = "13.41"

mapka = folium.Map(tiles="CartoDB.Positron")

wyswietlona_mapka = st_folium(mapka, height=350, width=650)

if wyswietlona_mapka.get("last_clicked"):
  lat = wyswietlona_mapka["last_clicked"]["lat":0.2f] #wbudowane w obiekt, zmieniać nie można
  lon = wyswietlona_mapka["last_clicked"]["lng":0.2f}

  querystring = {
    "latitude": lat,
    "longitude": lon,
    "hourly": "temperature_2m,relative_humidity_2m,wind_speed_10m",
}

  st.write(lat, lon)
  
  response = requests.get(url, params=querystring)
  
  dane_godz = response.json()["hourly"]
  dane_godz_df = pd.DataFrame.from_dict(dane_godz)
  
  st.write(dane_godz_df)
  st.line_chart(
      dane_godz_df[["time", "temperature_2m"]],
      x="time",
      y="temperature_2m",
  )