Kampis Elektroecke

Wetterdaten über XML

Raspberry Pi

Dieses Beispiel soll zeigen, wie Wetterdaten von Yahoo abrufen und mittels eines Python-Programms weiter verarbeitet werden können. Auf diese Weise kann z. B. das aktuelle Wetter auf einer Webseite oder dem Bildschirm ausgegeben werden.

Was ist eine XML-Datei?:

Eine XML-Datei ist eine Datei, die Daten, bzw. Datenstrukturen in einer hierarchischen Struktur abgelegt. Sie ermöglicht es Daten effizient über das Internet oder andere Computersysteme auszutauschen.
In einer XML-Datei sind die Daten als Klartext hinterlegt. Eine XML-Datei besteht in seiner Grundform aus mind. einer Entität und mind. einem Element. Den Elementen können anschließend noch Attribute hinzugefügt werden.
Ein sehr schönes Beispiel für eine XML-Datei findet man auf Wikipedia:

Wikipedia XML
Dabei ist <quiz></quiz> die Entität, sprich das Objekt wo die Informationen drin gespeichert sind.
Die beiden Tags <question> und <answer> sind zwei Elemente der Entität quiz.
Der Text der zwischen den beiden Tags steht (also z. B. zwischen <question> und </question>) ist der Dateninhalt.

Das Python Programm:

Als erstes wird mittels der Zeile

die angegebene URL geöffnet, ausgelesen und der Inhalt in der Variable Baum gespeichert.

Die URL ist dabei die standortbezogene URL für die Wetterdaten und der darin enthaltene Zahlencode ist dem Wohnort anzupassen! Der Zahlencode kann bei Yahoo Wetter herausgefunden werden, indem in das markierte Feld die entsprechende Postleitzahl eingetragen wird.

Nach einem Klick auf Go wird der benötigte Zahlencode in der URL-Leiste angezeigt:

Nachdem das Programm alle Daten des XML-Dokuments eingelesen hat, wandelt es diese Daten mit Hilfe der Zeile

für die interne Weiterverarbeitung in eine Baumstruktur um. Anschließend wird eine Referenz auf diesen Baum erzeugt, sprich der Baum ist unter dem Namen Baum verfügbar. Als erstes möchte ich wissen um welchen Ort es sich handelt. Wenn man sich die XML-Datei mal genauer anschaut, sieht man dort folgende Zeile:

Das Element, wo die Standortdaten gespeichert sind, heißt yweather:location.
Bei city, region und country handelt es sich um Attribute, denen ein bestimmter Wert zugeordnet wurde.
Um an die Daten zu gelangen suche ich erst nach einem Element mit dem Namen yweather:location:

Nun kann mittels

auf die Attribute city und country zugegriffen werden, um so die Werte aus dem Baum zu extrahieren. So kann das XML-Dokument Stück für Stück ausgelesen werden um alle wichtigen Daten zu erhalten.
Eine fertige Wetterausgabe für den Standort Monheim sieht dann z. B. so aus:

Wetter_XML(3)

Das komplette Skript gibt es bei GitLab zum Download.

→ Zurück Raspberry Pi


Letzte Bearbeitung: 11.10.2018

18 Kommentare

  1. Hallo Kampi, das ist eine tolle Website – weiter so!

    Ein kleiner Kommentar zur RSS Abfrage bei Yahoo:
    Du kannst Dir das Umrechnen von F in C für die Temperatur sparen, wenn Du im Python Script gleich in Celsius abfragst. Das geht mit ‘&u=c’ hinter der Abfrage. (siehe: http://developer.yahoo.com/weather/).

    Viele Grüße,
    Rudi

  2. Hallo Kampi,

    tolles Script, gefällt mir super gut.
    Aber kennst Du eine Möglichkeit die “print” Ausgaben von dem Script auf einer php-Seite des Webservers auszugeben?
    Das wäre ne coole Sache.

    Gruß Morty

  3. Hi Daniel,
    tolle Sache hier! Der Code für die Yahoodaten ist genau das was ich gesucht habe.
    Ich habe aber ein Problem beim Umsetzen. Code will nur in Python 2.7 starten, in Python 3 bringt er immer Fehler. Dachte erst es liegt an ‘ und ” aber das hat nichts geholfen. Kannst du mir dahingehend vielleicht helfen? Mein kompletter Code ist in Python 3 und da wollte ich die Wetterdaten gerne einbinden.

    Viele Grüße
    Christian

  4. Was muss ich tun, wenn ich jetzt die aktuelle Temperatur nicht nur ausgeben möchte, sondern sie auch noch in einer .txt auf meinem Webserver (auch dem Pi) speichern möchte?

  5. Hi,
    was müsste ich tun, damit die Wetterdaten in einem bestimmten Intervall z.B jede Minute automatisch neu abgefragt werden (Kein Cronjob/Änderung in der Python Datei)?
    Vielen Dank im Voraus!

      1. Ich möchte das Skript extrahieren und in eine existierende Python Datei implementieren, deswegen soll nur dieser “Wetterteil” regelmäßig aktualisiert werden.

        Bin mir nicht sicher, ob der Befehl: “updateRate = ” funktionieren würde.

  6. Hi, super Idee.

    Hast Du mal versucht das Wetter für die nächsten 3 oder 4 Tage auszulesen?
    Das steht ja in der Yahoo Weather XML drinnen.

    Dazu habe ich den Range von 2 auf 4 erhöht.
    Dann läuft das Script aber auf einen Fehler.

    Hast Du dazu eventuell eine Idee?

    Danke

    Gruß

    Marcel

    # Daten in einer Liste speichern
    for Counter in range(4):

    # Wetterdaten fuer die beiden Tage einlesen
    # Daten einlesen
    Future = Baum.getElementsByTagName(‘yweather:forecast’)[Counter]

    # Daten verarbeiten
    Wetter[Counter][0] = Future.attributes[“day”].value
    Wetter[Counter][1] = Future.attributes[“date”].value
    Wetter[Counter][2] = float(Future.attributes[“low”].value)
    Wetter[Counter][3] = float(Future.attributes[“high”].value)
    Wetter[Counter][4] = Future.attributes[“text”].value

    1. Hallo Marcel,

      ne das habe ich noch nicht probiert.
      Was bekommst du den für einen Fehler?
      So aus dem Stehgreif weiß ich nicht was da nicht läuft, aber ich habe auch das XML-File gerade nicht zur Hand :)
      Ich kann die Tage mal gucken was geändert werden muss.

  7. Danke für das Tutorial, leider bekomme ich beim Ausführen deines Skriptes (Wetter.py)folgende Fehlermeldung:

    Traceback (most recent call last):
    File “Wetter.py”, line 13, in
    Baum = urllib.urlopen(‘http://weather.yahooapis.com/forecastrss?w=675964&u=c’).read()
    File “/usr/lib/python2.7/urllib.py”, line 87, in urlopen
    return opener.open(url)
    File “/usr/lib/python2.7/urllib.py”, line 213, in open
    return getattr(self, name)(url)
    File “/usr/lib/python2.7/urllib.py”, line 350, in open_http
    h.endheaders(data)
    File “/usr/lib/python2.7/httplib.py”, line 1038, in endheaders
    self._send_output(message_body)
    File “/usr/lib/python2.7/httplib.py”, line 882, in _send_output
    self.send(msg)
    File “/usr/lib/python2.7/httplib.py”, line 844, in send
    self.connect()
    File “/usr/lib/python2.7/httplib.py”, line 821, in connect
    self.timeout, self.source_address)
    File “/usr/lib/python2.7/socket.py”, line 557, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
    IOError: [Errno socket error] [Errno -2] Name or service not known

    hast du vieleicht einen Tipp was da schief läuft ?

  8. Hier das erweiterte Script. speicher als “wetter.py”

    Dies funktioniert soweit.
    zu beachten;
    – wetter.py muss ausführbar sein
    – Die Einrückungen im Pythonscript müssen vorhanden sein
    – Es ist mir nicht gelungen die Daten von Yahoo direkt in Grad Celsius auszulesen, daher habe ich alles umgerechnet
    – Ich konnte meinen Standort auch nicht über die Kennziffer auslesen, dies ging nur mit Ort, Bundesland und Land
    dazu kann man hier testen https://developer.yahoo.com/weather/?guccounter=1
    – ausführen mit python ./wetter.py

    —————————————————–

    # Copyright by Kampis-Elektroecke
    # Modified by Julian R.
    # next Level Modification by Marcus Binz

    #!/usr/bin/env python

    from xml.dom.minidom import *
    import urllib

    # Liste fuer den Wetterbericht
    # 1. Dimension = heute, 2. Dimension = naechster Tag
    # 1. Element = Tag, 2. Element = Datum, 3. = Niedrigste Temperatur, 4. Element = Hoechste Temperatur, 5. Element = Wettersituation
    Wetter = [[“”, “”, “”, “”, “”] , [“”, “”, “”, “”, “”] , [“”, “”, “”, “”, “”] , [“”, “”, “”, “”, “”]]

    # URL oeffnen und XML Daten einlesen
    Baum = urllib.urlopen(‘https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Merchingen%2C%20SL%22)&format=xml&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys’).read()
    # XML Daten parsen und in Baumstruktur anordnen
    Baum = parseString(Baum)

    # Ort einlesen
    Ort = Baum.getElementsByTagName(‘yweather:location’)[0]
    Stadt = Ort.attributes[“city”].value
    Land = Ort.attributes[“country”].value

    # Datum einlesen
    Datum = Baum.getElementsByTagName(‘lastBuildDate’)[0].firstChild.data

    # Koordinaten auslesen
    Geo_Lat = Baum.getElementsByTagName(‘geo:lat’)[0].firstChild.data
    Geo_Long = Baum.getElementsByTagName(‘geo:long’)[0].firstChild.data

    # Wetterdaten von heute einlesen
    Today = Baum.getElementsByTagName(‘yweather:condition’)[0]

    # Wind einlesen
    Wind = Baum.getElementsByTagName(‘yweather:wind’)[0]
    Richtung = float(Wind.attributes[“direction”].value)
    Speed = float(Wind.attributes[“speed”].value)
    Speed = round((Speed*1.609),2)

    # Sonnenaufgang einlesen
    Sonne = Baum.getElementsByTagName(‘yweather:astronomy’)[0]
    Aufgang = Sonne.attributes[“sunrise”].value
    Untergang = Sonne.attributes[“sunset”].value

    # Atmosphere
    Atmosphere = Baum.getElementsByTagName(‘yweather:atmosphere’)[0]
    Luftfeuchtigkeit = float(Atmosphere.attributes[“humidity”].value)
    Luftdruck = float(Atmosphere.attributes[“pressure”].value)
    Tendenz = float(Atmosphere.attributes[“rising”].value)
    Sichtweite = float(Atmosphere.attributes[“visibility”].value)
    #Sichtweite = round((Sichtweite*1.609),2)

    # Wettertext einlesen
    Wetterlage = Today.attributes[“text”].value

    # Temperatur in Fahrenheit einlesen, umrechnen und runden
    Temperatur = float(Today.attributes[“temp”].value)
    Temperatur = round((Temperatur – 32.0) * (5.0 / 9.0) , 2)

    # Daten in einer Liste speichern
    for Counter in range(4):

    # Wetterdaten fuer die beiden Tage einlesen
    # Daten einlesen
    Future = Baum.getElementsByTagName(‘yweather:forecast’)[Counter]

    # Daten verarbeiten
    Wetter[Counter][0] = Future.attributes[“day”].value
    Wetter[Counter][1] = Future.attributes[“date”].value
    Wetter[Counter][2] = float(Future.attributes[“low”].value)
    Wetter[Counter][3] = float(Future.attributes[“high”].value)
    Wetter[Counter][4] = Future.attributes[“text”].value

    # Umrechnen der Temperatur in Grad Celsius
    Wetter[0][2] = round((Wetter[0][2] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[0][3] = round((Wetter[0][3] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[1][2] = round((Wetter[1][2] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[1][3] = round((Wetter[1][3] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[2][2] = round((Wetter[2][2] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[2][3] = round((Wetter[2][3] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[3][2] = round((Wetter[3][2] – 32.0) * (5.0 / 9.0) , 2)
    Wetter[3][3] = round((Wetter[3][3] – 32.0) * (5.0 / 9.0) , 2)

    # Umrechung Windrichtung
    if Richtung <= 22.5:
    Windrichtung = "Nord"
    elif Richtung <= 67.5:
    Windrichtung = "Nord-Ost"
    elif Richtung <= 112.5:
    Windrichtung = "Ost"
    elif Richtung <= 157.5:
    Windrichtung = "Sued-Ost"
    elif Richtung <= 202.5:
    Windrichtung = "Sued"
    elif Richtung <= 247.5:
    Windrichtung = "Sued-West"
    elif Richtung <= 292.5:
    Windrichtung = "West"
    elif Richtung <= 337.5:
    Windrichtung = "Nord-West"
    elif Richtung <= 360:
    Windrichtung = "Nord-West"
    else:
    Windrichtung = "Fehler!"

    #  

    #  

    # Ausgabe
    print ""
    print "Wetterbericht fuer " + Stadt + " in " + Land
    print "Datum: " + Datum
    print ""

    print "Koordinaten"
    print "Breitengrad: " + Geo_Lat
    print "Laengengrad: " + Geo_Long
    print ""

    print "Wetter heute"
    print "Temperatur: " + str(Temperatur) + " C Celsius"
    print "Max. Temperatur: " + str(Wetter[0][3]) + " C Celsius"
    print "Min. Temperatur: " + str(Wetter[0][2]) + " C Celsius"
    print "Wettersituation: " + Wetterlage
    print ""

    print "Windsituation"
    print "Richtung: " + Windrichtung
    print "Geschwindigkeit " + str(Speed) + " km/h"
    print ""

    print "Atmosphere"
    print "Luftfeuchtigkeit: " + str(Luftfeuchtigkeit) + "%"
    print "Luftdruck " + str(Luftdruck) + " Millibar"
    print "Tendenz " + str(Tendenz)
    print "Sichtweite " + str(Sichtweite) + " km"
    print ""

    print "Sonne"
    print "Sonnenaufgang " + Aufgang
    print "Sonnenuntergang " + Untergang
    print ""

    print "Wetter Morgen"
    print "Tag: " + Wetter[1][0]
    print "Datum: " + Wetter[1][1]
    print "Max. Temperatur: " + str(Wetter[1][3]) + " C Celsius"
    print "Min. Temperatur: " + str(Wetter[1][2]) + " C Celsius"
    print "Wetter: " + Wetter[1][4]
    print ""

    print "Wetter Uebermorgen"
    print "Tag: " + Wetter[2][0]
    print "Datum: " + Wetter[2][1]
    print "Max. Temperatur: " + str(Wetter[2][3]) + " C Celsius"
    print "Min. Temperatur: " + str(Wetter[2][2]) + " C Celsius"
    print "Wetter: " + Wetter[2][4]
    print ""

    print "Wetter in 3 Tagen"
    print "Tag: " + Wetter[3][0]
    print "Datum: " + Wetter[3][1]
    print "Max. Temperatur: " + str(Wetter[3][3]) + " C Celsius"
    print "Min. Temperatur: " + str(Wetter[3][2]) + " C Celsius"
    print "Wetter: " + Wetter[3][4]
    print ""

    # Quelle angeben
    Quelle = Baum.getElementsByTagName('link')[1].firstChild.data
    print "Alle Daten stammen von " + Quelle

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.