Kampis Elektroecke

Wetterdaten über XML

Raspberry Pi

Hier zeige ich euch wie ihr Wetterdaten von Yahoo abrufen könnt und diese mittels eines Python-Programms weiter verarbeitet. Dadurch könnt ihr euch z.B. das aktuelle Wetter ausgeben lassen, es ausdrucken, auf Websites anzeigen etc.

-> Was ist eine XML-Datei?:

Eine XML-Datei ist eine Datei, wo Daten in einer hierarchischen Struktur abgelegt sind.
Dadurch ist es möglich Daten plattformunabhängig über das Internet oder andere Computersysteme auszutauschen.
In einer XML-Datei sind die Daten als Klartext hinterlegt, was soviel heißt wie das, laut Definition, kein Binärcode etc. in der Datei vorkommen muss.
Somit kann eine XML Datei auch von einem Menschen gelesen werden.
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.
Und genau so eine Datei mache ich mir bei meinem “Wetterbericht” zu nutze.
Jetzt kann man sich die Frage stellen: “Woher weiß ich wie die XML-Datei einer Website aussieht?”
Nun dafür habe ich am Seitenende ein Programm hochgeladen, welches die URL einer beliebigen, im Programm gespeicherten XML-Datei öffnet, sie einließt und in der Konsole ausgibt.
Mittels

kann die Ausgabe anschließend in eine Textdatei namens XML-Aufbau.txt umgeleitet werden.
Dann weiß man genau wie das XML-Dokument der angegebenen Seite aussieht.

-> Das Python Programm:

So wie arbeitet das Wetterprogramm nun?
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!
Um den Zahlencode rauszufinden geht ihr auf die Website von Yahoo

-> Yahoo Wetter

und anschließend gebt ihr in dieses Feld

Wetter_XML(1)

eure Postleitzahl ein.
Mit einem Klick auf Go werdet ihr weiter geleitet und dort seht ihr das aktuelle Wetter für eure Stadt.
In der URL-Leiste erscheint dann der benötigte Zahlencode:

Wetter_XML(2)

Diesen Zahlencode müsst ihr in das Python Programm übertragen.
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:

Der Zusatz [0] gibt an, dass ich nach dem ersten Element mit dem Namen suche.
Manche Elemente (z.B. description) sind doppelt vorhanden. Um dann das zweite Element zu suchen schreibt man [1] anstatt [0].
Als Rückgabewert speicher ich eine Referenz auf das Element.
Diese Referenz ist ab sofort unter dem Namen Ort abrufbar.
Nun kann ich mittels

auf die Attribute city und country zugreifen und den Wert in einer Variable speichern.
Dabei ist der rot markierte Teil die Referenz auf das Element!
So kann das XML-Dokument Stück für Stück ausgelesen werden um alle wichtigen Daten zu erhalten.
Eine fertige Wetterausgabe für Monheim sieht dann z.B. so aus:

Wetter_XML(3)

Das komplette Skript gibt es auch wieder zum download.
Ihr könnt es dann natürlich problemlos euren Bedürfnissen anpassen :)

 

Dokumentation:

 

-> Zurück zu den Basteleien mit dem Raspberry Pi

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.