Einführung in Web APIs#
Bei einer API (Application Programming Interface oder Programmierschnittstelle) handelt es sich ganz allgemein erstmal um einen Teil einer Softwarearchitektur, der eine Kommunikation zwischen zwei unterschiedlichen Maschinen ermöglicht. Eine API stellt Entwickler:innen Funktionen bereit, mit denen sie ihre Maschine so programmieren können, dass diese Teile der externen Maschine, die die API bereitstellt, steuern kann. API-Funktionen haben einen Namen und benötigen von Ihnen vergebene Parameter.
Wenn wir im geisteswissenschaftlichen Kontext von APIs sprechen, meinen wir in der Regel Web APIs. Hierbei handelt es sich um spezielle APIs, die auf Webservern laufen und meist dazu genutzt werden, strukturierte oder semistrukturierte Datenbestände zu durchsuchen und herunterzuladen – manchmal sind APIs sogar die einzige Möglichkeit, um an öffentlich bereitgestellte Daten zu kommen. Um eine Web API zu nutzen, benötigen Sie immer zwei, manchmal auch drei Informationen:
Sie müssen wissen, welche Funktionen die API, mit der Sie arbeiten wollen, bereitstellt. Nur so sind Sie in der Lage, Abfragen zu konstruieren, mit denen Sie genau die Daten aus dem Datenbestand filtern können, die Sie auch tatsächlich benötigen. Eine Auflistung der Funktionen einer API finden Sie in deren Dokumentation.
Sie benötigen den Endpoint der API. Bei einem Endpoint handelt es sich um eine URI (eine Art Webadresse/URL). Über diese Adresse können Sie die Funktionen einer API aufrufen. Einer der Endpoints der verschiedene APIs von Europeana, die wir in diesem Notebook nutzen, lautet z.B. https://api.europeana.eu/.
Manchmal benötigen Sie außerdem noch einen Access Token oder einen API Key. Hierbei handelt es sich letztlich einfach nur um einen automatisch erzeugten Benutzernamen und ein Passwort. Diese Informationen erhalten Sie vom Anbieter der API. Access Token und API Key dienen der Zugriffssteuerung – manche Anbieter wollen Ihre Daten nicht uneingeschränkt öffentlich zur Verfügung stellen oder zumindest ungefähr nachverfolgen können, von wem bestimmte Zugriffe kommen.
Suchen Sie auf der Webseite des Projekts oder der Institution, an dessen Daten Sie interessiert sind, einfach nach API oder Developers. Dort finden Sie die Dokumentation sowie alle weiteren Informationen, die Sie für die Verwendung der API benötigen.
Abfragen konstruieren#
In dieser Einheit arbeiten wir mit einer der verschiedende Web APIs von Europeana – und zwar mit einer API um Inhalte digitalisierter Zeitungen abzufragen. Europeana ist ein von der EU gefördertes Projekt, das den Zugang über ein digitales Portal zu Europas Kulturellem Erbe, das in Museen und Institutionen in ganz Europa zu finden ist, für alle Interessierten zu ermöglichen. Hier finden Sie weitere Informationen zum Auftrag von Europeana.
Europeana bietet verschiedene APIs zu unterschiedlichen Zwecken. Wichtig ist daher eine eingehende Auseinandersetzungen mit den Möglichkeiten und den Funktionalitäten des API-Angebots. Eine sehr ausführliche Dokumentation zu diesem Angebot finden Sie auf eigenen Seiten, die für Entwickler:innen zur Verfügung gestellt werden unter https://pro.europeana.eu/page/search.
Aufgabe: Machen Sie sich mit der Dokumentation der API von Europeana vertraut.
API Key von Europeana#
Einen API Key von Europeana erhalten Sie, wenn Sie die Angaben in dem Formular ausfüllen, das Sie über diesen Link erreichen. Nachdem Sie den terms of use zugestimmt haben, erhalten den API Key in einer Email und können diesen bei Anfragen an die Europeana-APIs nutzen. Es entstehen keine Kosten für Sie und der Vorgang nimmt maximal nur 1 Minute in Anspruch.
Aufbau einer API-Anfrage#
Sie können diesen Link einfach in Ihrem Internetbrowser aufrufen, um das Ergebnis zu erhalten. Dazu müssen Sie Ihren API-Key am Ende der URL einfügen. Ihnen wird ein JSON angezeigt (das Sie sich auch herunterladen können).
Um besser zu verstehen, wie unsere Abfrage aufgebaut ist, können wir sie in ihre Bestandteile zerlegen. Eine Übersicht der Parameter finden Sie hier in der Dokumentation.
https://newspapers.eanadev.org/api/v2/search.json
# Dies ist der Endpoint der API. Hier liegen die
# verfügbaren Funktionen. Um diese nutzen zu können, müssen Sie Ihre
# Abfrage einfach an die Adresse des Endpoints anhängen.
?
# Auf den Endpoint folgt ein Fragezeichen. Danach kommt die Abfrage.
query=Python
# Hiermit suchen wir nach dem String 'Humboldt'. Syntaktisch beginnt die Abfrage mit dem Namen der Funktion; hinter
# dem Gleichheitszeichen folgt der Parameter. Die genaue Syntax entnehmen Sie der Dokumentation
# einer API.
&
# Einzelne Funktionsaufrufe werden mit einem kaufmännischen 'und' getrennt.
qf=LANGUAGE:de
# Mit qf können wir die Anfrage weiter verfeinern. Hier filtern wir die Sprache: de steht für deutsch.
&
profile=hits+params
# Hiermit steuern wir das Format und Umfang der Rückgabe.
&
hit.selectors=10
# Hiermit steuern wir das Format und Umfang der Rückgabe.
&
sort=europeana_id+desc
# Hier geben wir die Sortierung über die ID in absteigender Folge vor.
&
rows=5
# Die maximale Anzahl der Ergebnisse (also der Protokolle), die uns angezeigt
# werden soll. Fast alle Anbieter legen hier Beschränkungen auf; bei Europeana lassen
# sich nicht mehr als 100 Treffer in einer Abfrage zurückgeben. Auf diese Weise soll eine Überlastung
# der Server durch zu umfangreiche Rückgaben vermieden werden.
&
cursor=*
# Dieser Parameter wird als Marker genutzt, um über eine Paginierungs-Funktion alle
# Treffer abrufen zu können (die sonst ja bei einer Anfrage auf 100 Treffer beschränkt ist.)
&
wskey=<YOUR API KEY>
# Hier müssen Sie Ihren API Key eingeben, um die Anfrage durchführen zu können
APIs mit Python abfragen#
Idealerweise möchten wir die Daten natürlich automatisiert herunterladen und direkt weiterverarbeiten. In Python lassen sich API-Abfragen z.B. mit der requests-Bibliothek durchführen.
Zuerst importieren wir, wie üblich, die benötigten Programmierbibliotheken. Die meisten davon kennen Sie ja bereits. Bei pprint (pretty-print) handelt es sich um eine Alternative zur Funktion print() mit der Sie sich strukturierte Daten, wie zum Beispiel JSONs, bzw. Dictionaries formatiert (und damit lesbarer) anzeigen lassen können.
import requests
import json
import pprint
Es folgt nun die Anfrage an die API über den Endpoint:
# Der Endpoint der SearchAPI von Europeanna
api_base_url = 'https://newspapers.eanadev.org/api/v2/search.json?'
# Ihr API-Key
apikey = # <YOUR_API_KEY>
# Hier konstruieren wir die Abfrage als String.
query_url = api_base_url + 'query=Python'
query_url += '&qf=LANGUAGE:de'
query_url += '&profile=hits+params'
query_url += '&hit.selectors=10'
query_url += '&sort=europeana_id+desc'
query_url += '&rows=5'
query_url += '&cursor=*'
query_url += '&wskey=' + apikey
print(query_url)
Mit der Funktion json() der requests-Bibliothek können Sie das JSON als Dictionary parsen. Um Programmfehler zu vermeiden haben wir in diesem Beispiel außerdem eine if-Abfrage zur Sicherung eingebaut. Der Variable response_content wird nur dann ein Wert zugewiesen, wenn unsere Anfrage an den Server auch tatsächlich mit Daten beantwortet wird. Bei jeder Anfrage an einen Server gibt dieser einen HTTP-Statuscode zurück. Auf diese Weise lassen sich Fehler eingrenzen – so legt ein Statuscode z.B. fest, ob der Fehler auf Client- oder Server-Seite liegt. Einen Überblick über alle HTTP-Statuscodes finden Sie z.B. hier oder hier.
# Hier wird die Abfrage an den Server von Europeana gesandt.
response = requests.get(query_url)
if response.status_code == 200:
response_content = response.json()
else:
response_content = None
pprint.pprint(response_content)
Abfrage mit Header#
Eine Alternative ist die API-Abfrage mit einem *Header*. Dies bietet sich insbesondere an, wenn Abfragen besonders komplex sind oder deren Bestandteile von Ihrem Python-Programm gesteuert werden sollen. Für das requests-Modul wird ein Header als Dictionary definiert und der Funktion get() zusammen mit dem Endpoint der API als Parameter übergeben. Durch die Verwendung eines Dictionaries sparen Sie sich die Hantierung mit komplexen Strings, wie im oberen Beispiel. Ansonsten unterscheidet sich der folgende Codeblock nur marginal vom vorigen.
api_base_url = 'https://newspapers.eanadev.org/api/v2/search.json?'
request_header = {'query': 'Python',
'qf': 'LANGUAGE:de',
'profile': 'hits+params',
'hit.selectors': '5',
'sort': 'europeana_id+desc',
'rows': '100',
'start': '1',
#'cursor': '*',
'wskey': apikey}
response = requests.get(api_base_url, request_header)
if response.status_code == 200:
response_content = response.json()
else:
response_content = None
pprint.pprint(response_content)
Wie bereits weiter oben beschrieben beschränken die meisten APIs die Anzahl der Ergebnisse, die sich bei einer Abfrage herunterladen lassen. Um trotzdem alle möglichen Ergebnisse erhalten zu können, bieten viele APIs eine virtuelle Paginierung an (Details finden Sie in der jeweiligen Dokumentation, in unserem Falle hier). Im obigen Beispiel legen wir fest, dass wir nur 5 Ergebnisse der insgesamt 842 Treffer unserer Abfrage zum String ‘Python’ zurückbekommen wollen. Möchten wir 842 Treffer erhalten, müssen wir die API-Abfrage mehrmals an den Server senden und dabei den cursor marker entsprechend anpassen.
Um die Auslastung der Server des API-Anbieters möglichst gering zu halten, empfiehlt es sich nach jeder Abfrage eine kurze Wartepause einzulegen, bevor man mit der nächsten fortfährt. In Python kann man solche Pausen mit Hilfe der Funktion sleep() aus der Bibliothek time sehr leicht implementieren:
import time
print('Warte 2 Sekunden')
time.sleep(2)
print('Fertig')
API-Daten für die Auswertung aufbereiten#
Um die Daten, die von einer API abgerufen wurden, aufzubereiten, bedarf es je nach API und nach Rückgabeformat unterschiedliche Schritte. Wir werden uns daher im nächsten Kapitel mit weiteren APIs und API-Anfragen befassen. Zudem haben wir die Übungsaufgabe am Ende dieses Kapitel so gestaltet, dass Sie fremden Coden nachvollziehen und verstehen. Hier wird es darum gehen, wie für das obige Beispiel die Daten für eine erste Auswertung aufbereitet werden können.
Wie das Auslesen dieser Informationen bei einer gewöhnlichen Webseite in HTML mit Hilfe von BeautifulSoup funktioniert, werden wir in den nächsten Abschnitten durchgehen. Zunächst noch ein kurzer Exkurs zu den Grundlagen von HTML.