Erhalten von Positionsinformationen beim Parsen von HTML in Python

Ich versuche, einen Weg zu finden, um (möglicherweise fehlerhaftes) HTML in Python zu analysieren und, wenn eine Reihe von Bedingungen erfüllt ist, das Dokument mit der Position (Zeile, Spalte) auszugeben. Die Positionsinformation ist das, was mich hier oben auslöst. Und um es klar zu sagen, ich muss keinen Objektbaum erstellen. Ich möchte einfach nur bestimmte Daten und deren Position im Originaldokument finden (denken Sie an eine Rechtschreibprüfung, zum Beispiel: 'Wort "foo" in Zeile x, Spalte y, ist falsch geschrieben)'

ls Beispiel möchte ich so etwas (mit ElementTree's Target API):

import xml.etree.ElementTree as ET

class EchoTarget:
    def start(self, tag, attrib):
        if somecondition():
            print "start", tag, attrib, self.getpos()
    def end(self, tag):
        if somecondition():
            print "end", tag, self.getpos()
    def data(self, data):
        if somecondition():
            print "data", repr(data), self.getpos()

target = EchoTarget()
parser = ET.XMLParser(target=target)
parser.feed("<p>some text</p>")
parser.close() 

Allerdings, soweit ich das beurteilen kann, diegetpos() -Methode (oder so ähnlich) existiert nicht. Und dazu wird natürlich ein XML-Parser verwendet. Ich möchte möglicherweise fehlerhaftes HTML analysieren.

nteressanterweise ist das HTMLParser class in der Python Standard Lib bietet Unterstützung für das Abrufen der Standortinformationen (mit einemgetpos() Methode), aber es ist schrecklich bei der Handhabung von fehlerhaftem HTML und wurde als mögliche Lösung beseitigt. Ich muss HTML-Code analysieren, der im richtigen Wort vorhanden ist, ohne den Parser zu beschädigen.

Mir sind zwei HTML-Parser bekannt, die sich gut zum Parsen von fehlerhaftem HTML eignen, nämlich lxml und html5lib. Tatsächlich würde ich es vorziehen, eine dieser Optionen gegenüber anderen in Python verfügbaren Optionen zu verwenden.

Html5lib bietet jedoch, soweit ich das beurteilen kann, keine Ereignis-API und würde erfordern, dass das Dokument in ein Baumobjekt geparst wird. Dann müsste ich durch den Baum iterieren. Zu diesem Zeitpunkt besteht natürlich keine Zuordnung zum Quelldokument, und alle Standortinformationen gehen verloren. Html5lib ist also raus, was schade ist, da es der beste Parser für den Umgang mit fehlerhaftem HTML zu sein scheint.

Die lxml-Bibliothek bietet eine Target-API, die hauptsächlich die von ElementTree widerspiegelt. Ich kenne jedoch keine Möglichkeit, auf Standortinformationen für jedes Ereignis zuzugreifen. Ein Blick in den Quellcode lieferte ebenfalls keine Hinweise.

lxml bietet auch eine API für SAX-Ereignisse. Interessanterweise erwähnt Pythons Standardbibliothek, dass SAX @ unterstützLocator Objects, bietet aber wenig Dokumentation zur Verwendung. DiesSO Frage bietet einige Informationen (bei Verwendung eines SAX-Parsers), aber ich sehe keinen Zusammenhang mit der eingeschränkten Unterstützung für SAX-Ereignisse, die lxml bietet.

Endlich, bevor jemand @ vorschlächöne Sup, Ich werde darauf hinweisen, dass, wie auf der Homepage angegeben, "Beautiful Soup auf den beliebten Python-Parsern wie lxml und html5lib sitzt". Alles, was es mir gibt, ist ein Objekt zum Extrahieren von Daten ohne Verbindung zum ursprünglichen Quelldokument. Wie bei html5lib gehen alle Standortinformationen verloren, wenn ich auf die Daten zugreifen kann. Ich möchte / brauche direkten Zugriff auf den Parser.

Um das eingangs erwähnte Beispiel der Rechtschreibprüfung zu erweitern, möchte ich nur die Rechtschreibung von Wörtern im Dokumenttext überprüfen (aber nicht die Namen oder Attribute von Tags) und möglicherweise den Inhalt bestimmter Tags (z. B. das Symbol) überspringen Skript- oder Code-Tags). Deshalb brauche ich einen echten HTML-Parser. Ich bin jedoch nur an der Position der falsch geschriebenen Wörter im Originalquelldokument interessiert, wenn es darum geht, die falsch geschriebenen Wörter zu melden, und ich muss kein Baumobjekt erstellen. Dies ist nur ein Beispiel für eine mögliche Verwendung. Ich kann es für etwas völlig anderes verwenden, aber die Bedürfnisse wären im Wesentlichen die gleichen. Tatsächlich habe ich einmal etwas sehr ähnliches mit HTMLParser erstellt, es aber nie verwendet, da die Fehlerbehandlung für diesen Anwendungsfall nicht funktionieren würde. Das war vor Jahren, und ich habe diese Akte anscheinend irgendwo auf der ganzen Linie verloren. Dieses Mal möchte ich stattdessen lxml oder html5lib verwenden.

Also, fehlt mir etwas? Es fällt mir schwer zu glauben, dass keiner dieser Parser (abgesehen vom meist unbrauchbaren HTMLParser) Zugang zu den Positionsinformationen hat. Aber wenn sie es tun, muss es undokumentiert sein, was mir komisch vorkommt.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage