Ich sehe jeden Tag Fragen, wie man etwas aus einer HTML-Zeichenfolge analysiert oder extrahiert, und die erste Antwort / der erste Kommentar lautet immer "Verwenden Sie RegEx nicht zum Analysieren von HTML, damit Sie nicht den Zorn spüren!" (Dieser letzte Teil wird manchmal weggelassen).
Das ist ziemlich verwirrend für mich. Ich dachte immer, dass der beste Weg, eine komplizierte Zeichenfolge zu analysieren, im Allgemeinen die Verwendung eines regulären Ausdrucks ist. Wie funktioniert ein HTML-Parser? Verwendet es keine regulären Ausdrücke zum Parsen?
Ein besonderes Argument für die Verwendung eines regulären Ausdrucks ist, dass es nicht immer eine Parsing-Alternative gibt (z. B. JavaScript, bei dem DOMDocument keine allgemein verfügbare Option ist). jQuery zum Beispiel scheint mit einem regulären Ausdruck zum Konvertieren einer HTML-Zeichenfolge in DOM-Knoten einwandfrei zu funktionieren.
Ich bin mir nicht sicher, ob ich dies tun soll oder nicht, es ist eine echte Frage, die ich beantworten möchte und die eigentlich nicht als Diskussionsthread gedacht ist.
quelle
Antworten:
Normalerweise mit einem Tokeniser. Der Entwurf der HTML5-Spezifikation enthält einen umfangreichen Algorithmus für den Umgang mit "realem HTML".
quelle
Nun, nein.
Wenn Sie in Ihrem Gehirn auf einen Kurs zur Theorie der Berechnung zurückgreifen, wenn Sie einen Kurs oder einen Compilerkurs oder ähnliches belegt haben, können Sie sich daran erinnern, dass es verschiedene Arten von Sprachen und Rechenmodellen gibt. Ich bin nicht qualifiziert, auf alle Details einzugehen, aber ich kann einige der wichtigsten Punkte mit Ihnen besprechen.
Die einfachste Art von Sprache und Berechnung (für diese Zwecke) ist eine reguläre Sprache. Diese können mit regulären Ausdrücken generiert und mit endlichen Automaten erkannt werden. Grundsätzlich bedeutet dies, dass das "Parsen" von Zeichenfolgen in diesen Sprachen den Status, jedoch nicht den Hilfsspeicher verwendet. HTML ist sicherlich keine reguläre Sprache. Wenn Sie darüber nachdenken, kann die Liste der Tags beliebig tief verschachtelt werden. Beispielsweise können Tabellen Tabellen enthalten, und jede Tabelle kann viele verschachtelte Tags enthalten. Mit regulären Ausdrücken können Sie möglicherweise ein Paar Tags auswählen, aber sicherlich nichts, was willkürlich verschachtelt ist.
Eine klassische einfache Sprache, die nicht regulär ist, besteht aus korrekt übereinstimmenden Klammern. Versuchen Sie es wie Sie möchten, Sie werden niemals in der Lage sein, einen regulären Ausdruck (oder einen endlichen Automaten) zu erstellen, der immer funktioniert. Sie benötigen Speicher, um die Verschachtelungstiefe zu verfolgen.
Eine Zustandsmaschine mit einem Stapel für Speicher ist die nächste Stärke des Rechenmodells. Dies wird als Push-Down-Automat bezeichnet und erkennt Sprachen, die durch kontextfreie Grammatiken generiert werden. Hier können wir korrekt übereinstimmende Klammern erkennen - tatsächlich ist ein Stapel das perfekte Speichermodell dafür.
Ist das gut genug für HTML? Traurigerweise Nein. Vielleicht für Super-Duper sorgfältig validiertes XML, in dem alle Tags immer perfekt ausgerichtet sind. In echtem HTML können Sie leicht Schnipsel wie finden
<b><i>wow!</b></i>
. Dies ist offensichtlich nicht verschachtelt. Um es richtig zu analysieren, ist ein Stapel einfach nicht leistungsfähig genug.Die nächste Rechenebene sind Sprachen, die von allgemeinen Grammatiken generiert und von Turing-Maschinen erkannt werden. Es wird allgemein angenommen, dass dies das stärkste Rechenmodell ist, das es gibt - eine Zustandsmaschine mit Hilfsspeicher, deren Speicher überall geändert werden kann. Dies können Programmiersprachen. Dies ist der Grad der Komplexität, in dem HTML lebt.
Um hier alles in einem Satz zusammenzufassen: Um allgemeines HTML zu analysieren, benötigen Sie eine echte Programmiersprache, keinen regulären Ausdruck.
HTML wird genauso analysiert wie andere Sprachen: Lexing und Parsing. Der Lexing-Schritt zerlegt den Strom einzelner Zeichen in aussagekräftige Token. Der Analyseschritt fasst die Token unter Verwendung von Status und Speicher zu einem logisch zusammenhängenden Dokument zusammen, auf das reagiert werden kann.
quelle
Reguläre Ausdrücke sind nur eine Form des Parsers. Ein ehrlicher HTML-Parser ist erheblich komplizierter als in regulären Ausdrücken ausgedrückt werden kann, indem rekursiver Abstieg , Vorhersage und verschiedene andere Techniken verwendet werden, um den Text richtig zu interpretieren. Wenn Sie sich wirklich darauf einlassen möchten, sollten Sie sich lex & yacc ansehen und ähnliche Tools .
Das Verbot, Regexes für das HTML-Parsen zu verwenden, sollte wahrscheinlich korrekter geschrieben werden als: "Verwenden Sie keine naiven regulären Ausdrücke, um HTML zu analysieren ..." (damit Sie den Zorn nicht spüren) "... und behandeln Sie die Ergebnisse mit Vorsicht." Für bestimmte spezifische Ziele mag ein Regex durchaus ausreichend sein, aber Sie müssen sehr vorsichtig sein, um die Einschränkungen Ihres Regex zu kennen und so vorsichtig zu sein, wie es für die Quelle des zu analysierenden Textes angemessen ist (z. B. wenn dies der Fall ist) Benutzereingaben, seien Sie in der Tat sehr vorsichtig).
quelle
Das Parsen von HTML ist die Umwandlung eines linearen Textes in eine Baumstruktur. Reguläre Ausdrücke können im Allgemeinen keine Baumstrukturen verarbeiten. Der reguläre Ausdruck, den Sie an jedem Punkt benötigen, um das nächste Token zu erhalten, ändert sich ständig. Sie können reguläre Ausdrücke in einem Parser verwenden, benötigen jedoch für jeden möglichen Parsing-Status eine ganze Reihe regulärer Ausdrücke.
quelle
Wenn Sie eine 100% ige Lösung wünschen: Sie müssen Ihren eigenen benutzerdefinierten Code schreiben, der den HTML-Code zeichenweise durchläuft, und Sie müssen über eine enorme Menge an Logik verfügen, um zu bestimmen, ob Sie den aktuellen Knoten stoppen und den Knoten starten sollten Nächster.
Der Grund ist, dass dies gültiges HTML ist:
Aber so ist das:
Wenn Sie mit "90% -Lösung" einverstanden sind: Die Verwendung eines XML-Parsers zum Laden eines Dokuments ist in Ordnung. Oder mit Regex (obwohl die XML einfacher ist, wenn Sie dann den Inhalt beherrschen).
quelle