Blog der Heimetli Software AG

Mit Python Werte aus einer HTML-Seite auslesen

Seit ich HTML-Seite auslesen mit Python geschrieben habe, ist doch schon einige Zeit vergangen.

Seither habe ich Beautiful Soup entdeckt, und der Support für Python 2 geht langsam zu Ende.

Die Struktur der HTML-Seite

Die HTML-Seite bleibt genau gleich wie beim letzten Post:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Eine Tabelle mit Variablen</title>
 </head>
 <body>
  <table>
   <tr>
    <td class="name">Spannung</td><td class="value">13</td>
   </tr>
   <tr>
    <td class="name">Strom</td><td class="value">31</td>
   </tr>
  </table>
 </body>
</html>

Die Inhalte der td-Elemente werden extrahiert, und das class-Attribut gibt an, was der String sein soll. class="name" gibt an, dass die Zelle einen Variablennamen enthält, während class="value" den Wert der Variablen bezeichnet.

Um das Script relativ einfach zu halten, kann es nur eine Variable pro Zeile der Tabelle geben. Weitere Zellen mit beliebigem Inhalt sind dagegen erlaubt, so lange sie keinen der beiden Attributwerte haben.

Was macht das Script ?

Das Script erwartet ein oder mehrere URLs auf der Kommandozeile. Die entsprechenden Seiten werden geladen und die Variablen gesammelt:

pi@raspberrypi ~ $ python fetchsoup.py http://192.168.1.222/test/variables.html
Spannung = 13
Strom = 31
pi@raspberrypi ~ $ 

Das Script

Das Script wurde mit Python 3.7.2 auf Knoppix (Debian) geschrieben und dort auch getestet.

Im Vergleich zur alten Version ist es sehr viel kürzer und auch besser zu verstehen. Beautiful Soup erzeugt einen DOM-Baum im Speicher, in dem die gesuchten Elemente mit einfachen Aufrufen gefunden werden können.

Speziell herauszuheben ist die Bezeichnung class_ bei den Argumenten von find_all. Das ist nötig weil class ein Reserved Word von Python ist.

Interessant ist auch die Selektion des zweiten Elements in der gleichen Row. Durch den Umweg über den Parent kann das Element an einer beliebigen Position in der Zeile stehen.

Ein weiterer Vorteil von Beautiful Soup: Entities wie &#x2103; (℃) werden expandiert.

"""This script reads a HTML page and extracts variable names and values.

   The names and values are encoded as table cells with class-attributes
   like this:

   <tr>
    <td class="name">Voltage</td><td class="value">13</td>
   </tr>

   The number of variables in the file is not limited, but only one
   variable definition per table row is allowed.

   V2.00  19-NOV-2019 Te
"""

import sys
from urllib.request import urlopen
from bs4 import BeautifulSoup

def processpage( url ):
    """Reads and parses one URL from the command line."""
    try:
        html = urlopen( url ) 
        soup = BeautifulSoup( html.read(), features = "lxml" )

        elements = soup.find_all( "td", class_ = "name" )

        for element in elements:
            sibling = element.parent.find( "td", class_ = "value" )

            if sibling != None:
                print( f"{element.string} = {sibling.string}" )

    except Exception as exception:
        print( f"Error: {url} {exception}" )

if __name__ == "__main__":
    for url in sys.argv[1:]:
        processpage( url )

Ueber diesen Link können Sie fetchsoup.py herunterladen.