Problem mit HTMLParser, Zugriff auf Stringzeilen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Aries
User
Beiträge: 51
Registriert: Mittwoch 21. August 2013, 01:19

Hallo, ich möchte Daten aus Tabellen auf Internetseiten auslesen. Das funktioniert im Grundsatz mit HTMLParser, jedoch kommen häufig folgende Fehlermeldungen: bad start tag, bad end tag, malformed start tag. Manche Fehler, kann man in der folgenden Art verhindern:

Code: Alles auswählen

string = string.replace("?s=","?s")
string = string.replace("show=0","show")
string = string.replace("</scr' + 'ipt>","</scr>")
htmlparser1.feed(string)
Manche Fehler werden jedoch garnicht genau angegeben, und können deshalb so nicht verhindert werden.

Gibt es ein Patentrezept gegen dieses Problem?

Wie kann ich bestimmte Zeilen eines Strings löschen? (In dem Falle alle bis auf diejenigen, die die Tabelle beinhalten)
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Aries,
nimm einen HTML-Parser, der auch html versteht, z.B.: BeautifulSoup.
BlackJack

@Aries: Der `HTMLParser` aus der Standardbibliothek funktioniert nur mit korrektem HTML, also nicht wirklich mit dem was man im Netz so vorfindet. Zum parsen von „echtem” HTML nimmt man deshalb Parser die auch mit kaputtem HTML umgehen können. Die beiden verbreitetesten Pakete dafür sind `lxml.html` und `BeautifulSoup`.

Wenn man einen Parser verwendet operiert man nicht mehr auf einer Zeichenkette, sondern auf einem Objektbaum der die Struktur der Webseite repräsentiert. Man löscht dann nicht einzelne Zeilen, denn ein Element kann sich sowohl über mehrere Zeilen im HTML-Quelltext erstrecken, also auch nur einen Teil einer Zeile einer Zeile im Quelltext beanspruchen. Wenn man also eine HTML-Tabelle aus einem Dokument haben möchte, dann sucht man sich das entsprechende Wurzelelement und kann dann diesen Teilbaum weiterverarbeiten. Zum Beispiel in ein anderes Dokument, repräsentiert durch einen entsprechenden Objektbaum, einbauen und dann als HTML-Quelltext serialisieren oder nur den Teilbaum serialisieren.

Wobei eine HTML-Tabelle an sich kein komplettes gültiges HTML-Dokument ist. Man muss bei HTML damit rechnen ziemlich kaputtes Zeug aus dem Netz zu bekommen, aber wenn man selber HTML erzeugt, sollte man IMHO bessere Qualität liefern. :-)
Aries
User
Beiträge: 51
Registriert: Mittwoch 21. August 2013, 01:19

Sirius3 hat geschrieben:Hallo Aries,
nimm einen HTML-Parser, der auch html versteht, z.B.: BeautifulSoup.
Habe ich schon versucht, und bin daran gescheitert, dass ich das nicht installiert bekommen habe. Bis auf weiteres möchte ich es vermeiden, wenn es nicht unbedingt nötig ist, mein Gehirn damit weiter zu ficken.

Wenn ich den Standard-HTML-Parser nur mit der Zeichenkette der Tabelle fütter, bekomme ich die richtigen Ergebnisse. Jedoch will ich das mit hunderten verwandten Seiten machen, deswegen brauche ich eine nicht-manuelle Methode, um überfüssige Zeilen der Zeichenkette, mit der ich den HTML-Parser fütter, lösche.

Wenn ich z. B. die Zeilen 1 (0?) bis 150 eines Strings löschen will, oder einem anderen String die Zeilen 151-250 zuweisen will, wie geht das? Das zu wissen, könnte ja auch für andere Zwecke nützlich sein.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Woran ist es denn gescheitert? Wie hast Du probiert das Paket zu installieren?

Alternativ probier eben lxml, html5lib usw.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Aries hat geschrieben:Wenn ich z. B. die Zeilen 1 (0?) bis 150 eines Strings löschen will, oder einem anderen String die Zeilen 151-250 zuweisen will, wie geht das? Das zu wissen, könnte ja auch für andere Zwecke nützlich sein.
Ein String hat nicht direkt Zeilen und ist außerdem unveränderlich.

Wenn du die Daten beim Newline-Zeichen trennen möchtest, dann geht das mit split. Anschließend hast du die Bestandteile in einer Liste und kannst sie manipulieren.

Code: Alles auswählen

>>> data = 'Abc\nDef\nGhi\nKjl\nMno'
>>> lines = data.split('\n')
>>> lines
['Abc', 'Def', 'Ghi', 'Kjl', 'Mno']
>>> del lines[:2]
>>> lines
['Ghi', 'Kjl', 'Mno']
>>> lines[1] = 'Pqr'
>>> lines
['Ghi', 'Pqr', 'Mno']
>>> '\n'.join(lines)
'Ghi\nPqr\nMno'
Du solltest aber ernsthaft eine passende Bibliothek zum Parsen von HTML-ähnlichen Daten verwenden. BeautifulSoup hat sich dafür schon vielfach als geeignet erwiesen. Wenn du Installationsprobleme hast, dann solltest du die angehen statt das Rad noch mal neu zu erfinden.
Aries
User
Beiträge: 51
Registriert: Mittwoch 21. August 2013, 01:19

Danke, /me.
Hyperion hat geschrieben:Woran ist es denn gescheitert? Wie hast Du probiert das Paket zu installieren?
Ich habe es mit der Eingabeaufforderung versucht. Ich meine, die Fehlermeldung, nach der ich aufgegeben habe, war, dass der Ordner bs4 nicht gefunden werden könne. Der war aber da, wo er gefordert war.

Frage: Wenn man standardmäßig einen anderen HTML-Parser verwenden soll, warum befindet sich dann kein solcher in der Standardbibliothek?
BlackJack

@Aries: Weil es keinen Standardersatz gibt und weil die beiden am meisten eingesetzten Pakete diverse, teils optionale Abhängigkeiten haben, die auch in die Standardbibliothek aufgenommen werden müssten. Wo sich dann sozusagen rekursiv die Frage stellen würde welche von denen. Und auf so etwas wie Lizenzen müsste man auch noch mal schauen, ob man die überhaupt einfach so in die Standardbibliothek aufnehmen *kann*.

Die Frage ist eher warum es `HTMLParser` noch in der Standardbibliothek gibt. Bei Python 2.x wegen Rückwärtskompatibilität. Und bei Python 3.x hat wohl niemand ein PEP geschrieben oder das wurde abgelehnt. Die Begründung dafür müsste dann im PEP zu finden sein.

Weder die Beschreibung was Du versuchst hast, noch der Fehlermeldung hilft dabei herauszufinden woran es gescheitert ist und was man vielleicht dagegen tun kann.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Aries hat geschrieben:Ich habe es mit der Eingabeaufforderung versucht.
Das wäre dann also

Code: Alles auswählen

pip install beautifulsoup4
Sagt denn ein pip freeze, dass BeautifulSoup installiert ist?
Antworten