XML/HTML-Beispiele¶
HTML¶
Python verfügt über zahlreiche Bibliotheken zum Lesen und Schreiben von Daten in den allgegenwärtigen HTML- und XML-Formaten. Beispiele sind lxml, Beautiful Soup und html5lib. Während lxml im Allgemeinen vergleichsweise viel schneller ist, können die anderen Bibliotheken besser mit fehlerhaften HTML- oder XML-Dateien umgehen.
pandas hat eine eingebaute Funktion, read_html, die Bibliotheken wie lxml, html5lib und Beautiful Soup verwendet, um automatisch Tabellen aus HTML-Dateien als DataFrame-Objekte zu parsen. Diese müssen zusätzlich installiert werden. Mit Spack könnt ihr lxml, BeautifulSoup und html5lib in eurem Kernel bereitstellen:
$ spack env activate python-311
$ spack install py-lxml py-beautifulsoup4~html5lib~lxml py-html5lib
Alternativ könnt ihr BeautifulSoup auch mit anderen Paketmanagern installieren, z.B.
$ uv add lxml beautifulsoup4 html5lib
Um zu zeigen, wie das funktioniert, verwende ich eine HTML-Datei der Wikipedia, die einen Überblick über verschiedene Serialisierungsformate gibt.
[1]:
import pandas as pd
tables = pd.read_html(
"https://docs.python.org/3/library/xml.dom.html",
)
Die Funktion pandas.read_html hat eine Reihe von Optionen, aber standardmäßig sucht sie nach allen Tabellendaten, die in <table>-Tags enthalten sind, und versucht, diese zu analysieren. Das Ergebnis ist eine Liste von DataFrame-Objekten:
[2]:
len(tables)
[2]:
3
[3]:
xml_idl = tables[2]
xml_idl.head()
[3]:
| IDL Type | Python Type | |
|---|---|---|
| 0 | boolean | bool or int |
| 1 | int | int |
| 2 | long int | int |
| 3 | unsigned int | int |
| 4 | DOMString | str or bytes |
Von hier aus können wir einige Datenbereinigungen und -analysen vornehmen, wie z.B. die Anzahl der verschiedenen Schema-IDL:
[4]:
xml_idl["Python Type"].value_counts()
[4]:
Python Type
int 3
bool or int 1
str or bytes 1
Name: count, dtype: int64
XML¶
pandas hat eine Funktion read_xml, wodurch das Lesen von XML-Dateien sehr einfach wird:
[5]:
pd.read_xml("books.xml")
[5]:
| id | title | language | author | license | date | |
|---|---|---|---|---|---|---|
| 0 | 1 | Python basics | en | Veit Schiele | BSD-3-Clause | 2021-10-28 |
| 1 | 2 | Jupyter Tutorial | en | Veit Schiele | BSD-3-Clause | 2019-06-27 |
| 2 | 3 | Jupyter Tutorial | de | Veit Schiele | BSD-3-Clause | 2020-10-26 |
| 3 | 4 | PyViz Tutorial | en | Veit Schiele | BSD-3-Clause | 2020-04-13 |
lxml¶
Alternativ kann auch zunächst lxml.objectify zum Parsen von XML-Dateien verwendet werden. Dabei erhalten wir mit getroot einen Verweis auf den Wurzelknoten der XML-Datei:
[6]:
from pathlib import Path
from lxml import objectify
parsed = objectify.parse(Path.open("books.xml"))
root = parsed.getroot()
[7]:
books = []
for element in root.book:
data = {}
for child in element.getchildren():
data[child.tag] = child.pyval
books.append(data)
[8]:
pd.DataFrame(books)
[8]:
| title | language | author | license | date | |
|---|---|---|---|---|---|
| 0 | Python basics | en | Veit Schiele | BSD-3-Clause | 2021-10-28 |
| 1 | Jupyter Tutorial | en | Veit Schiele | BSD-3-Clause | 2019-06-27 |
| 2 | Jupyter Tutorial | de | Veit Schiele | BSD-3-Clause | 2020-10-26 |
| 3 | PyViz Tutorial | en | Veit Schiele | BSD-3-Clause | 2020-04-13 |