RegEx stimmt mit offenen Tags überein, mit Ausnahme von in sich geschlossenen XHTML-Tags

Nov 14 2009

Ich muss alle diese Eröffnungs-Tags abgleichen:

<p>
<a href="foo">

Aber nicht diese:

<br />
<hr class="foo" />

Ich habe mir das ausgedacht und wollte sicherstellen, dass ich es richtig verstanden habe. Ich fange nur das ein a-z.

<([a-z]+) *[^/]*?>

Ich glaube es heißt:

  • Finden Sie dann einen weniger als
  • Suchen (und erfassen) Sie az dann ein- oder mehrmals
  • Suchen Sie dann null oder mehr Leerzeichen
  • Finde jedes Zeichen null oder mehrmals, gierig, außer /dann
  • Finde ein Größer als

Habe ich das richtig Und was denkst du noch wichtiger?

Antworten

4413 bobince Nov 14 2009 at 06:04

Sie können [X] HTML nicht mit Regex analysieren. Weil HTML nicht durch Regex analysiert werden kann. Regex ist kein Tool, mit dem HTML korrekt analysiert werden kann. Wie ich hier schon so oft in HTML- und Regex-Fragen beantwortet habe, können Sie mit der Verwendung von Regex kein HTML verwenden. Reguläre Ausdrücke sind ein Werkzeug, das nicht ausgereift genug ist, um die von HTML verwendeten Konstrukte zu verstehen. HTML ist keine reguläre Sprache und kann daher nicht durch reguläre Ausdrücke analysiert werden. Regex-Abfragen sind nicht in der Lage, HTML in seine sinnvollen Teile zu zerlegen. so oft, aber es geht mir nicht auf die Nerven. Selbst verbesserte unregelmäßige reguläre Ausdrücke, wie sie von Perl verwendet werden, sind nicht in der Lage, HTML zu analysieren. Du wirst mich niemals zum Knacken bringen. HTML ist eine Sprache von ausreichender Komplexität, die nicht durch reguläre Ausdrücke analysiert werden kann. Selbst Jon Skeet kann HTML nicht mit regulären Ausdrücken analysieren. Jedes Mal, wenn Sie versuchen, HTML mit regulären Ausdrücken zu analysieren, weint das unheilige Kind das Blut von Jungfrauen, und russische Hacker pwn Ihre Webapp. Das Parsen von HTML mit Regex-Beschwörungen befleckte Seelen in das Reich der Lebenden. HTML und Regex gehören zusammen wie Liebe, Ehe und ritueller Kindsmord. Das <Center> kann es nicht halten, es ist zu spät. Die Kraft von Regex und HTML zusammen im selben konzeptuellen Raum wird Ihren Geist zerstören wie so viel wässriger Kitt. Wenn Sie HTML mit Regex analysieren, geben Sie ihnen und ihren blasphemischen Methoden nach, die uns alle zur unmenschlichen Arbeit für denjenigen verurteilen, dessen Name nicht in der mehrsprachigen Grundebene ausgedrückt werden kann. HTML-plus-Regexp wird die Nerven des Lebewesens verflüssigen, während Sie beobachten, wie Ihre Psyche im Ansturm des Grauens verdorrt. Rege̿̔̉x-basierte HTML-Parser sind der Krebs, der StackOverflow tötetEs ist zu spät. Es ist zu spät. Wir können nicht gerettet werden. Die Übertretung eines Kindes stellt sicher, dass Regex das gesamte lebende Gewebe verbraucht (mit Ausnahme von HTML, das es nicht kann, wie zuvor vorhergesagt). Sehr geehrter Herr, helfen Sie uns, wie jemand diese Geißel mit Regex zum Parsen überleben kann HTML hat die Menschheit zu einer Ewigkeit der Angst Folter und Sicherheitslücken verurteilt mit Rege x als Instrument zum Prozess HTML stellt eine Brea ch zwischen dieser Welt und der Furcht Reich der korrupten Entitäten (wie SGML Entitäten, sondern mehr korrupt) einem bloßen glimp se die Welt der reg ex - Parser für HTML wird ins tantly Transport ap Bewusstsein rogrammer des i nto aw orl d unaufhörlichen schreien, er kommt , die pestilent sl Ithy regex-Infektion wil l verschlingen Ihre HT ML - Parser, Anwendung und Existenz nur alle Zeit wie Visual Basic schlimmer er kommt er com es nicht fi ght h e kommt, HALLO s unheilige Radiance de stro҉ying alle aufklärung, HTML - Tags Undichte von Ih re Augen wie liq uid p ain, das Lied von REGULAR exp Re ssion Parsing wird ExtI die Stimmen von mor nguish tal Mann aus dem sp hier sehe ich es kann man sehen , um es schön t ist er f inal snufFing o f die Lüge s des Menschen alles verloren A LL I SL OST th e PONY er kommt s er CoM es ihn zusammen ich st er mich oder Permeats es al l MY FAC E MEIN GESICHT ᵒh Gott n o NO noo O ON Θ Anschlag t er einen * ̶͑̾̾ gl és n ot rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ T O͇̹̺ͅƝ̴ȳ̳ TH̘ Ë͖́̉ ̯͍̭P̯͍̭O̚ N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ S̨̥̫͎̭ͯ̿̔̀ͅ ͎a̧͈͖r̽̾̈́͒͑e


Haben Sie versucht, stattdessen einen XML-Parser zu verwenden?


Anmerkung des Moderators

Dieser Beitrag ist gesperrt, um unangemessene Änderungen an seinem Inhalt zu verhindern. Der Beitrag sieht genau so aus, wie er aussehen soll - es gibt keine Probleme mit seinem Inhalt. Bitte kennzeichnen Sie es nicht für unsere Aufmerksamkeit.

3294 KaitlinDuckSherwood Nov 14 2009 at 13:27

Während beliebiges HTML mit nur einem regulären Ausdruck unmöglich ist, ist es manchmal angebracht, sie zum Parsen eines begrenzten, bekannten Satzes von HTML zu verwenden.

Wenn Sie eine kleine Gruppe von HTML-Seiten haben, von denen Sie Daten kratzen und dann in eine Datenbank einfügen möchten, funktionieren reguläre Ausdrücke möglicherweise einwandfrei. Zum Beispiel wollte ich kürzlich die Namen, Parteien und Bezirke der australischen Bundesvertreter erfahren, die ich von der Website des Parlaments erhalten habe. Dies war ein begrenzter, einmaliger Job.

Regexes funktionierte gut für mich und war sehr schnell einzurichten.

2082 VladGudim Nov 19 2009 at 01:42

Ich denke, der Fehler hier ist, dass HTML eine Chomsky-Typ-2-Grammatik (kontextfreie Grammatik) ist und ein regulärer Ausdruck eine Chomsky-Typ-3-Grammatik (reguläre Grammatik) ist . Da eine Typ-2-Grammatik grundsätzlich komplexer ist als eine Typ-3-Grammatik (siehe Chomsky-Hierarchie ), ist es mathematisch unmöglich , XML mit einem regulären Ausdruck zu analysieren.

Aber viele werden es versuchen und einige werden sogar Erfolg beanspruchen - aber bis andere den Fehler finden und dich total durcheinander bringen.

1363 JustinMorgan Mar 09 2011 at 00:49

Hör nicht auf diese Jungs. Sie können kontextfreie Grammatiken mit Regex vollständig analysieren, wenn Sie die Aufgabe in kleinere Teile aufteilen. Sie können das richtige Muster mit einem Skript generieren, das diese in der folgenden Reihenfolge ausführt:

  1. Lösen Sie das Halteproblem.
  2. Quadriere einen Kreis.
  3. Erarbeiten Sie das Problem des Handlungsreisenden in O (log n) oder weniger. Wenn es mehr als das ist, wird Ihnen der Arbeitsspeicher ausgehen und die Engine wird hängen bleiben.
  4. Das Muster ist ziemlich groß. Stellen Sie daher sicher, dass Sie einen Algorithmus haben, der zufällige Daten verlustfrei komprimiert.
  5. Fast da - teilen Sie das Ganze einfach durch Null. Kinderleicht.

Ich habe den letzten Teil selbst noch nicht ganz beendet, aber ich weiß, dass ich näher komme. Es wirft CthulhuRlyehWgahnaglFhtagnExceptionaus irgendeinem Grund immer wieder s, also werde ich es auf VB 6 portieren und verwenden On Error Resume Next. Ich werde mit dem Code aktualisieren, sobald ich diese seltsame Tür untersucht habe, die sich gerade in der Wand geöffnet hat. Hmm.

PS Pierre de Fermat fand auch heraus, wie es geht, aber der Rand, in den er schrieb, war nicht groß genug für den Code.

1087 itsadok Nov 15 2009 at 13:37

Haftungsausschluss : Verwenden Sie einen Parser, wenn Sie die Option haben. Das gesagt...

Dies ist der reguläre Ausdruck, den ich (!) Zum Abgleichen von HTML-Tags verwende:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>

Es mag nicht perfekt sein, aber ich habe diesen Code durch viel HTML ausgeführt. Beachten Sie, dass es sogar seltsame Dinge auffängt <a name="badgenerator"">, die im Web auftauchen.

Ich denke, damit es nicht mit in sich geschlossenen Tags übereinstimmt, möchten Sie entweder Kobis negativen Blick hinter sich lassen:

<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+(?<!/\s*)>

oder einfach kombinieren, wenn und wenn nicht.

An Downvoter: Dies ist Arbeitscode von einem tatsächlichen Produkt. Ich bezweifle, dass jemand, der diese Seite liest, den Eindruck bekommt, dass es gesellschaftlich akzeptabel ist, Regexes in HTML zu verwenden.

Vorsichtsmaßnahme : Ich sollte beachten, dass dieser reguläre Ausdruck bei Vorhandensein von CDATA-Blöcken, Kommentaren sowie Skript- und Stilelementen immer noch zusammenbricht. Eine gute Nachricht ist, dass Sie diese mit einem regulären Ausdruck loswerden können ...

509 xanatos Mar 08 2011 at 20:30

Es gibt Leute, die Ihnen sagen, dass die Erde rund ist (oder dass die Erde ein abgeflachter Sphäroid ist, wenn sie seltsame Wörter verwenden möchten). Sie lügen.

Es gibt Leute, die Ihnen sagen, dass reguläre Ausdrücke nicht rekursiv sein sollten. Sie begrenzen dich. Sie müssen dich unterwerfen, und sie tun es, indem sie dich in Unwissenheit halten.

Sie können in ihrer Realität leben oder die rote Pille nehmen.

Wie Lord Marshal (er ist ein Verwandter der Klasse Marshal .NET?), Ich habe das gesehen Underverse Stapel Based Regex-Verse und mit zurück Kräfte Wissen Sie können sich nicht vorstellen. Ja, ich glaube, es gab ein oder zwei Alte, die sie beschützten, aber sie sahen Fußball im Fernsehen, also war es nicht schwierig.

Ich denke, der XML-Fall ist recht einfach. Die RegEx (in der .NET-Syntax), die in base64 deflationiert und codiert ist, um das Verständnis für Ihren schwachen Verstand zu erleichtern, sollte ungefähr so ​​aussehen:

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
+r/vD34mUADO1P4/AQAA//8=

Die einzustellenden Optionen sind RegexOptions.ExplicitCapture. Die von Ihnen gesuchte Erfassungsgruppe ist ELEMENTNAME. Wenn die Erfassungsgruppe ERRORnicht leer ist, ist ein Analysefehler aufgetreten und der Regex wurde gestoppt.

Wenn Sie Probleme haben, es in einen für Menschen lesbaren regulären Ausdruck umzuwandeln, sollte dies helfen:

static string FromBase64(string str)
{
    byte[] byteArray = Convert.FromBase64String(str);

    using (var msIn = new MemoryStream(byteArray))
    using (var msOut = new MemoryStream()) {
        using (var ds = new DeflateStream(msIn, CompressionMode.Decompress)) {
            ds.CopyTo(msOut);
        }

        return Encoding.UTF8.GetString(msOut.ToArray());
    }
}

Wenn Sie sich nicht sicher sind, nein, ich mache keine Witze (aber vielleicht lüge ich). Es wird klappen. Ich habe Tonnen von Komponententests gebaut, um es zu testen, und ich habe sogar (einen Teil) der Konformitätstests verwendet . Es ist ein Tokenizer, kein ausgewachsener Parser, daher wird das XML nur in seine Komponententoken aufgeteilt. DTDs werden nicht analysiert / integriert.

Oh ... wenn Sie den Quellcode des regulären Ausdrucks mit einigen Hilfsmethoden möchten:

Regex zum Tokenisieren einer XML-Datei oder des vollständigen normalen Regex

304 kenorb Feb 15 2010 at 07:55

In der Shell können Sie HTML mit sed analysieren :

  1. Turing.sed
  2. HTML-Parser schreiben (Hausaufgaben)
  3. ???
  4. Profitieren!

Verwandte (warum Sie Regex Match nicht verwenden sollten):

  • Wenn Sie reguläre Ausdrücke so sehr mögen, warum heiraten Sie sie nicht?
  • Reguläre Ausdrücke: Jetzt haben Sie zwei Probleme
  • Hacken des HTML-Desinfektionsprogramms von stackoverflow.com
278 Sam Sep 27 2011 at 11:01

Ich bin damit einverstanden, dass das richtige Tool zum Parsen von XML und insbesondere HTML ein Parser und keine Engine für reguläre Ausdrücke ist. Wie andere bereits betont haben, ist die Verwendung eines regulären Ausdrucks manchmal schneller, einfacher und erledigt die Aufgabe, wenn Sie das Datenformat kennen.

Microsoft hat tatsächlich einen Abschnitt mit Best Practices für reguläre Ausdrücke in .NET Framework und spricht speziell über das Berücksichtigen der Eingabequelle .

Reguläre Ausdrücke haben Einschränkungen, aber haben Sie Folgendes berücksichtigt?

Das .NET Framework ist einzigartig, wenn es um reguläre Ausdrücke geht, da es Balancing Group Definitions unterstützt .

  • Siehe Abgleichen ausgeglichener Konstrukte mit regulären .NET-Ausdrücken
  • Siehe .NET Regular Expressions: Regex und Balanced Matching
  • Siehe Microsoft-Dokumente zu Ausgleichsgruppendefinitionen

Aus diesem Grund glaube ich, dass Sie XML mit regulären Ausdrücken analysieren können. Beachten Sie jedoch, dass es sich um gültiges XML handeln muss ( Browser verzeihen HTML sehr und erlauben eine schlechte XML-Syntax in HTML ). Dies ist möglich, da die "Balancing Group Definition" es der Engine für reguläre Ausdrücke ermöglicht, als PDA zu fungieren.

Zitat aus Artikel 1 oben zitiert:

.NET-Engine für reguläre Ausdrücke

Wie oben beschrieben, können richtig ausgeglichene Konstrukte nicht durch einen regulären Ausdruck beschrieben werden. Die .NET-Engine für reguläre Ausdrücke bietet jedoch einige Konstrukte, mit denen ausgewogene Konstrukte erkannt werden können.

  • (?<group>) - schiebt das erfasste Ergebnis mit der Namensgruppe auf den Erfassungsstapel.
  • (?<-group>) - Das oberste Capture wird mit der Namensgruppe vom Capture-Stapel entfernt.
  • (?(group)yes|no) - Entspricht dem Ja-Teil, wenn eine Gruppe mit der Namensgruppe vorhanden ist, andernfalls stimmt kein Teil überein.

Diese Konstrukte ermöglichen es einem regulären .NET-Ausdruck, einen eingeschränkten PDA zu emulieren, indem im Wesentlichen einfache Versionen der Stapeloperationen zugelassen werden: Push, Pop und Leer. Die einfachen Operationen sind so ziemlich gleichbedeutend mit Inkrementieren, Dekrementieren und Vergleichen mit Null. Auf diese Weise kann die .NET-Engine für reguläre Ausdrücke eine Teilmenge der kontextfreien Sprachen erkennen, insbesondere diejenigen, für die nur ein einfacher Zähler erforderlich ist. Dies ermöglicht wiederum, dass die nicht traditionellen regulären .NET-Ausdrücke einzelne richtig ausgewogene Konstrukte erkennen.

Betrachten Sie den folgenden regulären Ausdruck:

(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
   <!-- .*? -->                  |
   <[^>]*/>                      |
   (?<opentag><(?!/)[^>]*[^/]>)  |
   (?<-opentag></[^>]*[^/]>)     |
   [^<>]*
)*
(?(opentag)(?!))

Verwenden Sie die Flags:

  • Einzelne Zeile
  • IgnorePatternWhitespace (nicht erforderlich, wenn Sie Regex reduzieren und alle Leerzeichen entfernen)
  • IgnoreCase (nicht erforderlich)

Regulärer Ausdruck erklärt (inline)

(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?>                                        # atomic group / don't backtrack (faster)
   <!-- .*? -->                 |          # match xml / html comment
   <[^>]*/>                     |          # self closing tag
   (?<opentag><(?!/)[^>]*[^/]>) |          # push opening xml tag
   (?<-opentag></[^>]*[^/]>)    |          # pop closing xml tag
   [^<>]*                                  # something between tags
)*                                         # match as many xml tags as possible
(?(opentag)(?!))                           # ensure no 'opentag' groups are on stack

Sie können dies bei A Better .NET Regular Expression Tester versuchen .

Ich habe die Beispielquelle verwendet von:

<html>
<body>
<div>
   <br />
   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>
</div>
</body>
</html>

Dies fand die Übereinstimmung:

   <ul id="matchMe" type="square">
      <li>stuff...</li>
      <li>more stuff</li>
      <li>
          <div>
               <span>still more</span>
               <ul>
                    <li>Another &gt;ul&lt;, oh my!</li>
                    <li>...</li>
               </ul>
          </div>
      </li>
   </ul>

obwohl es tatsächlich so herauskam:

<ul id="matchMe" type="square">           <li>stuff...</li>           <li>more stuff</li>           <li>               <div>                    <span>still more</span>                    <ul>                         <li>Another &gt;ul&lt;, oh my!</li>                         <li>...</li>                    </ul>               </div>           </li>        </ul>

Zuletzt hat mir Jeff Atwoods Artikel wirklich gefallen : Parsing Html The Cthulhu Way . Komischerweise wird die Antwort auf diese Frage zitiert, die derzeit über 4.000 Stimmen hat.

261 JohnFiala Nov 14 2009 at 06:44

Ich schlage vor, QueryPath zum Parsen von XML und HTML in PHP zu verwenden. Es ist im Grunde die gleiche Syntax wie jQuery, nur auf der Serverseite.

222 moritz Jan 27 2010 at 19:54

Die Antworten, dass Sie HTML nicht mit regulären Ausdrücken analysieren können, sind zwar korrekt, gelten hier jedoch nicht. Das OP möchte nur ein HTML-Tag mit regulären Ausdrücken analysieren, und das kann mit einem regulären Ausdruck erfolgen.

Der vorgeschlagene reguläre Ausdruck ist jedoch falsch:

<([a-z]+) *[^/]*?>

Wenn Sie etwas zu dem regulären Ausdruck hinzufügen, indem Rückzieher kann es gezwungen sein , dumme Sachen zu passen wie <a >>, [^/]zu tolerant ist. Beachten Sie auch, dass dies <space>*[^/]*redundant ist, da die [^/]*auch Leerzeichen entsprechen können.

Mein Vorschlag wäre

<([a-z]+)[^>]*(?<!/)>

Wo (?<! ... )ist (in Perl-Regexen) der negative Rückblick. Es lautet "a <, dann ein Wort, dann alles, was nicht a> ist, wobei das letzte möglicherweise kein / ist, gefolgt von>".

Beachten Sie, dass dies Dinge wie <a/ >(genau wie der ursprüngliche reguläre Ausdruck) zulässt. Wenn Sie also etwas restriktiveres wünschen, müssen Sie einen regulären Ausdruck erstellen, der mit durch Leerzeichen getrennten Attributpaaren übereinstimmt.

185 Kobi Nov 14 2009 at 05:50

Versuchen:

<([^\s]+)(\s[^>]*?)?(?<!/)>

Es ist ähnlich wie deins, aber das letzte >darf nicht nach einem Schrägstrich sein und akzeptiert auch h1.

181 cytinus May 17 2012 at 17:13

Sun Tzu, ein alter chinesischer Stratege, General und Philosoph, sagte:

Es heißt, wenn Sie Ihre Feinde kennen und sich selbst kennen, können Sie hundert Schlachten ohne einen einzigen Verlust gewinnen. Wenn Sie nur sich selbst kennen, aber nicht Ihren Gegner, können Sie gewinnen oder verlieren. Wenn Sie weder sich selbst noch Ihren Feind kennen, gefährden Sie sich immer selbst.

In diesem Fall ist Ihr Feind HTML und Sie sind entweder Sie selbst oder Regex. Sie könnten sogar Perl mit unregelmäßigem Regex sein. HTML kennen. Kenn dich selbst.

Ich habe ein Haiku verfasst, das die Natur von HTML beschreibt.

HTML has
complexity exceeding
regular language.

Ich habe auch ein Haiku verfasst, das die Natur von Regex in Perl beschreibt.

The regex you seek
is defined within the phrase
<([a-zA-Z]+)(?:[^>]*[^/]*)?>
155 meder Nov 15 2009 at 21:37
<?php
$selfClosing = explode(',', 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed'); $html = '
<p><a href="#">foo</a></p>
<hr/>
<br/>
<div>name</div>';

$dom = new DOMDocument(); $dom->loadHTML($html); $els = $dom->getElementsByTagName('*'); foreach ( $els as $el ) { $nodeName = strtolower($el->nodeName); if ( !in_array( $nodeName, $selfClosing ) ) { var_dump( $nodeName );
    }
}

Ausgabe:

string(4) "html"
string(4) "body"
string(1) "p"
string(1) "a"
string(3) "div"

Definieren Sie einfach die Namen der Elementknoten, die sich selbst schließen, laden Sie die gesamte HTML-Zeichenfolge in eine DOM-Bibliothek, greifen Sie auf alle Elemente zu, durchlaufen Sie sie und filtern Sie diejenigen heraus, die sich nicht selbst schließen, und bearbeiten Sie sie.

Ich bin mir sicher, dass Sie bereits wissen, dass Sie Regex für diesen Zweck nicht verwenden sollten.

149 GONeale Nov 17 2009 at 06:15

Ich weiß nicht, wie genau Sie dies benötigen, aber wenn Sie auch .NET verwenden, können Sie dann nicht das HTML Agility Pack verwenden ?

Auszug:

Es ist eine .NET-Codebibliothek, mit der Sie HTML-Dateien "aus dem Web" analysieren können. Der Parser ist sehr tolerant gegenüber "realem" fehlerhaftem HTML.

138 Jherico Nov 14 2009 at 05:47

Sie möchten, dass dem ersten >kein a vorangestellt wird /. Schauen Sie hier nach , wie das zu tun. Es wird als negatives Aussehen bezeichnet.

Eine naive Implementierung davon wird jedoch <bar/></foo>in diesem Beispieldokument übereinstimmen

<foo><bar/></foo>

Können Sie etwas mehr Informationen zu dem Problem geben, das Sie lösen möchten? Durchlaufen Sie Tags programmgesteuert?

123 John-DavidDalton Nov 15 2009 at 13:18

Das W3C erklärt das Parsen in einer Pseudo-Regexp-Form:
W3C Link

Folgen Sie den var-Links für QName, Sund Attribute, um ein klareres Bild zu erhalten.
Basierend darauf können Sie einen ziemlich guten regulären Ausdruck erstellen, um Dinge wie das Entfernen von Tags zu handhaben.

107 SamGoody Nov 17 2009 at 02:02

Wenn Sie dies für PHP benötigen:

Die PHP-DOM- Funktionen funktionieren nur dann ordnungsgemäß, wenn XML ordnungsgemäß formatiert ist. Egal wie viel besser sie für den Rest der Menschheit sind.

simplehtmldom ist gut, aber ich fand es ein bisschen fehlerhaft, und es ist ziemlich speicherlastig [Wird auf großen Seiten abstürzen.]

Ich habe Querypath noch nie verwendet , kann daher seine Nützlichkeit nicht kommentieren.

Ein weiterer Versuch ist mein DOMParser, der sehr ressourcenschonend ist und den ich seit einiger Zeit gerne benutze. Einfach zu lernen und leistungsstark.

Für Python und Java wurden ähnliche Links veröffentlicht.

Für die Downvoter - Ich habe meine Klasse erst geschrieben, als sich herausstellte, dass die XML-Parser der tatsächlichen Verwendung nicht standhalten konnten. Religiöses Downvoting verhindert nur, dass nützliche Antworten veröffentlicht werden - halten Sie die Dinge bitte im Blickfeld der Frage.

96 EmanueleDelGrande Jul 25 2011 at 21:35

Hier ist die Lösung:

<?php
// here's the pattern:
$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*(\/>|>)/'; // a string to parse: $string = 'Hello, try clicking <a href="#paragraph">here</a>
    <br/>and check out.<hr />
    <h2>title</h2>
    <a name ="paragraph" rel= "I\'m an anchor"></a>
    Fine, <span title=\'highlight the "punch"\'>thanks<span>.
    <div class = "clear"></div>
    <br>';

// let's get the occurrences:
preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER); // print the result: print_r($matches[0]);
?>

Um es gründlich zu testen, habe ich in die Zeichenfolge automatisch schließende Tags eingegeben:

  1. <h />
  2. <br/>
  3. <br>

Ich habe auch Tags eingegeben mit:

  1. ein Attribut
  2. mehr als ein Attribut
  3. Attribute, deren Wert entweder in einfache Anführungszeichen oder in doppelte Anführungszeichen gebunden ist
  4. Attribute, die einfache Anführungszeichen enthalten, wenn das Trennzeichen ein doppeltes Anführungszeichen ist und umgekehrt
  5. "unpretty" -Attribute mit einem Leerzeichen vor dem Symbol "=", danach und sowohl davor als auch danach.

Sollten Sie im obigen Proof of Concept etwas finden, das nicht funktioniert, kann ich den Code analysieren, um meine Fähigkeiten zu verbessern.

<EDIT> Ich habe vergessen, dass die Frage des Benutzers darin bestand, das Parsen von selbstschließenden Tags zu vermeiden. In diesem Fall ist das Muster einfacher und wird folgendermaßen:

$pattern = '/<(\w+)(\s+(\w+)\s*\=\s*(\'|")(.*?)\\4\s*)*\s*>/';

Der Benutzer @ridgerunner hat festgestellt, dass das Muster keine nicht zitierten Attribute oder Attribute ohne Wert zulässt . In diesem Fall bringt uns eine Feinabstimmung das folgende Muster:

$pattern = '/<(\w+)(\s+(\w+)(\s*\=\s*(\'|"|)(.*?)\\5\s*)?)*\s*>/';

</ EDIT>

Das Muster verstehen

Wenn jemand mehr über das Muster erfahren möchte, gebe ich eine Zeile an:

  1. Der erste Unterausdruck (\ w +) entspricht dem Tag-Namen
  2. Der zweite Unterausdruck enthält das Muster eines Attributs. Es besteht aus:
    1. ein oder mehrere Leerzeichen \ s +
    2. der Name des Attributs (\ w +)
    3. null oder mehr Leerzeichen \ s * (es ist möglich oder nicht, hier Leerzeichen zu lassen)
    4. das Symbol "="
    5. wieder null oder mehr Leerzeichen
    6. Das Trennzeichen des Attributwerts ist ein einfaches oder doppeltes Anführungszeichen ('| "). In dem Muster wird das einfache Anführungszeichen maskiert, da es mit dem PHP-Zeichenfolgenbegrenzer übereinstimmt. Dieser Unterausdruck wird mit den Klammern erfasst, sodass auf ihn verwiesen werden kann Um das Schließen des Attributs erneut zu analysieren, ist dies sehr wichtig.
    7. der Wert des Attributs, der mit fast allem übereinstimmt : (. *?); In dieser speziellen Syntax aktiviert die RegExp-Engine unter Verwendung der gierigen Übereinstimmung (dem Fragezeichen nach dem Sternchen) einen "Look-Ahead" -ähnlichen Operator, der mit allem übereinstimmt, was nicht diesem Unterausdruck folgt
    8. Hier kommt der Spaß: Der \ 4-Teil ist ein Rückreferenzoperator , der sich auf einen zuvor im Muster definierten Unterausdruck bezieht. In diesem Fall beziehe ich mich auf den vierten Unterausdruck, der das erste gefundene Attributtrennzeichen ist
    9. null oder mehr Leerzeichen \ s *
    10. Der Attribut-Unterausdruck endet hier mit der Angabe von null oder mehr möglichen Vorkommen, die durch das Sternchen angegeben werden.
  3. Da ein Tag möglicherweise mit einem Leerzeichen vor dem Symbol ">" endet, werden null oder mehr Leerzeichen mit dem Untermuster \ s * abgeglichen.
  4. Das zu übereinstimmende Tag kann mit einem einfachen ">" Symbol oder einem möglichen XHTML-Abschluss enden, der den Schrägstrich davor verwendet: (/> |>). Der Schrägstrich wird natürlich maskiert, da er mit dem Trennzeichen für reguläre Ausdrücke übereinstimmt.

Kleiner Tipp: Um diesen Code besser analysieren zu können, muss der generierte Quellcode betrachtet werden, da ich keine HTML-Sonderzeichen angegeben habe, die entkommen.

92 AmalMurali Nov 18 2009 at 21:50

Wann immer ich schnell etwas aus einem HTML-Dokument extrahieren muss, verwende ich Tidy, um es in XML zu konvertieren, und verwende dann XPath oder XSLT, um das zu bekommen, was ich brauche. In Ihrem Fall so etwas:

//p/a[@href='foo']
90 wen Nov 17 2009 at 01:34

Ich habe zuvor ein Open-Source-Tool namens HTMLParser verwendet . Es wurde entwickelt, um HTML auf verschiedene Arten zu analysieren und erfüllt den Zweck recht gut. Es kann HTML als unterschiedlichen Treenode analysieren und Sie können seine API einfach verwenden, um Attribute aus dem Knoten abzurufen. Probieren Sie es aus und sehen Sie, ob dies Ihnen helfen kann.

84 SamWatkins Jul 12 2011 at 00:13

Ich mag es, HTML mit regulären Ausdrücken zu analysieren. Ich versuche nicht, idiotisches HTML zu analysieren, das absichtlich kaputt ist. Dieser Code ist mein Hauptparser (Perl-Edition):

$_ = join "",<STDIN>; tr/\n\r \t/ /s; s/</\n</g; s/>/>\n/g; s/\n ?\n/\n/g; s/^ ?\n//s; s/ $//s; print

Es heißt htmlsplit und teilt den HTML- Code in Zeilen mit einem Tag oder Textblock in jeder Zeile auf. Die Zeilen können dann mit anderen Textwerkzeugen und Skripten wie grep , sed , Perl usw. weiter verarbeitet werden. Ich scherze nicht einmal :) Viel Spaß.

Es ist einfach genug, mein Perl-Skript "Slurp-Everything-First" in ein nettes Streaming-Ding umzuwandeln, wenn Sie riesige Webseiten verarbeiten möchten. Aber es ist nicht wirklich notwendig.

HTML Split


Einige bessere reguläre Ausdrücke:

/(<.*?>|[^<]+)\s*/g    # Get tags and text
/(\w+)="(.*?)"/g       # Get attibutes

Sie sind gut für XML / XHTML.

Mit geringfügigen Abweichungen kann es mit unordentlichem HTML umgehen ... oder zuerst HTML -> XHTML konvertieren.


Der beste Weg, reguläre Ausdrücke zu schreiben, ist der Lex / Yacc- Stil, nicht als undurchsichtige Einzeiler oder kommentierte mehrzeilige Monstrositäten. Das habe ich hier noch nicht gemacht; diese brauchen es kaum.

74 kingjeffrey Jul 18 2010 at 09:52

Hier ist ein PHP-basierter Parser , der HTML mit einem gottlosen regulären Ausdruck analysiert. Als Autor dieses Projekts kann ich Ihnen sagen, dass es möglich ist, HTML mit Regex zu analysieren, aber nicht effizient. Wenn Sie eine serverseitige Lösung benötigen (wie ich es für mein wp-Typography WordPress-Plugin getan habe ), funktioniert dies.

70 kenorb Apr 25 2010 at 23:38

Es gibt einige nette reguläre Ausdrücke zu ersetzen HTML mit BBCode hier . Beachten Sie für alle Neinsager, dass er nicht versucht, HTML vollständig zu analysieren, sondern nur zu bereinigen. Er kann es sich wahrscheinlich leisten, Tags abzutöten, die sein einfacher "Parser" nicht verstehen kann.

Zum Beispiel:

$store =~ s/http:/http:\/\//gi; $store =~ s/https:/https:\/\//gi;
$baseurl = $store;

if (!$query->param("ascii")) { $html =~ s/\s\s+/\n/gi;
    $html =~ s/<pre(.*?)>(.*?)<\/pre>/\[code]$2\[\/code]/sgmi;
}

$html =~ s/\n//gi; $html =~ s/\r\r//gi;
$html =~ s/$baseurl//gi;
$html =~ s/<h[1-7](.*?)>(.*?)<\/h[1-7]>/\n\[b]$2\[\/b]\n/sgmi;
$html =~ s/<p>/\n\n/gi; $html =~ s/<br(.*?)>/\n/gi;
$html =~ s/<textarea(.*?)>(.*?)<\/textarea>/\[code]$2\[\/code]/sgmi;
$html =~ s/<b>(.*?)<\/b>/\[b]$1\[\/b]/gi;
$html =~ s/<i>(.*?)<\/i>/\[i]$1\[\/i]/gi;
$html =~ s/<u>(.*?)<\/u>/\[u]$1\[\/u]/gi;
$html =~ s/<em>(.*?)<\/em>/\[i]$1\[\/i]/gi;
$html =~ s/<strong>(.*?)<\/strong>/\[b]$1\[\/b]/gi;
$html =~ s/<cite>(.*?)<\/cite>/\[i]$1\[\/i]/gi;
$html =~ s/<font color="(.*?)">(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi; $html =~ s/<font color=(.*?)>(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<link(.*?)>//gi; $html =~ s/<li(.*?)>(.*?)<\/li>/\[\*]$2/gi; $html =~ s/<ul(.*?)>/\[list]/gi;
$html =~ s/<\/ul>/\[\/list]/gi; $html =~ s/<div>/\n/gi;
$html =~ s/<\/div>/\n/gi; $html =~ s/<td(.*?)>/ /gi;
$html =~ s/<tr(.*?)>/\n/gi; $html =~ s/<img(.*?)src="(.*?)"(.*?)>/\[img]$baseurl\/$2\[\/img]/gi;
$html =~ s/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/\[url=$baseurl\/$2]$4\[\/url]/gi;
$html =~ s/\[url=$baseurl\/http:\/\/(.*?)](.*?)\[\/url]/\[url=http:\/\/$1]$2\[\/url]/gi;
$html =~ s/\[img]$baseurl\/http:\/\/(.*?)\[\/img]/\[img]http:\/\/$1\[\/img]/gi; $html =~ s/<head>(.*?)<\/head>//sgmi;
$html =~ s/<object>(.*?)<\/object>//sgmi; $html =~ s/<script(.*?)>(.*?)<\/script>//sgmi;
$html =~ s/<style(.*?)>(.*?)<\/style>//sgmi; $html =~ s/<title>(.*?)<\/title>//sgmi;
$html =~ s/<!--(.*?)-->/\n/sgmi; $html =~ s/\/\//\//gi;
$html =~ s/http:\//http:\/\//gi; $html =~ s/https:\//https:\/\//gi;

$html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsi; $html =~ s/\r\r//gi;
$html =~ s/\[img]\//\[img]/gi; $html =~ s/\[url=\//\[url=/gi;
70 EmanueleDelGrande Jul 05 2010 at 21:16

Über die Frage der regulären Ausdrucksmethoden zum Parsen von (x) HTML lautet die Antwort auf alle, die über einige Grenzen sprachen: Sie sind nicht ausreichend geschult, um die Kraft dieser mächtigen Waffe zu beherrschen, da hier niemand über Rekursion sprach .

Ein kollegialer Ausdrucksunabhängiger Kollege hat mich über diese Diskussion informiert, die sicherlich nicht die erste im Internet zu diesem alten und heißen Thema ist.

Nachdem ich einige Beiträge gelesen hatte, suchte ich als erstes nach dem "? R" -String in diesem Thread. Die zweite war die Suche nach "Rekursion".

Nein, heilige Kuh, keine Übereinstimmung gefunden. Da niemand den Hauptmechanismus erwähnte, auf dem ein Parser aufgebaut ist, wurde mir schnell bewusst, dass niemand den Punkt verstand.

Wenn ein (x) HTML-Parser eine Rekursion benötigt, reicht ein Parser für reguläre Ausdrücke ohne Rekursion für diesen Zweck nicht aus. Es ist ein einfaches Konstrukt.

Die schwarze Kunst der regulären Ausdrücke ist schwer zu beherrschen . Vielleicht gibt es weitere Möglichkeiten, die wir ausgelassen haben, als wir unsere persönliche Lösung ausprobiert und getestet haben, um das gesamte Web in einer Hand zu erfassen ... Nun, da bin ich mir sicher :)

Hier ist das magische Muster:

$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";

Probier es einfach. Es ist als PHP-String geschrieben, daher bewirkt der Modifikator "s", dass Klassen Zeilenumbrüche enthalten.

Hier ist ein Beispiel für das PHP-Handbuch, das ich im Januar geschrieben habe: Referenz

(Vorsicht. In diesem Hinweis habe ich den Modifikator "m" falsch verwendet. Er sollte gelöscht werden, obwohl er von der Engine für reguläre Ausdrücke verworfen wird, da keine ^oder eine $Verankerung verwendet wurde.)

Nun könnten wir über die Grenzen dieser Methode aus einer informierten Sicht sprechen:

  1. Je nach der spezifischen Implementierung der Engine für reguläre Ausdrücke kann die Anzahl der analysierten verschachtelten Muster für die Rekursion begrenzt sein , dies hängt jedoch von der verwendeten Sprache ab
  2. Obwohl beschädigt, führt (x) HTML nicht zu schwerwiegenden Fehlern. Es ist nicht saniert .

Wie auch immer, es ist nur ein Muster für reguläre Ausdrücke, aber es offenbart die Möglichkeit, viele leistungsfähige Implementierungen zu entwickeln.

Ich habe dieses Muster geschrieben, um den rekursiven Abstiegsparser einer Template-Engine zu betreiben, die ich in meinem Framework erstellt habe. Die Leistung ist sowohl in Bezug auf die Ausführungszeiten als auch in Bezug auf die Speichernutzung wirklich großartig (nichts mit anderen Template-Engines zu tun, die dieselbe Syntax verwenden).

62 CoreySanders Feb 04 2010 at 23:22

Wie viele Leute bereits betont haben, ist HTML keine reguläre Sprache, was das Parsen sehr schwierig machen kann. Meine Lösung besteht darin, es mit einem aufgeräumten Programm in eine normale Sprache umzuwandeln und dann einen XML-Parser zu verwenden, um die Ergebnisse zu nutzen. Dafür gibt es viele gute Möglichkeiten. Mein Programm wird mit Java mit der jtidy- Bibliothek geschrieben, um HTML in XML umzuwandeln, und dann Jaxen mit xpath in das Ergebnis.

60 daghan May 10 2012 at 20:53
<\s*(\w+)[^/>]*>

Die Teile erklärt:

<: Startcharakter

\s*: Es kann Leerzeichen vor dem Tag-Namen haben (hässlich, aber möglich).

(\w+): Tags können Buchstaben und Zahlen enthalten (h1). Nun, \wpasst auch zu '_', aber es tut nicht weh, denke ich. Wenn Sie neugierig sind, verwenden Sie stattdessen ([a-zA-Z0-9] +).

[^/>]*: Alles außer >und /bis zum Schließen>

>: Schließen >

NICHT VERWANDT

Und zu den Leuten, die reguläre Ausdrücke unterschätzen und sagen, dass sie nur so mächtig sind wie reguläre Sprachen:

a n ba n ba n, das nicht regelmäßig und nicht einmal kontextfrei ist, kann mit abgeglichen werden^(a+)b\1b\1$

Rückreferenz FTW !

55 LonnieBest Jun 01 2012 at 12:13

Wenn Sie nur versuchen, diese Tags zu finden (ohne die Ambitionen zu analysieren), versuchen Sie diesen regulären Ausdruck:

/<[^/]*?>/g

Ich habe es in 30 Sekunden geschrieben und hier getestet: http://gskinner.com/RegExr/

Es entspricht den von Ihnen erwähnten Tags, während die von Ihnen angegebenen Typen ignoriert werden.

53 manixrock Nov 16 2009 at 00:13

Mir scheint, Sie versuchen, Tags ohne ein "/" am Ende abzugleichen. Versuche dies:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
52 slevithan May 29 2012 at 06:27

Es ist richtig, dass es beim Programmieren normalerweise am besten ist, dedizierte Parser und APIs anstelle von regulären Ausdrücken zu verwenden, wenn Sie mit HTML arbeiten, insbesondere wenn die Genauigkeit von größter Bedeutung ist (z. B. wenn Ihre Verarbeitung Sicherheitsauswirkungen haben könnte). Ich schreibe jedoch keiner dogmatischen Ansicht zu, dass XML-artiges Markup niemals mit regulären Ausdrücken verarbeitet werden sollte. Es gibt Fälle, in denen reguläre Ausdrücke ein hervorragendes Werkzeug für den Job sind, z. B. beim einmaligen Bearbeiten in einem Texteditor, beim Beheben fehlerhafter XML-Dateien oder beim Umgang mit Dateiformaten, die aussehen, aber nicht ganz XML sind. Es gibt einige Probleme, die Sie beachten müssen, aber sie sind nicht unüberwindbar oder sogar unbedingt relevant.

Ein einfacher Regex wie <([^>"']|"[^"]*"|'[^']*')*>ist normalerweise gut genug, in Fällen wie den gerade erwähnten. Alles >in allem ist es eine naive Lösung, aber es erlaubt korrekt nicht codierte Symbole in Attributwerten. Wenn Sie beispielsweise nach einem tableTag suchen , können Sie es als anpassen </?table\b([^>"']|"[^"]*"|'[^']*')*>.

Um einen Eindruck davon zu bekommen, wie ein "fortgeschrittener" HTML-Regex aussehen würde, können Sie im Folgenden das Verhalten des realen Browsers und den HTML5-Parsing-Algorithmus nachvollziehen:

</?([A-Za-z][^\s>/]*)(?:=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)|[^>])*(?:>|$)

Das Folgende entspricht einer ziemlich strengen Definition von XML-Tags (obwohl nicht der gesamte Satz von Unicode-Zeichen berücksichtigt wird, die in XML-Namen zulässig sind):

<(?:([_:A-Z][-.:\w]*)(?:\s+[_:A-Z][-.:\w]*\s*=\s*(?:"[^"]*"|'[^']*'))*\s*/?|/([_:A-Z][-.:\w]*)\s*)>

Zugegeben, diese berücksichtigen nicht den umgebenden Kontext und einige Randfälle, aber selbst solche Dinge könnten behandelt werden, wenn Sie es wirklich wollten (z. B. indem Sie zwischen den Übereinstimmungen eines anderen regulären Ausdrucks suchen).

Verwenden Sie am Ende des Tages das für den Job am besten geeignete Werkzeug, auch wenn es sich bei diesem Werkzeug zufällig um einen regulären Ausdruck handelt.

49 EmreYazici Feb 09 2010 at 10:59

Obwohl es nicht geeignet und effektiv ist, reguläre Ausdrücke für diesen Zweck zu verwenden, bieten reguläre Ausdrücke manchmal schnelle Lösungen für einfache Übereinstimmungsprobleme, und meiner Ansicht nach ist es nicht so schrecklich, reguläre Ausdrücke für triviale Arbeiten zu verwenden.

Es gibt einen endgültigen Blog-Beitrag über übereinstimmende innerste HTML-Elemente, die von Steven Levithan geschrieben wurden.