API zum Selber bauen & Veröffentlichen
API sollte ziemlich sicher allen MMPlern bereits was aus der IM-Zeit etwas sagen.
Ich wollte etwas tiefer graben und habe eine eigene API zu bauen und sie dazu auch veröffentlichen.
Schaut gerne vorbei:
Klimawandel API
In der Kritik findet ihr mehr über die Idee und Umsetzung heraus.
(bas)
Der Anfang
Im letzten Semester lernten wir bereits das API (Application Programming Interface) kennen und für was man es gebrauchen kann. Ich wollte austesten, wie es ist, selbst eine API zu erstellen und diese für andere zugänglich zu machen. Dafür surfte ich im Internet in Foren und Webseiten über die Möglichkeiten, wie dies gehen soll. Ich fand einige Anhaltspunkte, wie es Personen mit dem den Node-Packages «Axios», «Cheerio» und «Express» geschafft haben. Daraufhin machte ich mich selbst ans Werk.
Die Idee «Klimawandel-API»
Mein Ziel ist es aus den Klimawandel-News-Artikeln von diversen Webseiten wie Blick, Nau oder SRF, die Titel der Beiträge und die URL’s zu entnehmen. Dadurch würde meine API eine Schnittstelle zu aktuellen News-Beiträgen über Klimawandel bilden.
Umsetzung
Erste Schritte
Als Erstes öffne ich den Quelltext-Editor Visual Studio Code und erstelle einen leeren Ordner namens «klimawandel api». Man braucht Node.js fürs Backend. In meinem Fall arbeite ich mit der Version 16.14.2. Über den Terminal-Befehl «node -v» findet man heraus mit welcher Version man arbeitet. Ich hatte Node.js wegen eines früheren Projekts bereits installiert und belasse es deshalb bei dieser Version.
Als Nächstes kreiere ich ein package.json-File mit Hilfe vom Terminal-Befehl «npm init». Dabei muss man darauf achten, auch im richtigen Projektordner zu sein. Als Nächstes werden Fragen für die Erstellung der package.json-Datei gefragt. Ich stimme bei allen zu bzw. lasse sie leer. Nach Beendigung wurde die Datei erfolgreich erstellt. Danach erstelle ich im Editor ein index.js. In diesem File wird der Code für unseren Server gespeichert.
Dann brauchen wir das NPM-File-Package «cheerio». Cheerio funktioniert ähnlich wie jQuery und ermöglicht uns HTML-Elemente einer Website zu manipulieren und so z.B. an einer anderen Stelle anzeigen zu lassen. Mit dem Terminal-Befehl «npm i cheerio» installieren wir es in unseren Projektordner. Jetzt wird cheerio auch im package.json unter dependencies (Abhängigkeiten) aufgelistet. Hinzu kommt die Installation des Packages «axios». Dies ermöglicht HTTP-Anfragen, um über die Befehle get, post, put und delete Daten zu holen und zu bearbeiten.
Was ich auch brauche, ist das Backend-Framework «express.js». Der Befehl zur Installation lautet hier «npm i express» Dieses Package hört auf die URL und kann dementsprechend Code ausführen. Das heisst, wenn ich die URL im Browser ändere und z.B. auf eine Unterseite gehe, wird ein entsprechender Code ausgeführt und mir Daten angezeigt.
Nachdem installieren der Packages kann man im Terminal «npm i», um das package-lock.json zu erstellen. Dort drin sieht man, von welcher Quelle die Packages heruntergeladen worden sind.
Index.js
Als Erstes definieren wir einen Port, an dem unser Server ausgegeben wird. Dafür schreibe ich «let Port = 8000;». Die Zahl kann eine Beliebige sein. Später können wir im Webbrowser die Adresse «http://localhost:8000/» aufrufen, um unsere JSON-Daten zu sehen. Dann initialisieren wir die Packages über «let package = require(‹package›)». Damit express seine vollen Nutzen entfalten kann, kommt eine Zeile mit «let app = express()» dazu. Dadurch wird die Funktion Express aufgerufen und mit Hilfe der Variable können wir sie mehrmals verwenden.
Browser-Startseite
Auf der Startseite möchte ich einen Willkommenstext einfügen. Hier kann ich über app.get(‹/›, (res) => {}) die Homepage ansprechen. App haben wir weiter oben definiert, es steht für die Express-Funktion. Und get ist eine gängige Syntax, um sich Daten zu holen. In die geschweiften Klammern kommt der Code res.json(‹Willkommen auf der News-API mit Beiträgen über den Klimawandel.›). «res» steht für response also Antwort und json für das Datenformat. Sobald man das gespeichert hat, kann man im Browser den localhost:8000 aufrufen und den Willkommenstext sehen.
Web Scraping
Ich habe zum Beispiel die News-Seite Blick besucht und bin dann zur Unterseite https://www.blick.ch/dossiers/klimawandel/ gelangt. Dort sieht man beim Untersuchen der Seite, dass die Beiträge im anchor-Tag das Wort «Klima» enthalten. Diese Information benötigen wir, um die Beiträge im Code anzusprechen und sie so zu verwenden.
Zurück zu Index.js; hier drin nehmen wir wieder app.get, aber nun verwenden eine Unterseite. Das heisst, man kann im Code statt ‹/› als Beispiel ‹/news› schreiben. Als nächstes kommt das importierte Package «Axios» zum Zug. Mit dem Code axios.get(‹https://www.srf.ch/news/klima-und-klimawandel›) rufen wir die SRF-Website auf. Anschliessend kommt der Code .then((response) => {let html = response.data} hinzu. Dies bewirkt, dass das HTML von der SRF-Seite in der Variable html gespeichert wird. Mit console.log(html) sehen wir in der Console bzw. Terminal die ganze HTML-Struktur. Nun brauche ich aber bestimmte Elemente und nicht die ganze Struktur. Für diesen Grund können wir «Cheerio» verwenden. Ich speichere cheerio.load(html) in der Variable $. In der nächsten Zeile schreibe ich $(‹a:contains(«Klima»)›). Damit untersucht Cheerio alle anchor-Tag-Elemente mit dem Inhalt «Klima». Als nächstes will ich die Titel und die URL der News-Beiträge ansprechen. Dafür schreibe ich beim Titel let titel = $(this).text(); und bei der URL let url = $(this).attr(‹href›);. Nun kann man diese Daten separat in einem Array «beitraege» speichern. Dieses Array sollte zuerst ausserhalb der get-Funktion definiert werden, damit sie global ansprechbar ist. In der axios.get-Funktion können wir mit beitraege.push({titel, url}) alle News-Artikel im Array speichern. Damit die Artikel auch im Browser angezeigt werden, schreiben wir in der nächsten Zeile res.json(beitraege).
Juhu, nun werden im Browser die Daten angezeigt! Mit der Chrome-Erweiterung JSON-Viewer wird die JSON-Struktur leserlicher dargestellt.
Multiple Medien
In einem globalen Array «medien» können wir mehrere News-Seiten erfassen. Diese Medien sollen auf Klimawandel-Beiträge untersucht werden. Dies können wir durch die Funktion medien.forEach(medium => { … } ausführen lassen. In die geschweiften Klammern kommt der Code den wir beim Web Scraping geschrieben haben.
Unvollständige URL
Wenn man im Browser ist und auf einen URL klickt, wird man leider nicht zu einem Beitrag, sondern einer 404-Seite weitergeleitet. Dies kann verhindert werden, indem beim medien-Array eine weitere Eigenschaft hinzugefügt wird. Bei Nau schreiben wir z.B. basis: ‹https://www.nau.ch›. Das heisst wir haben der URL eine Basis gegeben. Dazu ergänzen wir bei der beitraege.push({}) in den geschweiften Klammern url: medium.basis + url. Nun sollte die Weiterleitung funktionieren.
Learnings und Fazit
Ich habe bei diesem Projekt sehr viel lernen dürfen. Zum einen wie die verschiedenen Node-Packages Axios, Cheerio und Express funktionieren und wie ich sie anwenden kann. Zum anderen wie die API aufgebaut ist und was es alles für Beispiele von anderen Personen gibt.
Ich fand das Projekt spannend und lehrreich. Auch wenn ich einige Male nicht mehr weiter wusste, viel googeln und Dokumenationen durchgelesen habe, ging es schlussendlich einigermassen auf.