Frage

Ich erstelle eine Anwendung, die eine URL als Eingabe wird, rufen Sie die HTML-Inhalt der Seite aus dem Web und Extrakt alles, was nicht in einem Tag enthalten ist . Mit anderen Worten, der Textinhalt der Seite, wie sie in den Besuchern auf dieser Seite zu sehen. Dazu gehört ‚Maskieren‘ aus allem abgekapselt in <script></script>, <style></style> und <!-- -->, da diese Abschnitte Text enthalten, die nicht innerhalb von einem Tag umhüllt ist (aber ist am besten allein gelassen).

Ich habe diese Regex aufgebaut:

(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>)

Sie wählt richtig alle Inhalte, dass ich ignorieren wollen, und nur verlässt den Textinhalt der Seite. Aber das bedeutet, dass, was ich zu extrahieren möchte nicht in der Match-Sammlung zeigen (I VB.Net in Visual Studio 2010 bin mit).

Gibt es eine Möglichkeit, „Invert“ die Anpassung eines gesamten Dokuments wie diese, so dass ich Streichhölzer auf allen Textstrings bekommen würde, die durch die Anpassungs in der obigen regex weggelassen sind?

Bisher was ich tat, war eine andere Alternative am Ende hinzufügen, dass wählt „eine beliebige Sequenz, die nicht enthalten “, was bedeutet dann die übrig gebliebenen Text. Ich nannte das letzte Bit in einer Capture-Gruppe, und als ich Iterierte über die Spiele, überprüfe ich auf das Vorhandensein von Text in der „Text“ -Gruppe. Dies funktioniert, aber ich frage mich, ob es möglich war, sie alle durch regex zu tun und nur mit Streichhölzern auf dem Klartext am Ende.

Dies soll allgemein arbeiten, ohne in dem HTML-Code keine spezifischen Tags zu kennen. Es soll zu extrahieren alle Text. Außerdem muss ich die ursprüngliche html erhalten, so dass die Seite alle seine Verbindungen und Skripte behält - i nur den Text in der Lage sein müssen, um zu extrahieren, dass ich Durchsuchungen und Ersatz innerhalb sie durchführen können, ohne Angst vor „Umbenennen“ alle Tags, Attribute oder Skriptvariablen usw. (so kann ich nicht nur tun, ein auf allen Spielen ich werde, „mit nichts ersetzen“, denn auch wenn ich dann bin übrig geblieben, was ich brauche, ist es ein Streit ist, dass wieder in die richtigen Stellen der wieder einzuführen voll funktionsfähiges Dokument).

Ich möchte wissen, ob dies überhaupt möglich mit regex ist (und ich weiß, über HTML Agility Pack and XPath, aber nicht das Gefühl wie).

Irgendwelche Vorschläge?

Update: Hier ist die (regex-basierte) Lösung, die ich am Ende mit: http://www.martinwardener.com/regex/ , in einer Demo-Web-Anwendung implementiert, die sowohl die aktiven regulären Ausdrücke zusammen mit einem Test-Engine zeigen Ihnen die Analyse auf jedem Online-hTML-Seite ausführen können, geben Sie mal und extrahiert Ergebnisse analysieren (für Link, uRL und Text einzeln Portionen -. sowie Ansichten, wo all Regex-Übereinstimmungen in Platz in dem vollständigen HTML-Dokument markiert)

War es hilfreich?

Lösung 5

OK, also hier ist, wie ich es so mache:

Mit meiner ursprünglichen regex (mit dem zusätzlichen Suchmuster für den Klartext, die einen beliebigen Text sein geschieht, die nach dem Tag übrig gesucht fertig sind):

(?:(?:<(?P<tag>script|style)[\s\S]*?</(?P=tag)>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>))|(?P<text>[^<>]*)

Dann in VB.Net:

Dim regexText As New Regex("(?:(?:<(?<tag>script|style)[\s\S]*?</\k<tag>>)|(?:<!--[\s\S]*?-->)|(?:<[\s\S]*?>))|(?<text>[^<>]*)", RegexOptions.IgnoreCase)
Dim source As String = File.ReadAllText("html.txt")
Dim evaluator As New MatchEvaluator(AddressOf MatchEvalFunction)
Dim newHtml As String = regexText.Replace(source, evaluator)

Die eigentliche Text ersetzen geschieht hier:

Private Function MatchEvalFunction(ByVal match As Match) As String
    Dim plainText As String = match.Groups("text").Value
    If plainText IsNot Nothing AndAlso plainText <> "" Then
        MatchEvalFunction = match.Value.Replace(plainText, plainText.Replace("Original word", "Replacement word"))
    Else
        MatchEvalFunction = match.Value
    End If
End Function

Voila. newHtml enthält nun eine exakte Kopie des Originals, mit Ausnahme jedes Vorkommen von „Original Wort“ in der Seite (wie es in einem Browser dargestellt wird) wird mit „Replacement Wort“ umgeschaltet und alle HTML und Script-Code ist unberührt erhalten. Natürlich könnte man / würde in einer aufwendigeren Ersatz Routine gesetzt, aber dies zeigt das Grundprinzip. Dies ist 12 Zeilen Code, einschließlich Funktionsdeklaration und das Laden von HTML-Code, usw. würde ich mir sehr zu sehen, eine parallele Lösung interessiert sein, in DOM getan etc zum Vergleich (ja, ich weiß, dieser Ansatz kann durch sicher Vorkommen einiger verschachtelten Tags Macken - in SCRIPT Umschreiben - aber der Schaden aus, dass nach wie vor sehr begrenzt sein werden, wenn überhaupt, und im allgemeinen (einige der Kommentare, siehe oben) wird dies ziemlich den Job verdammt gut ).

Andere Tipps

, was ich tat, war eine andere Alternative am Ende hinzufügen, dass wählt „eine beliebige Sequenz, die nicht < oder > enthält“, das bedeutet dann die übrig gebliebenen Text. Ich nannte die letzte Bit in einer Capture-Gruppe, und als ich Iterierte über die Spiele, überprüfe ich auf das Vorhandensein von Text in der „Text“ Gruppe.

Das ist, was man normalerweise tun würde. Oder noch einfacher, ersetzen Sie jedes Spiel des Markup-Musters mit und leeren String und was du hast links ist der Stoff, den Sie suchen.

Es Art von Arbeiten, aber es scheint eine Zeichenfolge, hier zu sein und dort, die abgeholt wird das soll nicht sein.

Nun ja, das ist, weil Ihr Ausdruck und regex in unzureichend allgemeinen ist auch gültig HTML zu analysieren, geschweige denn die Schrecken, die dort aus auf der realen Web. Erster Tipp zu sehen, wenn Sie auch wirklich diesen vergeblichen Ansatz jagen wollen. Attributwerte (sowie Textinhalte im Allgemeinen) kann ein Unescaped > Zeichen enthalten

Ich möchte noch einmal auf die Vorteile von HTML Agility-Pack vor.

ETA:., Da Sie scheinen es zu wollen, hier einige Beispiele von Markup, das aussieht wie es wird Ihr Ausdruck stolpern

<a href=link></a> - unquoted
<a href= link></a> - unquoted, space at front matched but then required at back
<a href="~/link"></a> - very common URL char missing in group
<a href="link$!*'link"></a> - more URL chars missing in group
<a href=lïnk></a> - IRI
<a href
    ="link"> - newline (or tab)
<div style="background-image: url(link);"> - unquoted
<div style="background-image: url( 'link' );"> - spaced
<div style="background-image: u&#114;l('link');"> - html escape
<div style="background-image: ur\l('link');"> - css escape
<div style="background-image: url('link\')link');"> - css escape
<div style="background-image: url(\
'link')"> - CSS folding
<div style="background-image: url
('link')"> - newline (or tab)

und das ist nur vollständig gültig Markup, dass nicht den richtigen Link entsprechen, nicht der möglichen ungültigen Markup, Markup, das nicht, sollten aber einen Link übereinstimmt, oder eines der vielen Probleme mit dem anderen Technik des Splitting-Markup von Text. Dies ist die Spitze des Eisbergs.

Regex ist nicht zuverlässig für das Abrufen von Textinhalten von HTML-Dokumenten. Regex kann nicht verschachtelte Tags verarbeiten. ein Dokument Gesetzt erfordert keine verschachtelten Tag enthalten, regex noch alle Tags richtig geschlossen sind.

Wenn Sie PHP verwenden, der Einfachheit halber, empfehle ich Ihnen dringend, DOM (Document Object Model) zu verwenden, HTML-Dokumente zu analysieren / extrahieren. DOM-Bibliothek besteht in der Regel in jeder Programmiersprache.

Wenn Sie Extrakt Teile einer Zeichenfolge gesuchte nicht durch eine regex abgestimmt, können Sie einfach die Teile ersetzen, die sind abgestimmt mit einem leeren String für den gleichen Effekt.

Beachten Sie, dass der einzige Grund, dies funktionieren könnte, weil die Tags, die Sie daran interessiert sind, zu entfernen, <script> und <style> Tags, nicht verschachtelt werden können.

Allerdings ist es nicht ungewöhnlich für eine <script> Tag-Code programmatisch Anfügen eines anderen <script> Tag zu enthalten, wobei in diesem Fall Ihre regex fehl. Es wird auch in dem Fall nicht, wo jeder Tag nicht richtig geschlossen ist.

Sie können nicht Parsing HTML mit regulären Ausdrücken.

Parsing HTML mit regulären Ausdrücken führt zu Traurigkeit.

Ich weiß, Sie tun es nur zum Spaß, aber es gibt so viele Pakete gibt, als tatsächlich das Parsen den richtigen Weg zu tun, und tue es zuverlässig und getestet wurde.

Gehen Sie nicht, das Rad neu zu erfinden, und es eine Art und Weise zu tun, dass alles ist aber zu vereiteln Sie auf der Straße gewährleistet.

Zur Information:

Statt Regex, mit JQuery, ist es möglich zu extrahieren Text allein aus einem HTML-Markup. Für Sie, dass folgende Muster verwenden können.

$("<div/>").html("#elementId").text()

können Sie beziehen sich diese JSFIDDLE

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top