{"id":1396,"date":"2020-10-23T13:09:38","date_gmt":"2020-10-23T11:09:38","guid":{"rendered":"https:\/\/www.rustimation.eu\/?p=1396"},"modified":"2025-05-17T12:06:22","modified_gmt":"2025-05-17T10:06:22","slug":"nochmal-update-wetterbericht-im-json-format-auslesen-und-verarbeiten","status":"publish","type":"post","link":"https:\/\/www.rustimation.eu\/index.php\/nochmal-update-wetterbericht-im-json-format-auslesen-und-verarbeiten\/","title":{"rendered":"Zweites Update: Wetterbericht im JSON Format auslesen und verarbeiten"},"content":{"rendered":"<p><em><strong>Da Darksky von Apple \u00fcbernommen wurde, kann man keine neuen kostenlosen Accounts mehr anlegen. Deshalb hier das zweite Update, diesmal mit dem kostenfreien Service <a href=\"http:\/\/openweathermap.org\">Openweathermap<\/a>.<\/strong><br \/>\n<\/em><\/p>\n<h2>Update vom 2. Update:<\/h2>\n<p><strong>April 2024:<\/strong> Die API Version 2.5 l\u00e4uft im Juni 2024 aus und wird mit Version 3.0 ersetzt. Der Service ist bis zu 1000 Abrufen\/Tag immer noch kostenlos, aber man muss den Service trotzdem mit einer Kreditkarte abonnieren (subscribe). Wenn man unter den 1000 Abrufen\/Tag bleibt, wird die Karte nicht belastet. Funktionell bleibt alles beim Alten. d.h. im Aufruf muss lediglich die API\u00a0 Version von 2.5 auf 3.0 ge\u00e4ndert werden. Der API Key bleibt unver\u00e4ndert. Dieser Beitrag wurde daher insgesamt auf den neuesten Stand gebracht.<\/p>\n<p>Also zum Beispiel: <span class=\"lang:default decode:true crayon-inline\">https:\/\/api.openweathermap.org\/data\/<strong>3.0<\/strong>\/onecall?lat={lat}&amp;lon={lon}&amp;exclude={part}&amp;appid={API key}<\/span><\/p>\n<p>Nach der Subscription dauert es u.U. ein paar Stunden, bis der API Key umgestellt ist und die Abrufe mit 3.0 klappen.<\/p>\n<p>Code wurde auf auf Python 3.x portiert.<\/p>\n<p><!--more--><\/p>\n<p style=\"text-align: center;\">-.-.-.-.-.-.-.-.-.-.-.-.-<\/p>\n<p>In meine <a title=\"rusticam Le Fasse - Lago di Garda\" href=\"http:\/\/rusticam.eu\" target=\"_blank\" rel=\"noopener noreferrer\">Webcam <\/a>m\u00f6chte ich einen Wetterbericht mit einigen Tagen Vorausschau einblenden.<\/p>\n<p>Die bisher von mir verwendete Webservices von <em>Weather Underground <\/em>und <em>Darksky.net\u00a0<\/em> stellen keine neuen kostenfreien APIs mehr zur Verf\u00fcgung. Ich bin deshalb auf Openweathermap umgestiegen, in der Hoffnung, dass der Service etwas l\u00e4nger bestehen bleibt.<\/p>\n<p><a href=\"https:\/\/openweathermap.org\/\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>Openweathermap.org<\/strong><\/a> ist ein sehr m\u00e4chtiger Service mit aktuellem Wetter, stundengenauer 4 Tage Vorhersage, 16 Tage Vorhersage, Klimavorhersage \u00fcber 30 Tage und inzwischen gibt es auch die sogenannte \"One Call API\" mit vielen kostenfreien Features wie minutengenauer Vorhersage f\u00fcr die n\u00e4chste Stunde, 7 Tage Vorhersage, 5 Tages R\u00fcckschau etc. Die Wettertexte sind leider nicht ganz so ausf\u00fchrlich wie die von Darksky.<\/p>\n<p>Die 7 Tage Vorhersage aus der One Call API ist genau das, was ich brauche.<\/p>\n<p><strong>Mondphasen gibt es hier leider keine<\/strong>: vielleicht etwas nerdig, aber ich will sowieso eine m\u00f6glichst genaue Anzeige der Mondphase und der sichtbaren Mondoberfl\u00e4che in Prozent. Ich <a href=\"https:\/\/www.rustimation.eu\/index.php\/mondphase-und-beleuchtung-ausrechnen\/\">errechne deshalb die Mondphase selbst<\/a>.<\/p>\n<p><strong>Update April 2024<\/strong>: Wie ich beim Ansehen der neuen API gemerkt habe, wird jetzt auch die Montphase als <a href=\"https:\/\/www.rustimation.eu\/index.php\/mondphase-und-beleuchtung-ausrechnen\/\" target=\"_blank\" rel=\"noopener\">numerischer Wert<\/a> ausgegeben.<\/p>\n<h2>Schritt 1: Account anlegen<\/h2>\n<p>Surft zu <a href=\"https:\/\/home.openweathermap.org\/users\/sign_in\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/home.openweathermap.org\/users\/sign_in<\/a> und klickt den Button \"Create an account\" an.<\/p>\n<p>Die Registrierung ist selbsterkl\u00e4rend. Am Schluss erhaltet ihr euren eigenen geheimen API Schl\u00fcssel [key] der Art \"700416988c7436cd5abc92c328d2b320\". Mit diesem Schl\u00fcssel m\u00fcsst ihr euch bzw. euer Programm bei k\u00fcnftigen Abfragen ausweisen.<\/p>\n<p>Seit 2024 muss man sich mit einer Kreditkarte registrieren. Bleibt man unter der 1000er Freigrenze, wird die Karte nicht belastet.<\/p>\n<h2>Schritt 2: Webservice ansprechen<\/h2>\n<p>Irgendwie m\u00fcssen die Daten aus dem Webservice in Python eingelesen werden. Daf\u00fcr gibt es in Python Standardmethoden. Mit der standardm\u00e4\u00dfig vorhandenen urllib2 Library habe ich mich allerdings etwas schwer getan. Die neuere\u00a0 Library \"Requests\" ist meines Erachtens leichter zu bedienen, enth\u00e4lt netterweise auch die ben\u00f6tigten JSON Funktionen, muss aber erst noch installiert werden. Doch keine Angst, die Installation ist unkompliziert:<\/p>\n<blockquote><p><em>Requests is an elegant and simple HTTP library for Python, built for human beings.<\/em><\/p><\/blockquote>\n<p>Der Entwickler empfiehlt, das Paket mit\u00a0 <code>pip <\/code>zu installieren &#8211; ich w\u00fcrde dazu aber die Raspbian hauseigene Paketverwaltung verwenden :<\/p>\n<p><span class=\"lang:default decode:true crayon-inline \">sudo apt install python3-requests<\/span><\/p>\n<p>Damit haben wir die unten stehenden \"pip\"-Probleme nicht.<\/p>\n<p style=\"padding-left: 40px;\"><span style=\"color: #808080;\">Der Vollst\u00e4ndigkeit halber und f\u00fcr den Fall, dass <em>apt install<\/em> nicht funkioniert, noch die \"pip\"-Methode:<\/span><\/p>\n<pre class=\"\" style=\"padding-left: 40px;\"><span style=\"color: #808080;\">sudo pip3 install requests<\/span><\/pre>\n<p style=\"padding-left: 40px;\"><span style=\"color: #808080;\">Wenn es zu einer Fehlermeldung kommt, weil <code>pip <\/code>noch nicht installiert ist, dann muss das <code>pip <\/code>Paket ebenfalls installiert werden &#8211; am besten gleich noch sicherstellen, dass ein weiteres wichtiges Entwicklerpaket mit installiert wird:<\/span><\/p>\n<pre class=\"lang:sh decode:1 inline:1\" style=\"padding-left: 40px;\"><span style=\"color: #808080;\">sudo apt install python3-pip python3-dev<\/span><\/pre>\n<p style=\"padding-left: 40px;\"><span style=\"color: #808080;\">anschlie\u00dfend <code>requests <\/code>wie oben dargestellt installieren.<\/span><\/p>\n<p style=\"padding-left: 40px;\"><span style=\"color: #808080;\">Kommt es dann noch zum ber\u00fcchtigten \"Externally Managed Environment\" Fehler, beachtet bitte diese Hinweise<span style=\"color: #ff0000;\"> <a style=\"color: #ff0000;\" href=\"https:\/\/www.rustimation.eu\/index.php\/python-das-externally-managed-environment-problem\/\" target=\"_blank\" rel=\"noopener\"><span style=\"color: #993300;\">in einem anderen Artikel <\/span><\/a><\/span>meines Blogs.<\/span><\/p>\n<p>Wer tiefer einsteigen will: weitere Info gibts bei <a href=\"https:\/\/2.python-requests.org\/en\/latest\/user\/install\/\" target=\"_blank\" rel=\"noopener noreferrer\">Python Requests<\/a>.<\/p>\n<p>Damit ist euer Pi f\u00fcr die folgenden Schritte ger\u00fcstet.<\/p>\n<h2>Schritt 3: JSON verarbeiten<\/h2>\n<p>Bez\u00fcglich der Openweathermap angebotenen Daten und deren Struktur gibt es eine gute Dokumentation auf deren Site\u00a0 <a href=\"https:\/\/openweathermap.org\/api\/one-call-api\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/openweathermap.org\/api\/one-call-api<\/a>.<\/p>\n<h4>a: Das JSON Format anschauen<\/h4>\n<p>Um das Prinzip zu verdeutlichen, nehmen wir uns f\u00fcr den Anfang den allgemeinen Wetter\u00fcberblick vor.<\/p>\n<p>Gebt zuerst einmal folgende Zeile in euren <strong>Browser<\/strong> ein:<\/p>\n<pre class=\"expand:true lang:sh decode:true\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"html\">https:\/\/api.openweathermap.org\/data\/3.0\/onecall?lat=48.1404&amp;lon=11.5583&amp;units=metric&amp;lang=de&amp;appid=DeinenGeheimenKey<\/code><\/pre>\n<p>Nach dem Fragezeichen werden die Aufrufparameter \u00fcbergeben. Zuerst kommen die\u00a0 Geokoordinaten (lan\/lon bzw. Breite und L\u00e4nge) f\u00fcr den Ort, f\u00fcr den ihr die heutigen Wetterdaten wissen wollt &#8211; in diesem Beispiel ist es der Hauptbahnhof M\u00fcnchen. Die weiteren Parameter werden dann untereinander durch ein Ampersand \"&amp;\" getrennt werden. Beim obigen Beispiel ist das die Sprache (lang=de) sowie metrische Einheiten ( &amp;units=metric) und zum Schluss anstatt <em>DeinenGeheimenKey<\/em> nat\u00fcrlich euer eigener, vorhin generierter Key.<\/p>\n<p><strong>Hinweis<\/strong>: Geokoordinaten bekommt ihr heraus, indem ihr bei Google Maps die gew\u00fcnschte Gegend anzeigt und dann einen Rechtsklick auf die Stelle macht, deren Koordinaten ihr wissen wollt. Dann \"was ist hier\" ausw\u00e4hlen. In einem kleinen Popup unten auf der Karte werden dann die Geokoordinaten schon im richtigen Format angezeigt. Diese einfach \u00fcbernehmen und in die Codezeile eintragen.<\/p>\n<p>Ich arbeite praktisch nur mit dem Firefox Browser, da wei\u00df ich wenigstens, dass mein Surfverhalten nicht weiterverkauft wird &#8211; anders als bei Chrome oder Edge. Firefox hat eine sehr gute eingebaute Darstellung des empfangenen JSON Objekts. Edge und Chome k\u00f6nnen das \u00fcbrigens von Haus aus nicht.<\/p>\n<p>Das im Firefox Browser angezeigte Ergebnis f\u00fcr den 23. Oktober 2020 ist dann wie folgt, wobei ich hier der \u00dcbersichtlichkeit halber die Daten f\u00fcr <em>minutely <\/em>und <em>hourly<\/em> eingeklappt habe:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1398 size-large\" src=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/10\/2020-10-23-11_51_17-Mozilla-Firefox-367x1024.jpg\" alt=\"\" width=\"367\" height=\"1024\" srcset=\"https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/10\/2020-10-23-11_51_17-Mozilla-Firefox-367x1024.jpg 367w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/10\/2020-10-23-11_51_17-Mozilla-Firefox-107x300.jpg 107w, https:\/\/www.rustimation.eu\/wordpress\/wp-content\/uploads\/2020\/10\/2020-10-23-11_51_17-Mozilla-Firefox.jpg 434w\" sizes=\"auto, (max-width: 367px) 100vw, 367px\" \/><\/p>\n<p>Diese wundersch\u00f6n strukturierten Informationen k\u00f6nnen wir in Python jetzt ganz elegant verarbeiten.<\/p>\n<p><strong>Exkurs<\/strong>: Auch eine sch\u00f6n lesbare Struktur erhaltet ihr mit meinem Lieblingseditor Notepad++, der allerdings noch \u00fcber den Plugin Manager die Erweiterung \"JSON Viewer\" bekommen muss. Notepad++ gibts kostenlos im Internet. Tante Google fragen.<br \/>\nDazu den Men\u00fcpunkt <em>Erweiterungen<\/em> ausw\u00e4hlen und dann auf <em>Plugin Manager<\/em> gehen. Dort dann unter dem Tab <em>Available<\/em> den JSON Viewer ausw\u00e4hlen und auf <em>Install<\/em> klicken.<br \/>\nZum Ansehen, den JSON String aus dem Browser in ein Bearbeitungsfenster von Notepad++ reinkopieren, mit der Maus komplett markieren und dann unter <em>Erweiterungen<\/em> &#8211; <em>JSON Viewer<\/em> &#8211; <em>Format JSON<\/em> anklicken. Et voil\u00e0, JSON ist so noch besser anzusehen.<br \/>\nGanz toll ist auch der Online JSON Editor bei <a href=\"http:\/\/jsoneditoronline.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/jsoneditoronline.org\/<\/a><\/p>\n<h3>b: Ein JSON Ojekt erzeugen<\/h3>\n<p>In die erste Zeile unseres Progr\u00e4mmchens kommt das \"<a title=\"Shebang! Oder wie man Python wegl\u00e4sst\" href=\"http:\/\/www.rustimation.eu\/index.php\/shebang-oder-wie-man-python-weglaesst\/\">Shebang<\/a>\" f\u00fcr Python. Dann noch die Codierung f\u00fcr UTF-8<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"python\">!\/usr\/bin\/python\r\n#coding=UTF-8<\/pre>\n<p>Anschlie\u00dfend wird die soeben installierte Requests Bibliothek importiert<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\" data-enlighter-language=\"python\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">import requests<\/code><\/pre>\n<p>Zun\u00e4chst einmal m\u00fcssen wir den Webservice mit dem oben ausprobierten Aufruf ansprechen und den gelieferten Output einem Python Objekt [hier: r] zuweisen.<\/p>\n<pre class=\"expand:true lang:python decode:true EnlighterJSRAW\">r=requests.get(\"https:\/\/api.openweathermap.org\/data\/3.0\/onecall?lat=48.1404&amp;lon=11.5583&amp;units=metric&amp;lang=de&amp;exclude=minutely,hourly&amp;appid=DeinKey\")<\/pre>\n<p>Damit kann man allerdings herzlich wenig anfangen. Das Objekt muss noch als JSON String geparsed (d.h. zergliedert) werden:<\/p>\n<pre class=\"lang:python decode:1 inline:1 \">data = r.json()<\/pre>\n<p><code>data <\/code>ist ein Python Dictionary Objekt und enth\u00e4lt den ganzen JSON String , nicht besonders sch\u00f6n anzusehen, aber komplett.<\/p>\n<p>Hier noch das ganze Code Snippet:<\/p>\n<pre class=\"expand:true lang:python decode:true EnlighterJSRAW\">#!\/usr\/bin\/python\r\n#coding=UTF-8\r\n\r\nimport requests\r\n\r\n#get webservice data\r\nr = requests.get(\"https:\/\/api.openweathermap.org\/data\/3.0\/onecall?lat=48.1404&amp;lon=11.5583&amp;units=metric&amp;lang=de&amp;exclude=minutely,hourly&amp;appid=DeinKey\", timeout=120)\r\ndata = r.json() # data contains the parsed JSON string\r\nprint (data)\r\nr.close()<\/pre>\n<p>und hier der Output davon:<\/p>\n<pre class=\"height-set:true height:250 wrap:true lang:sh decode:true EnlighterJSRAW\">{u'timezone_offset': 7200, u'lon': 10.74, u'daily': [{u'wind_speed': 1.46, u'clouds': 87, u'dew_point': 10.03, u'temp': {u'min': 10.41, u'max': 12.64, u'eve': 12.33, u'morn': 10.98, u'night': 12.64, u'day': 11.78}, u'uvi': 2.31, u'pop': 0.77, u'humidity': 89, u'pressure': 1020, u'weather': [{u'main': u'Rain', u'id': 501, u'icon': u'10d', u'description': u'M\\xe4\\xdfiger Regen'}], u'sunset': 1603469870, u'rain': 10.15, u'dt': 1603450800, u'wind_deg': 49, u'feels_like': {u'eve': 12.31, u'morn': 9.92, u'day': 10.81, u'night': 12.41}, u'sunrise': 1603431871}, {u'wind_speed': 2.03, u'clouds': 67, u'dew_point': 10.66, u'temp': {u'min': 11.8, u'max': 15.22, u'eve': 12.36, u'morn': 11.92, u'night': 11.86, u'day': 15.22}, u'uvi': 2.47, u'pop': 0.96, u'humidity': 74, u'pressure': 1017, u'weather': [{u'main': u'Rain', u'id': 501, u'icon': u'10d', u'description': u'M\\xe4\\xdfiger Regen'}], u'sunset': 1603556173, u'rain': 5.72, u'dt': 1603537200, u'wind_deg': 12, u'feels_like': {u'eve': 10.56, u'morn': 12.25, u'day': 14.01, u'night': 9.1}, u'sunrise': 1603518354}, {u'wind_speed': 1.96, u'clouds': 1, u'dew_point': 8.78, u'temp': {u'min': 10.04, u'max': 14.68, u'eve': 11.87, u'morn': 10.04, u'night': 11.54, u'day': 14.68}, u'uvi': 2.14, u'pop': 0.04, u'humidity': 67, u'pressure': 1015, u'weather': [{u'main': u'Clear', u'id': 800, u'icon': u'01d', u'description': u'Klarer Himmel'}], u'sunset': 1603642476, u'dt': 1603623600, u'wind_deg': 217, u'feels_like': {u'eve': 11.42, u'morn': 6.36, u'day': 12.99, u'night': 11.03}, u'sunrise': 1603604837}, {u'wind_speed': 1.16, u'clouds': 92, u'dew_point': 9.98, u'temp': {u'min': 10.59, u'max': 12.32, u'eve': 11.38, u'morn': 11.36, u'night': 10.59, u'day': 12.32}, u'uvi': 1.91, u'pop': 1, u'humidity': 85, u'pressure': 1007, u'weather': [{u'main': u'Rain', u'id': 502, u'icon': u'10d', u'description': u'Starker Regen'}], u'sunset': 1603728781, u'rain': 23.99, u'dt': 1603710000, u'wind_deg': 52, u'feels_like': {u'eve': 9.97, u'morn': 10.27, u'day': 11.52, u'night': 9.67}, u'sunrise': 1603691321}, {u'wind_speed': 6.84, u'clouds': 88, u'dew_point': 5.37, u'temp': {u'min': 7.22, u'max': 10.57, u'eve': 8.15, u'morn': 8.67, u'night': 7.22, u'day': 8.46}, u'uvi': 2.12, u'pop': 1, u'humidity': 80, u'pressure': 1007, u'weather': [{u'main': u'Rain', u'id': 501, u'icon': u'10d', u'description': u'M\\xe4\\xdfiger Regen'}], u'sunset': 1603815087, u'rain': 8.88, u'dt': 1603796400, u'wind_deg': 16, u'feels_like': {u'eve': 4.09, u'morn': 5.11, u'day': 2.59, u'night': 3.22}, u'sunrise': 1603777805}, {u'wind_speed': 0.86, u'clouds': 36, u'dew_point': 3.51, u'temp': {u'min': 5.93, u'max': 11.52, u'eve': 8.64, u'morn': 5.93, u'night': 7.8, u'day': 11.52}, u'uvi': 2.03, u'pop': 0, u'humidity': 57, u'pressure': 1016, u'weather': [{u'main': u'Clouds', u'id': 802, u'icon': u'03d', u'description': u'M\\xe4\\xdfig bew\\xf6lkt'}], u'sunset': 1603901394, u'dt': 1603882800, u'wind_deg': 259, u'feels_like': {u'eve': 6.32, u'morn': 0.76, u'day': 9.47, u'night': 4.57}, u'sunrise': 1603864289}, {u'wind_speed': 1.23, u'clouds': 71, u'dew_point': 3.93, u'temp': {u'min': 6.37, u'max': 11.3, u'eve': 8.74, u'morn': 6.37, u'night': 8.5, u'day': 11.3}, u'uvi': 2.07, u'pop': 0, u'humidity': 60, u'pressure': 1022, u'weather': [{u'main': u'Clouds', u'id': 803, u'icon': u'04d', u'description': u'\\xdcberwiegend bew\\xf6lkt'}], u'sunset': 1603987703, u'dt': 1603969200, u'wind_deg': 142, u'feels_like': {u'eve': 7.03, u'morn': 1.75, u'day': 9.09, u'night': 5.65}, u'sunrise': 1603950774}, {u'wind_speed': 0.79, u'clouds': 100, u'dew_point': 4.3, u'temp': {u'min': 7.08, u'max': 12.37, u'eve': 9.74, u'morn': 7.08, u'night': 9.07, u'day': 12.37}, u'uvi': 2.03, u'pop': 0, u'humidity': 57, u'pressure': 1026, u'weather': [{u'main': u'Clouds', u'id': 804, u'icon': u'04d', u'description': u'Bedeckt'}], u'sunset': 1604074013, u'dt': 1604055600, u'wind_deg': 192, u'feels_like': {u'eve': 7.93, u'morn': 2.75, u'day': 10.52, u'night': 6.69}, u'sunrise': 1604037259}], u'current': {u'wind_speed': 0.5, u'clouds': 75, u'dew_point': 9.47, u'temp': 11.56, u'uvi': 2.31, u'visibility': 1800, u'humidity': 87, u'pressure': 1021, u'weather': [{u'main': u'Rain', u'id': 501, u'icon': u'10d', u'description': u'M\\xe4\\xdfiger Regen'}, {u'main': u'Mist', u'id': 701, u'icon': u'50d', u'description': u'Tr\\xfcb'}], u'sunset': 1603469870, u'rain': {u'1h': 1.42}, u'dt': 1603448772, u'wind_deg': 0, u'feels_like': 11.11, u'sunrise': 1603431871}, u'lat': 45.66, u'timezone': u'Europe\/Rome'}<\/pre>\n<h3>c: Einzelne JSON Elemente ansprechen<\/h3>\n<p>Um beispielsweise direkt die Stunde des Sonnenaufgangs anzusprechen und in eine Variable hineinzuschreiben, muss man sich ganz einfach durch die Hierarchie des Directory Elements hangeln. An oberster Stelle kommt <code>daily<\/code> dann die fortlaufende Nummer, wobei <code>0<\/code> f\u00fcr den aktuellen Tag steht und schlie\u00dflich das Element<\/p>\n<pre class=\"lang:default decode:1 inline:1 \">sunrise<\/pre>\n<p>In Python ausgedr\u00fcckt sieht das so aus:<\/p>\n<pre class=\"lang:python decode:true\">sunrise_time = data['daily'][0]['sunrise']\r\n<\/pre>\n<p>Die Zeit wird allerdings als UNIX Zeitstempel, eine 10stellige Zahl,\u00a0 ausgegeben. Zur lesbaren Darstellung kann man diesen Wert mittels <em>strftime<\/em> nat\u00fcrlich gleich konvertieren. Hierzu muss allerdings noch \"datetime\" aus der <em>datetime<\/em> Bibliothek\u00a0 importiert werden.<\/p>\n<pre class=\"lang:default decode:1 inline:1 \">from datetime import datetime as dt<\/pre>\n<p>Die darin steckenden Routinen brauchen wir sp\u00e4ter auch noch f\u00fcr die Anzeige des Wochentags. Das <em>as dt<\/em> ist nur eine wahlfreie Abk\u00fcrzung zur Vermeidung von Schreibarbeit.<\/p>\n<pre class=\"lang:default decode:true EnlighterJSRAW\"> sunrise_time = dt.fromtimestamp(data['daily'][0]['sunrise']).strftime('%H:%M')<\/pre>\n<p><strong>Hinweis<\/strong>: Openweathermap bezieht sich bei den Zeitangaben immer auf die Zeit des Ortes, dessen Koordinaten man eingegeben hat. Es ist also keine Konversion von UTC (<a href=\"https:\/\/www.timeanddate.com\/worldclock\/timezone\/utc\">Universal Time Coordinated<\/a>) n\u00f6tig. Die Zeitstempel f\u00fcr die einzelnen Tages-Wetterberichte beziehen sich immer auf 0 Uhr Ortszeit.<\/p>\n<h4>d: Iteration<\/h4>\n<p>Bei iterativen Daten, z.B. der Wettervorhersage f\u00fcr heute und die n\u00e4chsten 7 Tage kann man das nat\u00fcrlich auch per Schleife auslesen. Die Schleife l\u00e4uft \u00fcber den Wert 'day' in der zweiten Ebene<\/p>\n<pre class=\"lang:python decode:1 inline:1\">['daily'][day]<\/pre>\n<p>also die Stelle, bei der wir vorhin nur die \"0\" verwendet haben.<\/p>\n<pre class=\"expand:true lang:python decode:true EnlighterJSRAW\">#!\/usr\/bin\/python\r\n#coding=UTF-8\r\n\r\n###############################################\r\n# Portiert auf Python 3.x und Raspbian Bookworm\r\n###############################################\r\n\r\nimport requests\r\nfrom datetime import datetime as dt\r\nfrom datetime import date\r\n\r\n#UTF-8 assignments\r\ndegreeChar = u'\\N{DEGREE SIGN}'\r\n\r\n# inits\r\nfcast = [] # create array\r\nwdays = [\"Mo\",\"Di\",\"Mi\",\"Do\",\"Fr\",\"Sa\",\"So\"]\r\n\r\nr = requests.get(\"https:\/\/api.openweathermap.org\/data\/3.0\/onecall?lat=48.14&amp;lon=11.55&amp;units=metric&amp;lang=de&amp;exclude=minutely,hourly&amp;appid=HierKommtDeinKeyHin\", timeout=120)\r\ndata = r.json() # data contains the parsed JSON string\r\nr.close()\r\n\r\n# Get sunrise\/set in readable format\r\nsunrise_time = dt.fromtimestamp(data['daily'][0]['sunrise']).strftime('%H:%M')\r\nsunset_time = dt.fromtimestamp(data['daily'][0]['sunset']).strftime('%H:%M')\r\n\r\n# daily forecast today plus next 7 days\r\nfor day in data['daily']:\r\n        fcdaytext = day['weather'][0]['description']\r\n        fcdegmax = day['temp']['max']\r\n        fcdegmin = day['temp']['min']\r\n        fcweekday = date.fromtimestamp(day['dt']).weekday()\r\n        fctext = \"%s: %s %1.0f%sC\/%1.0f%sC\" % (wdays[fcweekday],fcdaytext,fcdegmax,degreeChar,fcdegmin,degreeChar)\r\n        fcast.append(fctext)  # for further processing\r\n        print (\"%s %1.0f%sC\/%1.0f%sC\" % (fctext,fcdegmax,degreeChar,fcdegmin,degreeChar))\r\n### end get forecast\r\n\r\nprint (\"Sonnenaufgang: %s, Sonnenuntergang: %s\" % (sunrise_time, sunset_time))\r\n<\/pre>\n<p>Beim <em>requests<\/em> Statement habe ich noch einen 120 Sekunden Timeout eingebaut, damit das Programm bei einem Abrufproblem nicht ewig h\u00e4ngt. Am besten f\u00e4ngt man Zugriffsfehler mit<em> try:\u00a0<\/em> <em>except:<\/em>\u00a0 Bl\u00f6cken ab.<\/p>\n<p>Der Array <code>fcst[x]<\/code> enth\u00e4lt die Wettervorhersage f\u00fcr den Tag 0 bis 7, also acht Tage. Diese Daten k\u00f6nnt ihr nach Belieben in euren Programmen weiterverwenden.<\/p>\n<p>Ich pers\u00f6nlich verwende nur die ersten vier Tage des Wetterberichts. Hier ist die Eintrittswahrscheinlichkeit noch relativ gro\u00df.<\/p>\n<p>Das Gradzeichen ist im normalen Zeichensatz nicht vorhanden und wird \u00fcber <code class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">degreeChar = u'\\N{DEGREE SIGN}'<\/code> erzeugt.<\/p>\n<p>Der Output sieht dann hoffentlich so \u00e4hnlich wie hier aus.<\/p>\n<pre class=\"lang:python decode:true EnlighterJSRAW\">Fr: M\u00e4\u00dfiger Regen 16\u00b0C\/12\u00b0C 16\u00b0C\/12\u00b0C\r\nSa: M\u00e4\u00dfiger Regen 14\u00b0C\/9\u00b0C 14\u00b0C\/9\u00b0C\r\nSo: Klarer Himmel 17\u00b0C\/6\u00b0C 17\u00b0C\/6\u00b0C\r\nMo: M\u00e4\u00dfiger Regen 9\u00b0C\/6\u00b0C 9\u00b0C\/6\u00b0C\r\nDi: M\u00e4\u00dfiger Regen 8\u00b0C\/5\u00b0C 8\u00b0C\/5\u00b0C\r\nMi: Leichter Regen 10\u00b0C\/3\u00b0C 10\u00b0C\/3\u00b0C\r\nDo: Leichter Regen 12\u00b0C\/6\u00b0C 12\u00b0C\/6\u00b0C\r\nFr: Leichter Regen 15\u00b0C\/9\u00b0C 15\u00b0C\/9\u00b0C\r\nSonnenaufgang: 07:45, Sonnenuntergang, 18:10<\/pre>\n<p>Bei Interesse einfach tiefer bei Openweathermap graben, es gibt da alle m\u00f6glichen Wetter-Informationen.<\/p>\n<p>Dieser Beitrag wurde inspiriert von der wirklich gut gemachten Site <a href=\"http:\/\/www.pythonforbeginners.com\/scraping\/scraping-wunderground\" target=\"_blank\" rel=\"noopener noreferrer\">http:\/\/www.pythonforbeginners.com\/scraping\/scraping-wunderground <\/a>wobei auch diese Seite jetzt veraltet sein d\u00fcrfte.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mit einem Raspberry Pi und Python einen Wetter-Webservice auslesen, interpretieren und weiterverarbeiten.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,9,10],"tags":[95,106,49,51],"class_list":["post-1396","post","type-post","status-publish","format-standard","hentry","category-json","category-python","category-raspberry-pi","tag-darksky","tag-open-weathermap","tag-weather-underground","tag-wetterbericht"],"_links":{"self":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1396","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/comments?post=1396"}],"version-history":[{"count":1,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1396\/revisions"}],"predecessor-version":[{"id":3531,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/posts\/1396\/revisions\/3531"}],"wp:attachment":[{"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/media?parent=1396"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/categories?post=1396"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rustimation.eu\/index.php\/wp-json\/wp\/v2\/tags?post=1396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}