Pyhton3, BS4, BeautifulSoup HTML Parser Abfrage

  • Hallo Zusammen,

    ich habe mir in Python3 und BS4 einen HTML Parser für meine Heizung gebaut.
    Anbei mein Code:

    Jetzt frage ich jeden einzelnen Sensor über den Link ab und durchlaufe in Endeffekt immer wieder den selben Code.
    Das geht sicher einfacher und besser, bzw. gibt es sicher eine Möglichkeit weitere Sensoren bzw. Links in ein Array oder Dictionary zu packen und dieses mit einer Schleife abzufragen.
    Gibt es diese Möglichkeit und würde dies Sinn machen?
    Wie könnte ich am besten bei soetwas vorgehen?

    Danke

  • Hi wusa,

    wenn du die Werte weiterhin so anstatt REST-Interface abfragen möchtest, bietet sich für o.g. Code doch eine einzige Funktion an (ungetestet):

    [code=php]sensor_path = 'http://192.168.7.5:8080/user/var/120/10251/0/0/%s'

    def get_buffer_value(buffer_path):
    """Fetches buffer temperature and parses output."""
    uClient = uReq(buffer_path)
    buffer = uClient.read()
    uClient.close()

    parsed_buffer = soup(buffer, "html.parser")
    buffer_value = parsed_buffer.value
    return buffer_value.get('strvalue')[

    if __name__ == '__main__':
    buffers = ['12242', '12522', '12244']
    [get_buffer_value(sensor_path+number) for number in buffers][/php]

    Da sich der Pfad zu den Sensoren offensichtlich nur in der hintersten Nummer ändert, könntest du eine Liste dieser Nummern vorhalten und dann mit einer simplen List-Comprehension jeden Sensor einholen.

    O.g. Code kann und sollte noch verbessert werden (hinsichtlich PEP etc.) - sollte aber zur Anregung einer Lösung ausreichen.

    Mfg, sls

    “Don’t comment bad code - rewrite it.”

    Brian Kernighan

    Einmal editiert, zuletzt von sls (17. September 2017 um 20:51)

  • Hallo,

    Zitat

    Gibt es diese Möglichkeit und würde dies Sinn machen?


    Ja und ja.

    Zitat

    Wie könnte ich am besten bei soetwas vorgehen?


    Die Lösung hast du doch quasi schon selber genannt: pack' die URLs in eine Liste oder ein Dict und iterier' dann darüber.

    Und die URL ist echt strange... Wie sieht eigentlich die Seite aus, die da zurück geliefert wird?

    Gruß, noisefloor

  • Zitat von "linusg" pid='300187' dateline='1505656181'


    frage ich mich, was läuft denn da für ein Server im Hintergrund? Und hast du keine Möglichkeit, das Ganze mit einer REST-Schnittstelle zu machen?

    Das ist der Webserver meiner Heizung. Was da genau im Hintergrund läuft kann ich leider nicht sagen.
    REST Schnittstelle ist glaube ich vorhanden. Mehr dazu aber im Post weiter unten.
    Wie ich das ganze aber über diese Schnittstelle machen muss weiß ich nicht. Habe in andren Foren über die Heizung nur die Lösung über die URL gelesen.

    Zitat von "sls" pid='300222' dateline='1505672126'


    Da sich der Pfad zu den Sensoren offensichtlich nur in der hintersten Nummer ändert,

    Das ist nur bei den Puffer Werten der Fall. Es gibt noch weitere Sensoren, die sich unterscheiden. ZB. der Kesselvorlauf sieht so aus:
    http://192.168.7.5:8080/user/var/40/10021/0/0/12241
    Hier ist der Pfad zwar ähnlich aber mit ein paar Zahlen unterschiedlich.


    Zitat von "noisefloor" pid='300223' dateline='1505672231'


    Und die URL ist echt strange... Wie sieht eigentlich die Seite aus, die da zurück geliefert wird?


    Das hier ist die komplette Rückgabe von der URL:

    Code
    <eta xmlns="http://www.eta.co.at/rest/v1" version="1.0">
    <value uri="/user/var/120/10251/0/0/12242" strValue="67" unit="°C" decPlaces="0" scaleFactor="10" advTextOffset="0">672</value>
    </eta>
  • Ich denke mal, dass es keine Problem sein sollte, wenn ich dennoch BeautifulSoup nutze?
    Ich habe noch andere Sachen vor, da würde ich dann auch BeautifulSoup benutzen wollen.

    Hätte noch eine Frage zu den Links/URLs in Dictionaries.

    Müssen die Links anhand diesem Schema aufgebaut werden, oder gehe ich den falschen Weg. Finde im Internet nichts, wie ich Links in Dicts einbauen kann/soll.

    Hier ein Beispiel, welches ich im Internet zu Maßen finde:

    Code
    dict = {}
      dict['a'] = 'alpha'
      dict['g'] = 'gamma'
      dict['o'] = 'omega'

    Kann ich das quasi als Vorlage für Links verwenden?

    Code
    dict = {}
      dict['pufferoben'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12242'
      dict['puffermitte'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12522'
      dict['pufferunten'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12244'


    Würde das so gehen, oder befinde ich mich auf dem Holzweg?

  • Hallo,

    Zitat

    Ich denke mal, dass es keine Problem sein sollte, wenn ich dennoch BeautifulSoup nutze?


    Zumindest solltest du nicht explizit den HTML-Parser von BS nutzen. Das kann funktionieren, muss aber nicht. XML parst man nun mal mit einem XML-Parser. Was BS ja grundsätzlich auch kann.

    [quoteWürde das so gehen, oder befinde ich mich auf dem Holzweg?[/quote]
    Prinzipiell richtig, ABER `dict` als Variablenname ist ganz schlecht, weil du damit die eingebaute Funktion `dict` überschreibst. Was ungewünschte Nebeneffekte haben kann. Außerdem sind aussagekräftige Namen immer gut, hier also z.B. `urls` oder so was in der Art.

    Gruß, noisefloor

  • Das mit dem XML Parser in BeautifulSoup habe ich in der Doku gesehen. Das werde ich noch umbauen.

    Du meinst quasi so:

    Code
    urls = {}
      urls['pufferoben'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12242'
      urls['puffermitte'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12522'
      urls['pufferunten'] = 'http://192.168.7.5:8080/user/var/120/10251/0/0/12244'
  • Hallo Zusammen,

    ich habe meine Script jetzt auf Dictionary umgebaut.

    Leider habe ich hier ein kleines Problem.

    Anbei der Code:

    Problem hierbei ist jetzt, dass die Werte zwar ausgelesen werden, aber immer unterschiedlich:

    Ich habe das Script innerhalb ein paar Sekunden immer wieder ausgeführt.

    Jetzt habe ich aber immer die Werte an unterschiedlichen stellen.

    Kann man so etwas verhindern und wenn ja, wie?

    Ich will ja nicht meine Puffer Oben Temp in der Mitte haben.

    Danke

  • Vielen Dank!

    Das ging soweit ohne Probleme:


    Jetzt besteht nur noch ein letztes Problem... Es werden alle Werte untereinander ausgegeben. Was prinzipiell auch kein Problem ist.

    Wie könnte ich dennoch nur auf einen einzigen Wert der Ausgabe zugreifen?

    Habe es mit

    Code
    print(heizung_temperatur[1])

    getestet. Allerdings werden mir dann alle 3 Werte aber nur mit der 2ten Zahl angezeigt.

  • Allerdings werden mir dann alle 3 Werte aber nur mit der 2ten Zahl angezeigt.

    Hier die Ausgabe mit dem "normalen" Code:

    Code
    print(heizung_temperatur)
    Spoiler anzeigen

    68

    63

    42

    Dann mit dem angepassten Code wie ich es gemeint habe mit der 2ten Zahl

    Code
    print(heizung_temperatur[1])
    Spoiler anzeigen

    8

    3

    2

    Und hier deine Ausgabe:

    Code
    print(heizung_temperatur, type(heizung_temperatur))
    Spoiler anzeigen

    68 <class 'str'>

    63 <class 'str'>

    42 <class 'str'>


    Wenn ich jetzt aber zum Beispiele hinter die "64" noch etwas hinzufügen möchte, dann weiß ich nicht wie ich den Wert einzeln aus dem ?Array? oder ist das eine Auflistung von dem Dict bekomme?

    Darum dachte ich an die [1] was aber leider nicht funktioniert.

  • So ganz verstehe ich das Problem immer noch nicht, da wirst du geduldig mit mir sein müssen!

    Python
    heizung_value = heizungs_temp_soup.value
    heizung_temperatur = heizung_value.get('strvalue')
    print(heizung_temperatur)

    heizung_value ist ein dict. Dort holst du dir den Wert, der sich hinter dem Schlüssel 'strvalue' verbirgt. Es handelt sich um einen String, z.B. '68', '63', ...

    Wenn du diesen String mit slicing ausgibst, hast du logischerweise nur noch einen Teil davon. Mehrere Dinge kannst du z.B. Mit print("foo", "bar", 1, 2, [3, 4], False, True, None) ausgeben.

  • So ganz verstehe ich das Problem immer noch nicht, da wirst du geduldig mit mir sein müssen!

    Ich denke eher du wirst geduldig mit mir sein müssen.

    Ich bin froh wenn ich hier Hilfe bekomme.

    Ich versuche es nochmal zu erklären.

    Ich habe mein Dict mit den Werten die ich in der Schleife abfrage, so wie du auch schon geschrieben hast:

    Es handelt sich um einen String, z.B. '68', '63',

    In diesem String sind jetzt meine ganzen Werte 68, 63 usw... die -direkt- hintereinander ausgegeben/angezeigt werden.

    Jetzt würde ich gerne zum weiter bearbeiten einen Wert aus dem String "rausziehen". Das soll heißen, wie kann ich zum Beispiel nur den Wert 63, der an 2ter Stelle im String steht anzeigen lassen?

    Ich hoffe es ist verständlich!

  • Ich stehe nach wie vor auf dem Schlauch :conf:

    Ich habe mein Dict mit den Werten die ich in der Schleife abfrage, so wie du auch schon geschrieben hast:

    Von welchem dict reden wir genau, und was ist der genaue inhalt? Anders kommen wir hier nicht weiter...

    In diesem String sind jetzt meine ganzen Werte 68, 63 usw... die -direkt- hintereinander ausgegeben/angezeigt werden.

    Das sind die kompletten Strings! Da gibt es nichts herauszuziehen. In jedem loop ist der String einer deiner Werte, mehr nicht.

  • Vielleicht ist das Beispiel besser.

    Wie kann ich die einzelnen Werte z.B. beschriften:

    68 + Puffer Fühler oben

    63 + Puffer Fühler unten

    Ich frage ja alle Werte auf einmal in der "for" Schleife ab.

    Dann ist die gesamte Ausgabe auf einmal vorhanden.

    68

    63

    42

    .... usw.

    Kann ich jetzt die einzelnen Werte, die ausgegeben werden noch "beschriften"?

  • Na, so ist es doch mal gut erklärt :thumbup:

    Ersetze den for loop durch das:

    Python
    for name in urls.keys():
        uClient = uReq(urls[name])
        heizungs_temp = uClient.read()
        uClient.close()
        heizungs_temp_soup = soup(heizungs_temp, "html.parser")
        heizung_value = heizungs_temp_soup.value
        heizung_temperatur = heizung_value.get('strvalue')
        print("{0}: {1} °C".format(name, heizung_temperatur))

    Wenn du jetzt die Keys noch änderst:

    Python
    urls['Puffer oben']='http://192.168.7.5:8080/user/var/120/10251/0/0/12242'

    statt

    Python
    urls['pufferoben']='http://192.168.7.5:8080/user/var/120/10251/0/0/12242'

    usw. ist's vielleicht noch ein bisschen schöner. Meinst du das? ;)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!