it-swarm.com.de

RegEx stimmt mit offenen Tags außer XHTML-Tags überein

Ich muss mit all diesen Eröffnungs-Tags übereinstimmen:

<p>
<a href="foo">

Aber nicht diese:

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

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

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

Ich glaube, es heißt:

  • Finden Sie dann ein Kleiner als
  • Suchen (und erfassen) Sie dann ein- oder mehrmals nach a-z
  • Suchen Sie dann null oder mehr Leerzeichen
  • Suchen Sie ein beliebiges Zeichen null oder mehrmals, gierig, mit Ausnahme von /
  • Finde ein Größeres als

Habe ich das richtig? Und vor allem, was denkst du?

1324
Jeff

Sie können [X] HTML nicht mit regulären Ausdrücken analysieren. Weil HTML nicht von regulären Ausdrücken analysiert werden kann. Regex ist kein Tool, mit dem HTML korrekt analysiert werden kann. Wie ich hier schon so oft in Fragen zu HTML und Regex beantwortet habe, erlaubt die Verwendung von Regex nicht, HTML zu konsumieren. Reguläre Ausdrücke sind ein Werkzeug, das nicht ausreichend ausgefeilt ist, um die von HTML verwendeten Konstrukte zu verstehen. HTML ist keine reguläre Sprache und kann daher nicht mit regulären Ausdrücken analysiert werden. Regex-Abfragen sind nicht dazu geeignet, HTML in sinnvolle Teile zu zerlegen. so oft kommt es aber nicht auf mich an. Selbst verbesserte unregelmäßige reguläre Ausdrücke, wie sie von Perl verwendet werden, sind nicht für das Parsen von HTML geeignet. Du wirst mich niemals zum Knacken bringen. HTML ist eine Sprache von ausreichender Komplexität, die von regulären Ausdrücken nicht 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-Aufforderungen verdorbene Seelen in das Reich der Lebenden. HTML und Regex gehören zusammen wie Liebe, Ehe und ritueller Kindsmord. Das <Zentrum> kann es nicht halten, es ist zu spät. Die Kraft von Regex und HTML im selben konzeptuellen Raum wird Ihren Verstand zerstören wie so viel wässriges PuTTY. Wenn Sie HTML mit Regex analysieren, geben Sie ihnen und ihren blasphemischen Wegen nach, die uns alle dazu verurteilen, unmenschliche Anstrengungen für denjenigen zu unternehmen, dessen Name in der mehrsprachigen Basisebene nicht ausgedrückt werden kann, kommt er. HTML-plus-regexp verflüssigt die Nerven des Lebewesens, während Sie beobachten, wie Ihre Psyche im Ansturm des Grauens welkt. Regex-basierte HTML-Parser sind der Krebs, der StackOverflow tötet es ist zu spät. Es ist zu spät. Wir können nicht gerettet werden Die Trangession eines Kindes stellt sicher, dass Regex das gesamte lebende Gewebe konsumiert (mit Ausnahme von HTML, das es nicht kann, wie zuvor prophezeit). lieber Herr, hilf uns, wie kann jemand diese Geißel überleben? Die Verwendung von Regex zum Parsen von HTML hat die Menschheit zu einer Ewigkeit furchtbarer Folter und Sicherheitslücken verurteilt mit regex als Werkzeug zur Verarbeitung von HTML schafft einen Durchbruchch zwischen dieser Welt und das Schreckensreich der crupto entitiesrrupt Entities (wie SGML Entities, aber mehr korrupt) ein bloßer flüchtiger blickse der Welt der regex-Parser für HTML werden insTransportieren Sie einen pdas Bewusstsein des Programmierers izu einem worlda er ständig schreit, kommt er, die Pest sles wird eine Regex-Infektion gebenich verschlinge deine HTML Parser, Anwendung und Existenz für alle Zeiten wie Visual Basic nur noch schlimmer er kommt er comes nicht fiGht hwir kommen, ̕h̕iS unhǫly radiańcé destro҉ying alles Enli̍̈́̂̈́ghtenment, HTML Umbauten lea͠ki͠ņg fr̶ǫm ̡yo ͟ur eye͢s͢ ̛l̛ik̕e liqUid pain, das Lied der Regulären Expssion parsing wird extiNguish die Stimmen von mortal mann aus der spHier kann ich es sehen kannst du sehen, dass es schön ist ter final snuffing ofür die Lüges des Menschen ALLE IS LOŚ͖̩͇̗̪̏̈́T ALL I S LOST the pon̷y er kommts er kommtes er comichs ter ichoder durchdringenes all MEIN FACE MEIN GESICHTo NEIN NEINO O NΘ hör auf ter ein * ̶͑̾̾ ̅ͫ͏̙̤g̅ͫ͏̙̤l͇̫͛͆̾ͫ̑͆es ist ͎a̧͈͖r̽̾̈́͒͑e nOt rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISΌ TO͇̹̺ͅƝ̴ȳ̳ TH̘Ë͖́̉ Ë͖́̉P͠O̯͍̭ N̚Y̐ H̡ ̶̧̨̱̹̭̯ͧ̾ͬÇ̶̨̱̹̭̯ͧ̾ͬO̷̙̲̝͖ͭ̏ͥͮ͟M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ


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


Hinweis des Moderators

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

4420
bobince

Während es richtig ist, reguläre Ausdrücke zum Parsen von willkürlich HTML aufzufordern, ist es manchmal angebracht, einen begrenzten, bekannten Satz von HTML zu parsen.

Wenn Sie eine kleine Menge von HTML-Seiten haben, aus denen Sie Daten entfernen und dann in eine Datenbank kopieren möchten, funktionieren reguläre Ausdrücke möglicherweise einwandfrei. Ich wollte zum Beispiel 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 funktionierten gut für mich und waren sehr schnell einzurichten.

3139

Ich denke, der Fehler hier ist, dass HTML eine Chomsky Typ 2-Grammatik (kontextfreie Grammatik) und RegEx 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 sie mathematisch unmöglich XML mit RegEx zu analysieren.

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

1966
NealB

Hören Sie 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 die folgenden Schritte ausführt:

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

Ich habe den letzten Teil noch nicht ganz abgeschlossen, aber ich weiß, dass ich näher komme. Es wirft aus irgendeinem Grund immer wieder CthulhuRlyehWgahnaglFhtagnExceptions, also portiere ich es auf VB 6 und verwende 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.

P.S. Pierre de Fermat hat auch herausgefunden, wie es geht, aber der Rand, an dem er schrieb, war nicht groß genug für den Code.

1273
Justin Morgan

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

Dies ist der reguläre Ausdruck, den ich verwende (!), Um HTML-Tags zuzuordnen:

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

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

Ich schätze, Sie möchten Kobi s negatives Aussehen verwenden, damit es nicht mit in sich geschlossenen Tags übereinstimmt:

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

oder einfach kombinieren, wenn und wenn nicht.

Für Downvoter: Dies ist der Arbeitscode eines tatsächlichen Produkts. Ich bezweifle, dass jeder, der diese Seite liest, den Eindruck bekommt, dass es sozialverträglich ist, reguläre Ausdrücke 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 Regex loswerden können ...

1054
itsadok

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 (ist er ein Verwandter der Klasse von Marshal .NET?) Habe ich das gesehen Underverse Stack Based Regex-Verse und zurück mit befugnisse Wissen, das Sie sich nicht vorstellen können. Ja, ich denke, 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. Der RegEx (in der .NET-Syntax), der in base64 deflatiert und codiert ist, um das Verständnis für schwache Nerven zu erleichtern, sollte ungefähr so ​​aussehen:

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

Die einzustellenden Optionen sind RegexOptions.ExplicitCapture. Die Erfassungsgruppe, nach der Sie suchen, ist ELEMENTNAME. Wenn die Erfassungsgruppe ERROR nicht leer ist, ist ein Analysefehler aufgetreten und der Regex wurde gestoppt.

Wenn Sie Probleme bei der Konvertierung in eine von Menschen lesbare reguläre Ausdrucksweise haben, 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 Unit-Tests 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 der Regex wollen, mit einigen Hilfsmethoden:

regulärer Ausdruck, um einen XML-Code zu kennzeichnen oder vollständiger regulärer Ausdruck

486
xanatos

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

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

Verwandte (warum sollten Sie nicht Regex Match verwenden):

291
dubiousjim

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

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

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

Das .NET Framework ist in Bezug auf reguläre Ausdrücke insofern einzigartig, als es Balancing Group Definitions unterstützt.

Aus diesem Grund glaube ich, dass Sie XML mit regulären Ausdrücken analysieren können. Beachten Sie jedoch, dass es sich bei um gültige XML-Browser handeln muss (, die HTML sehr verzeihen und eine schlechte XML-Syntax in HTML zulassen ). Dies ist möglich, da die "Bilanzgruppendefinition" es der regulären Ausdrucksmaschine ermöglicht, als PDA zu fungieren.

Zitat aus dem oben zitierten Artikel 1:

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

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

  • (?<group>) - verschiebt das erfasste Ergebnis mit der Namensgruppe auf den Erfassungsstapel.
  • (?<-group>) - Entfernt die am häufigsten aufgenommene Datei mit der Namensgruppe vom Aufnahmestapel.
  • (?(group)yes|no) - stimmt mit dem Ja-Teil überein, wenn eine Gruppe mit der Namensgruppe existiert, andernfalls stimmt dies mit keinem 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 Empty. Die einfachen Operationen sind so ziemlich gleichbedeutend mit Inkrementieren, Dekrementieren und Vergleichen mit Null. Dadurch kann die .NET-Engine für reguläre Ausdrücke eine Teilmenge der kontextfreien Sprachen erkennen, insbesondere derjenigen, für die nur ein einfacher Leistungsindikator erforderlich ist. Dies wiederum ermöglicht es den nicht traditionellen regulären Ausdrücken von .NET, einzelne richtig ausgeglichene Konstrukte zu erkennen.

Betrachten Sie den folgenden regulären Ausdruck:

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

Benutze die Flaggen:

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

Erklärter regulärer Ausdruck (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 unter A Better .NET Regular Expression Tester versuchen.

Ich habe die Beispielquelle 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>

Schließlich hat mir Jeff Atwoods Artikel sehr gut gefallen: Parsing Html The Cthulhu Way . Komischerweise zitiert es die Antwort auf diese Frage, die derzeit über 4.000 Stimmen hat.

270
Sam

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.

256
John Fiala

Die Antworten, die Sie 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 parsen, und das ist etwas, was mit einem regulären Ausdruck gemacht werden kann.

Der vorgeschlagene reguläre Ausdruck ist jedoch falsch:

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

Wenn Sie dem regulären Ausdruck etwas hinzufügen, kann durch Zurückverfolgen erzwungen werden, dass dumme Dinge wie <a >>, [^/] zu tolerant sind. Beachten Sie auch, dass <space>*[^/]* redundant ist, da [^/]* auch Leerzeichen enthalten kann.

Mein Vorschlag wäre

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

Wobei (?<! ... ) (in Perl reguliert) der negative Look-Behind ist. Es liest "ein <, dann ein Wort, dann alles, was nicht ein> ist, von denen das letzte nicht ein/sein kann, gefolgt von>".

Beachten Sie, dass dies Dinge wie <a/ > (genau wie der ursprüngliche reguläre Ausdruck) ermöglicht. Wenn Sie also etwas Einschränkenderes wünschen, müssen Sie einen regulären Ausdruck erstellen, um Attributpaare zuzuordnen, die durch Leerzeichen getrennt sind.

215
moritz

Versuchen:

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

Es ähnelt Ihrem, aber das letzte > darf nicht nach einem Schrägstrich stehen und akzeptiert auch h1.

178
Kobi

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 gewinnen, ohne einen einzigen Verlust zu erleiden. Wenn Sie nur sich selbst kennen, aber nicht Ihren Gegner, können Sie gewinnen oder verlieren. Wenn Sie weder sich noch Ihren Feind kennen, gefährden Sie sich immer.

In diesem Fall ist Ihr Feind HTML und Sie sind entweder Sie selbst oder Regex. Sie könnten sogar Perl mit unregelmäßiger Regex sein. Kennen Sie HTML. 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]+)(?:[^>]*[^/]*)?>
173
cytinus
<?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 Elementknotennamen, die sich selbst schließen, laden Sie die gesamte HTML-Zeichenfolge in eine DOM-Bibliothek, greifen Sie alle Elemente ab, durchlaufen und filtern Sie diejenigen heraus, die sich nicht selbst schließen, und bearbeiten Sie sie.

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

154
meder omuraliev

Ich kenne Ihren genauen Bedarf nicht, aber wenn Sie auch .NET verwenden, können Sie nicht Html ​​Agility Pack verwenden?

Auszug:

Es handelt sich um eine .NET-Codebibliothek, mit der Sie HTML-Dateien "aus dem Web" analysieren können. Der Parser ist sehr tolerant gegenüber "real world" -missgebildetem HTML.

148
GONeale

Sie möchten, dass dem ersten > kein / vorangestellt wird. Schauen Sie sich hier an, um Einzelheiten dazu zu erfahren. Es wird als negatives Aussehen bezeichnet.

Eine naive Implementierung davon führt jedoch dazu, dass <bar/></foo> in diesem Beispieldokument übereinstimmt

<foo><bar/></foo>

Können Sie weitere Informationen zu dem Problem bereitstellen, das Sie lösen möchten? Durchlaufen Sie Tags programmgesteuert?

135
Jherico

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

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

123

Wenn Sie dies für PHP benötigen:

Das PHP DOMFunktionen funktioniert nur dann richtig, wenn es richtig formatiertes XML 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 speicherintensiv [Wird auf großen Seiten abstürzen.]

Ich habe querypath noch nie benutzt, kann also nichts über dessen Nützlichkeit sagen.

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

Für Python und Java wurden ähnliche Links gepostet.

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

105
SamGoody

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 ausführlich zu testen, habe ich die folgenden Tags für das automatische Schließen der Zeichenfolge eingegeben:

  1. <hr />
  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 steht
  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 etwas finden, das im obigen Proof of Concept nicht funktioniert, kann ich den Code analysieren, um meine Fähigkeiten zu verbessern.

<EDIT> Ich habe vergessen, dass die Frage des Benutzers lautete, das Parsen selbstschließender Tags zu vermeiden. In diesem Fall ist das Muster einfacher:

$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 führt eine Feinabstimmung zu folgendem 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 * (es ist möglich oder nicht, Leerzeichen hier zu lassen)
    4. das "=" Symbol
    5. wieder null oder mehr Leerzeichen
    6. der Begrenzer des Attributwerts ist ein einfaches oder doppeltes Anführungszeichen ('| "). Im Muster wird das einfache Anführungszeichen maskiert, da es mit dem Zeichenfolgenbegrenzer PHP übereinstimmt. Dieser Unterausdruck wird mit dem Zeichenfolgenbegrenzer erfasst Klammern, damit auf das Schließen des Attributs erneut verwiesen werden kann. Deshalb ist es sehr wichtig.
    7. der Wert des Attributs, der mit fast übereinstimmt: (. *?); In dieser speziellen Syntax aktiviert die RegExp-Engine unter Verwendung des greedy match (Fragezeichen nach dem Sternchen) einen "Look-Ahead" -ähnlichen Operator, der mit nichts anderem übereinstimmt, als mit dem, was auf diesen Unterausdruck folgt
    8. hier kommt der Spaß: Der\4-Teil ist ein Rückverweis-Operator, der auf einen Unterausdruck verweist, der zuvor im Muster definiert wurde. In diesem Fall verweise ich auf den vierten Unterausdruck, nämlich Der erste gefundene Attributbegrenzer
    9. null oder mehr Leerzeichen *
    10. der Attribut-Unterausdruck endet hier mit der Angabe von null oder mehr möglichen Vorkommen, die vom Sternchen angegeben werden.
  3. Da ein Tag möglicherweise mit einem Leerzeichen vor dem Symbol ">" endet, werden null oder mehr Leerzeichen mit dem\s * -Untermuster abgeglichen.
  4. Das zuzuordnende 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 ausgeblendet, da er mit dem Begrenzer für reguläre Ausdrücke übereinstimmt.

Kleiner Tipp: Um diesen Code besser analysieren zu können, muss man sich den generierten Quellcode ansehen, da ich keine HTML-Sonderzeichen angegeben habe.

94

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

//p/a[@href='foo']
90
Sembiance

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 ziemlich gut. Es kann HTML als unterschiedlichen Treenode parsen und Sie können seine API leicht verwenden, um Attribute aus dem Knoten herauszuholen. Probieren Sie es aus und sehen Sie, ob dies Ihnen helfen kann.

90
wen

Ich analysiere HTML gerne mit regulären Ausdrücken. 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 auf, wobei jede Zeile ein Tag oder einen Textblock enthält. Die Zeilen können dann mit anderen Textwerkzeugen und Skripten wie grep , sed , Perl usw. weiterverarbeitet werden. Ich mache keine Witze :) Viel Spaß.

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

Ich wette, ich werde dafür abgelehnt.

HTML Split


Entgegen meiner Erwartung gab es einige positive Stimmen, daher schlage ich einige bessere reguläre Ausdrücke vor:

/(<.*?>|[^<]+)\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 fertig werden ... oder das HTML -> XHTML zuerst konvertieren.


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

84
Sam Watkins

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

74
kingjeffrey

Es gibt einige nette reguläre Ausdrücke, um HTML durch BBCode zu ersetzen hier . Beachten Sie, dass HTML nicht vollständig analysiert, sondern nur bereinigt werden soll. 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
sblom

Bezüglich der Frage der RegExp-Methoden zum Parsen von (x) HTML lautet die Antwort für alle, die über einige Grenzen gesprochen haben: Sie sind nicht genug geschult, um die Kraft dieser mächtigen Waffe zu beherrschen, da NIEMAND hier sprach über Rekursion.

Ein RegExp-agnostischer Kollege hat mich auf diese Diskussion aufmerksam gemacht, die sicherlich nicht die erste im Internet ist, die sich mit diesem alten und heißen Thema befasst.

Nachdem ich einige Beiträge gelesen hatte, suchte ich als erstes in diesem Thread nach der Zeichenfolge "? R". 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 klar, dass niemand den Punkt verstand.

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

Die schwarze Kunst von RegExp ist schwer zu meistern, also gibt es vielleicht noch weitere Möglichkeiten, die wir ausgelassen haben, als wir unsere persönliche Lösung ausprobiert haben, um das gesamte Web in einer Hand zu erfassen ... Nun, da bin ich mir sicher es :)

Hier ist das magische Muster:

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

Probier es einfach.
Es wird als PHP-String geschrieben, sodass Klassen mit dem Modifikator "s" Zeilenumbrüche enthalten.
Hier ist eine Beispielnotiz zum PHP Handbuch Ich schrieb am Januar: Referenz

(Vorsicht, in diesem Hinweis habe ich fälschlicherweise den Modifikator "m" verwendet. Er sollte gelöscht werden, obwohl er von der RegExp-Engine verworfen wird, da kein ^ oder $ anchorage verwendet wurde.).

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

  1. je nach der spezifischen Implementierung der RegExp-Engine kann die Rekursion eine Begrenzung für Anzahl der analysierten verschachtelten Muster haben, dies hängt jedoch von der verwendeten Sprache ab
  2. obwohl beschädigtes (x) HTML nicht zu schwerwiegenden Fehlern führt, wird es nicht bereinigt .

Trotzdem handelt es sich nur um ein RegExp-Muster, aber es bietet die Möglichkeit, viele leistungsstarke Implementierungen zu entwickeln.
Ich habe dieses Muster geschrieben, um den rekursiven Descent-Parser einer Template-Engine zu aktivieren, die ich in meinem Framework erstellt habe, und die Leistung ist wirklich großartig, sowohl in der Ausführungszeit als auch im Speicher Verwendung (hat nichts mit anderen Template-Engines zu tun, die dieselbe Syntax verwenden).

67

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

62
Corey Sanders
<\s*(\w+)[^/>]*>

Die Teile erklärt:

<: Startzeichen

\s*: Es kann vor dem Tagnamen Leerzeichen geben (hässlich, aber möglich).

(\w+): Tags können Buchstaben und Zahlen enthalten (h1). Nun, \w stimmt auch mit '_' überein, aber es tut wohl nicht weh. Verwenden Sie stattdessen ([a-zA-Z0-9] +), wenn Sie neugierig sind.

[^/>]*: alles außer > und /, bis > geschlossen wird

>: Schließen von >

NICHT IN VERBINDUNG STEHEN

Und Kollegen, die reguläre Ausdrücke unterschätzen und behaupten, sie seien nur so mächtig wie reguläre Sprachen:

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

Rückverweise FTW !

60
daghan

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 Tag-Typen, ignoriert jedoch die Typen, von denen Sie sagten, dass sie ignoriert werden sollen.

54
Lonnie Best

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

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
53
manixrock

Es ist richtig, dass es normalerweise am besten ist, beim Programmieren dedizierte Parser und APIs anstelle von regulären Ausdrücken zu verwenden, wenn es um HTML geht, insbesondere wenn Genauigkeit an erster Stelle steht (z. B. wenn Ihre Verarbeitung möglicherweise Sicherheitsrisiken hat). Ich schreibe jedoch keiner dogmatischen Ansicht zu, dass XML-ähnliche Markups niemals mit regulären Ausdrücken verarbeitet werden sollten. Es gibt Fälle, in denen reguläre Ausdrücke ein großartiges Werkzeug für den Job sind, z. B. wenn Sie einmalige Änderungen in einem Texteditor vornehmen, beschädigte XML-Dateien reparieren oder mit Dateiformaten arbeiten, die aussehen, aber nicht ganz XML sind. Es gibt einige Punkte, die beachtet werden müssen, die jedoch nicht unüberwindlich oder sogar unbedingt relevant sind.

Ein einfacher regulärer Ausdruck wie <([^>"']|"[^"]*"|'[^']*')*> ist normalerweise gut genug, in Fällen wie denen, die ich gerade erwähnt habe. Alles in allem ist es eine naive Lösung, aber es erlaubt korrekterweise nicht codierte > Symbole in Attributwerten. Wenn Sie beispielsweise nach einem table -Tag suchen, können Sie es als </?table\b([^>"']|"[^"]*"|'[^']*')*> anpassen.

Um einen Eindruck davon zu bekommen, wie ein "fortgeschrittener" HTML-Regex aussehen würde, werden im Folgenden die Verhaltensweisen von Browsern und der HTML5-Parsing-Algorithmus in der Praxis ziemlich genau beschrieben:

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

Das Folgende entspricht einer recht strengen Definition von XML-Tags (obwohl nicht alle in XML-Namen zulässigen Unicode-Zeichen berücksichtigt werden):

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

Zugegeben, diese berücksichtigen nicht den Umgebungskontext und einige Edge-Fälle, aber selbst solche Dinge könnten erledigt werden, wenn Sie es wirklich wollen (z. B. indem Sie zwischen den Übereinstimmungen eines anderen Regex suchen).

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

51
slevithan

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 aus meiner Sicht ist es nicht so schrecklich, reguläre Ausdrücke für triviale Arbeiten zu verwenden.

Es gibt ein definitiver Blog-Beitrag über das Zuordnen innerster HTML-Elemente, die von Steven Levithan geschrieben wurden.

49
Emre Yazici

Wenn Sie nur die Tag-Namen möchten, sollte dies über Regex möglich sein.

<([a-zA-Z]+)(?:[^>]*[^/] *)?> 

sollte tun, was du brauchst. Aber ich finde die lösung von "moritz" schon in ordnung. Ich habe es am Anfang nicht gesehen.

Für alle Downvoter: In manchen Fällen ist es einfach sinnvoll, Regex zu verwenden, da dies die einfachste und schnellste Lösung sein kann. Ich bin damit einverstanden, dass Sie HTML im Allgemeinen nicht mit regulären Ausdrücken analysieren sollten. Aber Regex kann ein sehr mächtiges Werkzeug sein, wenn Sie eine Teilmenge von HTML haben, in der Sie das Format kennen und nur einige Werte extrahieren möchten. Ich habe das hunderte Male gemacht und fast immer das erreicht, was ich wollte.

41
morja

Das OP scheint nicht zu sagen, was er mit den Tags tun muss. Muss er beispielsweise inneren Text extrahieren oder nur die Tags untersuchen?

Ich bin fest im Lager, dass RegEx nicht das A und O für Textparser ist. Ich habe eine große Menge an Text-Parsing-Code geschrieben, einschließlich dieser Code zum Parsen von HTML-Tags .

Während es stimmt, dass ich mit RegEx nicht so toll bin, halte ich reguläre Ausdrücke für einfach zu starr und schwierig, um sie für diese Art von Analyse beizubehalten.

39
Jonathan Wood

Dies kann Folgendes bewirken:

<.*?[^/]>

Oder ohne die Endungs-Tags:

<[^/].*?[^/]>

Was ist mit den Flame Wars bei HTML-Parsern? HTML-Parser müssen das gesamte Dokument analysieren (und neu erstellen!), Bevor Ihre Suche kategorisiert werden kann. Reguläre Ausdrücke können unter bestimmten Umständen schneller/eleganter sein. Meine 2 Cent ...

34
Paul

Ich denke, das könnte funktionieren

<[a-z][^<>]*(?:(?:[^/]\s*)|(?:\s*[^/]))>

Und das könnte getestet werden hier .


Gemäß w3schools ...

XML-Benennungsregeln

XML-Elemente müssen folgenden Namensregeln folgen:

  • Namen können Buchstaben, Zahlen und andere Zeichen enthalten
  • Namen dürfen nicht mit einer Zahl oder einem Interpunktionszeichen beginnen
  • Namen dürfen nicht mit den Buchstaben xml (oder XML oder Xml usw.) beginnen
  • Namen dürfen keine Leerzeichen enthalten
  • Es kann ein beliebiger Name verwendet werden, es sind keine Wörter reserviert.

Und das Muster, das ich verwendet habe, wird diese Regeln einhalten.

20
Cylian