Es ist wieder die Jahreszeit, in der viele Online-Dienste und Plattformen für ihre Benutzer einen maßgeschneiderten Jahresrückblick zusammenstellen. Dank der Fülle der gesammelten Daten kann darin das Nutzerverhalten oft gut analysiert und schön aufbereitet werden.
Je nach Plattform fallen diese Jahresberichte unterschiedlich aus: Manche beschränken sich auf einige Kernpunkte und Datenpunkte, während andere die Daten mit Grafiken und Visualisierungen anreichern.
Ich fand die Idee dieser Jahresrückblicke schon immer interessant, allerdings war ich mit den erzeugten Rückblicken nie wirklich zufrieden: Bei manchen hätte ich mir eine ausführlichere Analyse zu einem speziellen Thema gewünscht, während ich bei anderen eine informative Visualisierung vermisste. Auch kommt es oft vor, dass sich das Format der Jahreszusammenfassungen ändert, so dass es schwierig ist, Vergleiche über mehrere Jahre hinweg anzustellen.
Außerdem werden dieser Zusammenfassungen natürlich immer vom Anbieter zusammengestellt, der diese Seiten jederzeit und aus verschiedensten Gründen wieder vom Netz nehmen kann.
Da habe ich mir gedacht:
Warum nicht einfach einen Jahresrückblick selbst programmieren? So schwer kann es ja nicht sein. Schließlich erlauben viele Online-Dienste und Plattformen den Zugriff auf ihre Daten per Programmierschnittstelle.
Also habe ich mir als Ziel gesetzt eine eigene Zusammenfassung des Jahres zu programmieren, mit Daten und Auswertungen die mich interessieren. Weiterhin sollte der Jahresrückblick komplett auf meiner Webseite gehostet sein und keine Abhängigkeiten von Drittanbietern haben, so dass ich die komplette Kontrolle über Aussehen und Inhalte behalte.
Das Ergebnis
Das fertige Produkt kann man auf meiner Rückblick-Seite einsehen. Dort habe ich die für mich interessanten Daten nach Themen aufgeteilt. Je nach Anzahl und Form der mir zugänglichen Daten konnte ich zu den verschiedenen Themen mehr oder weniger Visualisierungen erstellen.
Daten folgener Plattformen und Dienste konnte in meinem automatisierten Jahresbericht visualisieren:
- Meine Ausflüge, Radtouren und Wanderungen, die ich auf Komoot veröffentlicht habe
- Meine Checkins bei Swarm (ehemals Foursquare)
- Meine Veröffentlichungen auf Mastodon und Pixelfed
- Meine öffentlichen Code-Aktivitäten bei Github
- Meine Filmbewertungen bei Letterboxd
- Meine Musikgewohnheiten bei Last.fm
- Meine Nutzung öffentlicher Verkehrsmittel bei Traewelling
- Mein Konsum von Videospielen
- Der Verlauf meiner Matches bei PUBG:Battlegrounds
Technischer Überblick
Im Folgenden erkläre ich, welche Technik ich für die Erstellung des Jahresrückblicks einsetze, gehe auf die Beschaffung der Daten bei einzelnen Diensten ein und beschreibe, wie ich die dazugehörigen Datenvisualisierungen erstellt habe.
A: Daten sammeln
Bevor ich die Daten anzeigen kann, muss ich sie zunächst von den entsprechenden Online-Diensten abrufen. Das funktioniert je nach Plattform und Dienst unterschiedlich.
Dazu habe ich ein Skript erstellt, das einmal am Tag automatisch ausgeführt wird und die dabei anfallenden Daten in meine eigene Datenbank speichert.
Als Datenbank habe ich SQLite ausgewählt, da sie von vielen Programmiersprachen unterstützt wird und sich wie eine Datei verhält, die ich jederzeit kopieren kann. Das ist insbesondere beim Debuggen sehr praktisch. Ein weiterer Vorteil von SQLite ist, dass ich dafür keinen eigenen Server installieren, starten, und warten muss.
Beim Daten-Sammel-Skript habe ich mich für Node.js entschieden: JavaScript bietet die Flexibilität dynamischer Typisierung, was bei der Verarbeitung der verschiedenen, nicht immer konsistenten Antwortformate der Online-Dienste von Vorteil ist. Außerdem bringt es Unterstütung für asynchrone Operationen mit Promises und async / await
mit. Diese ist sehr hilfreich wenn man mit vielen Servern gleichzeitig kommunizieren möchte.
Je nach Plattform und Dienst ist es unterschiedlich schwierig, an meine dort gespeicherten Daten heranzukommen. Im Folgenden habe ich eine kleine Liste erstellt, welche Schritte nötig waren, um meine Daten zu speichern.
- Pixelfed Komplexität:
(1/10)
: Pixelfed stellt einen öffentlichen Feed für jeden Nutzer bereit. Er ist einfach zu parsen und enthält alle relevanten Informationen. - Mastodon Komplexität:
(1/10)
Mastodon stellt die öffentliche Timeline jedes Nutzers als im JSON-Format zur Verfügung, die alle für mich interessanten Informationen enthält. - PUBG:Battlegrounds Komplexität:
(2/10)
PUBG stellt die Informationen aller Matches per API zur Verfügung. Dafür muss ein API-Schlüssel beantragt werden. Aufgrund der API-Struktur muss ich für jedes Match fünf verschiedene, verkettete Anfragen an die API senden, um an die Relevanten Informationen zu kommen. - Steam Komplexität:
(2/10)
: Steam stellt viele Informationen zu einem Profil im XML-Format bereit. Leider ist die API nicht gut dokumentiert, und die URL-Parameter funktionieren nicht bei allen Titeln. - Traewelling Komplexität:
(2/10)
: Traewelling stellt den öffentlichen Feed von Benutzern als JSON zur Verfügung. Die GeoJSON-Datei mit den GeoDaten auch unter einer einfachen URL erreichbar. Die API von Traewelling hat sich allerdings des öfteren geändert, und so ist es z.B. vorgekommen, dass ich die GeoJSON-Daten über einen längeren Zeitraum nur aus einer HTML-Seite extrahieren konnte. - Github Komplexität:
(3/10)
: github stellt über einen .atom feed die Öffentlichen Aktivitäten eines Nutzers zur Verfügung. Allerdings hat sich die Formatierung der Inhalte über die Jahre immer mal wieder geändert, so dass bei der Auswertung und Anzeige zusätzliche Logik notwendig ist, welche die Feed-Einträge durch einen HTML-Parser laufen lässt. - Letterboxd: Komplexität:
(4/10)
: Letterboxd stellt für jeden Benutzer einen Feed mit den Bewertungen zuf Verfügung. Darin nicht enthalten sind weitere Informationen zum bewerteten Film wie z.B. Dauer oder Mitwirkende. Diese Informationen bekomme ich über eine zusätzliche Abfragen bei der Open Movie Database. Dafür muss eine API-Schlüssel beantragt werden. - Last.fm: Komplexität:
(4/10)
: last.fm stellt eine Programmierschnittstelle für die gehörten Musikstücke zur Verfügung (API-Schlüssel notwendig). Die API stellt das Datum, Titel, Künstler und Album-Artwork zur Verfügung. Es fehlt die Dauer des Musikstücks und das Genre. Diese Information bekomme ich über einen zusätzlichen Aufruf der Musikbrainz API. - Foursquare/Swarm: Komplexität:
(5/10)
: Die Foursquare-Node API hat die für mich Relevanten Daten nicht bereitgestellt. Stattdessen musste ich den Umweg über einen eigens erstellten PHP-Server gehen, der die für mich relevanten Daten speichert. - Komoot: Komplexität:
(9/10)
: Komoot stellt für Normalsterbliche leider keine öffentliche API zur Verfügung (es scheint eine API für Geschäftskunden zu geben). Entsprechend müssen alle für mich relevanten Daten aus der öffentlichen Webseite extrahiert werden. Auch ist der Zugriff auf meine Daten eingeschränkt: seit einiger Zeit stellt Komoot nur noch drei Fotos pro Eintrag zur Verfügung. Möchte ich alle Bilder zu einem Eintrag haben, muss ich mich auf der Webseite einloggen und diese mauell herunterladen. Von Komoot bekomme ich die Informationen zur Sportart, die Dauer und die Höhenmeter sowie die Geodaten der Route. Wetterinformationen zu einem Komoot-Eintrag bekomme ich über eine Anfrage an die API von Pirate Weather (API-Schlüssel nötig). Informationen über befahrenen Straßen, und den Untergrund bekomme ich über eine Anfrage an GeoAPIfy (API-Schlüssel nötig). Informationen über die durchquerten Gebiete, Orten und Länder bekomme ich von OpenStreetMap, genauer von der Overpass API. Diese gibt netterweise auch die Wikipedia-Einträge der entsprechenden Gebiete zurück. Über eine Abfrage bei der Wikidata-API bekomme ich dann schließlich noch die Stadtwappen sowie den Beschreibungstext der Gebiete.
Ich finde man sieht hier sehr schön, wie quelloffene Projekte (wie Traewelling, Pixelfed und Mastodon) oft die Nase vorn haben, wenn es um den maschinenlesbaren Zugriff auf die eigenen Nutzerdaten geht.
B: Daten auswerten und anzeigen
Ich benutze für meine Webseite das CMS Kirby, das in PHP geschrieben ist. Entsprechend habe ich für die Anzeige und Auswertungen einigen Code in PHP geschrieben.
Weiterhin werden für die Auswertung natürlich viele Datenbankabfragen in SQL verwendet. Diese sind teilweise komplexer geworden als gedacht.
Für die Anzeige und Visualisierungen habe ich vor allem zwei verschiedene JavaScript-Bibliotheken verwendet:
Zum einen setze ich d3 ein, um alle Graph-Darstellungen zu erzeugen. Sie ist sehr flexibel und bietet Unterstützung für eine riesige Anzahl verschiedenster Graph-Typen und Visualisierungsarten. Es gibt für d3 es online sehr viele Lern-Ressourcen, und massenhaft Beispiele, so dass mir das Erstellen der verschiedenen Visualisierungen hier sehr einfach gefallen ist.
Bei den Kartenvisualisierungen habe ich mich für die Bibliothek maplibre-gl entschieden. Sie bietet eine Fülle an Funktionenen und erlaubt es gleichzeitg, sehr viele Entscheidungen welche die Kartendarstellungen betreffen, selbst zu treffen.
Da ich mir als Ziel gesetzt hatte, alle den Jahresrückblick betreffende Daten selbst zu hosten, schieden für mich die üblichen Kartenanbieter wie Google Maps oder MapBox aus. Stattdessen entschied ich mich dazu Protomaps zu verwenden. Dieses Datenformat macht es möglich, Kartendaten relativ einfach herunterzuladen und dann selbst zu hosten und bietet gleichzeitig die Möglichkeit, das Erscheinungsbild der Karten auch selbst zu gestalten.
Ich habe den Quelltext der pmtiles Bibliothek, noch leicht angepasst, so dass es mir nun auch möglich ist 3D-Reliefs auf der Karte anzuzeigen (Das sieht besonders bei Touren im Gebirge, z.B. einer Tour in den Alpen beeindruckend aus).
Eine weitere Biblothek, die mir bei der Verarbeitung von Geodaten sehr hilft ist turf.js: Sie ist ein super Werkzeug für die Arbeit mit GeoJSON, und macht es z.B. sehr einfach Flächen und Distanzen zu berechnen, oder Schnittpunkte von Flächen zu finden.
Erkenntnisse
Bei der Arbeit an dem Projekt habe ich einiges gelernt und herausgefunden. Hier eine kurze Liste mit interessanten Funden und Überraschungen.
- Die Overpass-API für OpenStreetMap ist aufgrund ihrer eigenen Abfragesprache zwar etwas schwerfällig zu bedienen, bietet jedoch eine Fülle an Informationen, die ich nicht erwartet hätte.: Insbesondere die Verweise auf die WikiMedia API waren sehr hilfreich und haben es mir ermöglicht, neue Features zu bauen.
- Die WikiMedia API ist ebenfalls etwas gewähnungsbedürftig strukturiert, bietet aber ebenfalls Zugang zu vielen Daten und Informationen, die sich für das Projekt als sehr nützlich erwiesen haben.
- Die Verwendung von GeoJSON als Datenformat für alle Geodaten war eine gute Entscheidung. Es gibt dafür in vielen Programmiersprachen extzellente Tools (siehe turf.js), ist leicht verständlich und leicht zu verarbeiten.
- SQL-Abfragen können auch für einfache Visualisierungen schnell komplex werden. Insbesondere die Abfragen zu den Aktivitäts-Serien (Serien von aufeinander foldenden Tagen, an denen es täglich ein Event gibt) waren schwierig zu realisieren.
- Obwohl die Datenmengen für die Visualisierungen einigermaßen überschaubar sind, musste ich für manche Berechnugen Stellen
Web Worker
einsetzen, um Daten im Hintegrund zu verarbeiten ohne dass der ins Browser stocken kommt.
Lieblingsfeature
Besonders gut gefällt mir die Visualisierung aller gefahrenen Strecken: Ich mag, wie sich darin mein eigenes Radnetz abzeichnet. Und wahrscheinlich auch, weil in diese Darstellung die der meißte Aufwand geflossen ist und ich hier sehr viel gelernt habe.
Fazit
Insgesamt habe ich mit dem Projekt nicht nur einen Jahresrückblick gebaut der alle Informationen enthält, die mir wichtig sind, sondern auch einiges über das Sammeln und Verarbeiten von API-Daten, (Karten-)Visualisierungen gelernt.
Ich finde es gut, dass ich zugrunde liegenden Daten lokal jetzt selbst hoste und ich so die Kontrolle über Inhalte und Auswertungen habe.
Hinterlasse einen Kommentar
Auf der eigenen Website geantwortet? Sende eine Webmention!