In einem privaten Projekt habe ich die Idee verfolgt, Wettervorhersagen für die Schweiz als Service über Social Media anzubieten. Für die Darstellung der Informationen habe ich auf Tilemaps zurückgegriffen. In diesem Blogpost soll es um die Daten und die Automatisierung gehen.
Bots, Holzöpfel und Zipfelchappe ⓘ
Wie in Teil 1 beschrieben, habe ich für den Social-Media-Wetterbericht eine Tilemap aus Emojis konzipiert. Nach ersten öffentlichen Tests mit der Tilemap, schon mit Wetterinformationen, hat Yannick Rochat folgendes getwittert: «Tell me this is a bot updating hourly.» 🙂 Dies gab den endgültigen Ausschlag für das Projekt emoji-weather: einen Meteo-Bot in Python zu programmieren, der vollautomatisch Emoji-Wetterberichte verbreitet – nicht im Stundenrhythmus wie von Yannick vorgeschlagen – das fand ich für das Publikum zu anstrengend – sondern drei Mal pro Tag.
Abfrage von Wetterdaten
Für die Abfrage von Wetterinformationen habe ich mich für die Programmierschnittstelle (API) von OpenWeather entschieden. Dieser Service hat einen grosszügigen free tier, der 60 API-Abfragen pro Minute bzw. 1 Mio. pro Monat erlaubt. Ich nutze den 5 day weather forecast, der über die nächsten 5 Tage Vorhersagen mit einer zeitlichen Auflösung von 3 Stunden liefert. Um eine Abfrage zu tätigen schickt man Breiten- und Längengrad sowie den eigenen API-Key an die Schnittstelle:
api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={API key}
Bei der Umsetzung wurde schnell klar, dass es keinen Sinn macht, ein reguläres Grid analog zur Anordnung der Tiles in der Tilemap abzufragen. Damit resultieren zum Teil Extremwerte vor allem in den Alpen. Ich habe das Grid wie folgt angepasst und dabei Stützpunkte tendenziell auf grössere oder wichtigere Ortschaften (und in den Alpen sicher immer in die Täler) verschoben:
Für das Abfragen der Wetterdaten wird der folgende Python-Code verwendet (das ist nur ein kleiner Auszug; der gesamte Code ist öffentlich einsehbar, siehe Link am Ende dieses Beitrags). Die for-Schlaufe (Zeile 7) iteriert durch die 84 Positionen im Grid und fragt – für die Positionen, für die wir Daten wünschen (Zeile 10) – die OpenWeather-Schnittstelle ab (Zeilen 12–13). Die Antwort im JSON-Format wird pro Position in einem Objekt meteodatum (Instanz einer Custom-Klasse) gespeichert (Zeile 15). Dieses wiederum wird dem Objekt meteomap (wiederum eine Instanz einer Custom-Klasse) hinzugefügt (Zeile 16).
Informationscodierung
Den Social-Media-Wetterbericht gibt es von zwei Bots (bzw. eigentlich vier, aber dazu später mehr): Ein Bot publiziert die generelle Wettervorhersage (also: bewölkt, sonnig, Niederschlag, etc.) und die erwarteten Luft-Temperaturen. Ein zweiter Bot – eher für Spezialistinnen und Spezialisten – veröffentlicht eine Windprognose, zusammengesetzt aus Windstärke und Windrichtung.
Für die Umsetzung der Informationen von OpenWeather in diese «Berichtsformate» habe ich entsprechende Methoden in der Klasse MeteoMap geschrieben (emojify_windspeed() (nicht gezeigt) ist sehr ähnlich zu emojify_temperature() in Zeile 11):
Wie man sieht, handelt es sich bei der Umsetzung für kategoriale Variablen (Wettervorhersage und Windrichtung) um eine Reihe von dictionary-Lookups. Bei den ratio-skalierten Parametern (Temperatur und Windgeschwindigkeit) werden die Daten klassiert: in automatisch ermittelte Quintile für die Temperatur und in automatisch ermittelte Quartile für die Windgeschwindigkeit. Gegen Ende der einzelnen Methoden im obigen Code-Ausschnitt – nach der eigentlichen Emoji-fizierung – wird mit set_basemap() die «Hintergrundkarte» konfiguriert (zum Beispiel Zeile 49). Das lakes-Flag bestimmt, ob Genfersee und Bodensee als blaue Kreise in die Karte eingefügt werden oder nicht (übrigens eine kontroverse Design-Entscheidung, wie man auch wieder in der Diskussion auf LinkedIn gesehen hat 😉).
Eine zum Python-Programm zugehörige Config-Datei (oben wird ihr Inhalt mit config referenziert) definiert die Codierung der Wetterdaten, bestimmt also darüber, mit welchem Emoji ein Prognosewert dargestellt wird. Glücklicherweise umfasst das Emoji-Universum unterdessen sehr viele Symbole, so dass die Wetterinformationen relativ detailliert visualisiert werden können:
Um den gesamten möglichen Informationsgehalt von OpenWeather abzudecken, sind auch einige spezielle Wetterlagen zu codieren, von denen ich bei manchen hoffe, dass wir sie nicht (allzu oft) antreffen werden…
Für spezielle Temperaturlagen wird die Quintil-Farbskala angepasst:
Temperaturskala | Normal | Warmlagen (80-Perzentil > 27°C) | Kaltlagen (20-Perzentil < -5°C) |
---|---|---|---|
> 80-Perzentil | 🟥 | 🥵 | 🟧 |
> 60-Perzentil | 🟧 | 🟥 | 🟨 |
> 40-Perzentil | 🟨 | 🟧 | 🟩 |
> 20-Perzentil | 🟩 | 🟨 | 🟦 |
≤ 20-Perzentil | 🟦 | 🟩 | 🥶 |
Die nicht mit Wetterdaten besetzten Positionen in der Tilemap müssen zum Schluss natürlich auch noch aufgefüllt werden. Von der Hintergrundkarte kommen mit der schon weiter oben angesprochenen Methode set_basemap() die Landesflaggen und Seen dazu. Damit die Anordnung des Grids gelingt, wird der Whitespace mit einem Füll-Emoji belegt. Und je nach Darstellung wird unterhalb der Karte eine Legende ergänzt. Damit sind die einzelnen Posts der Wetter-Bots fertig zusammengestellt.
Resultat
Die Code-Basis von emoji-weather wurde noch ergänzt mit dem ganzen «Drumherum» und vor allem mit der Funktionalität, um die Wetterprognose-Posts via Mastodon (ursprünglich: via Twitter) zu verbreiten.
Wenn Du gerne aktuelle Wetterprognosen in Deinem Fediverse-Newsfeed hast, kannst Du zwischen den folgenden Accounts auf der Schweizer Mastodon-Instanz tooting.ch wählen:
- Wetter- und Temperaturprognose (dark mode): @meteo@tooting.ch
- Wetter- und Temperaturprognose (light mode): @meteo_light@tooting.ch
- Windrichtungs- und Windstärkeprognose (dark mode): @meteoplus@tooting.ch
- Windrichtungs- und Windstärkeprognose (light mode): @meteoplus_light@tooting.ch
Einige Beispiele, wie die Wetterprognosen im Mastodon-Feed erscheinen:
Mastodon-Accounts haben die für manche Zwecke sehr nützliche Eigenschaft, dass sie auch altbewährte RSS-Feeds bereitstellen. Diese erhält man, indem man den oben verlinkten Account-URLs «.rss» anhängt. Leider werden die HTML-Tags in den Feeds gemäss RSS-Spezifikation codiert ausgeliefert (zum Beispiel wird <br> zu <br>). Ich habe bisher leider keinen RSS-Reader (oder andere Lösung) gefunden, der damit umgehen kann. Ansonsten könnten die Wetterprognosen auch auf diesen Kanälen bezogen werden – ganz ohne Mastodon- oder Fediverse-Account:
- Wetter- und Temperaturprognose (dark mode): https://tooting.ch/@meteo.rss
- Wetter- und Temperaturprognose (light mode): https://tooting.ch/@meteo_light.rss
- Windrichtungs- und Windstärkeprognose (dark mode): https://tooting.ch/@meteoplus.rss
- Windrichtungs- und Windstärkeprognose (light mode): https://tooting.ch/@meteoplus_light.rss
Falls Du eine Lösung findest, die die RSS-Feeds schön darstellt, lass es mich bitte wissen oder schreib’s in die Kommentare.
Den ganzen Python-Code hinter emoji-weather kannst Du auf GitHub anschauen.
Wenn Dein Interesse noch anhält: Im dritten und letzten Teil erkläre ich, wie ich emoji-weather auf GitHub ☁️-deploye und zeige dazu einige Fallstricke und vor allem Tricks. Falls das nicht eh schon offensichtlich ist: sind natürlich alles transferable skills… Stay tuned.
Ein Gedanke zu „Wettervorhersage in Social Media – Teil 2: Daten und Programmierung“
Kommentare sind geschlossen.