web-dev-qa-db-fra.com

RegEx correspond aux balises ouvertes, à l'exception des balises autonomes XHTML

Je dois faire correspondre toutes ces balises d'ouverture:

<p>
<a href="foo">

Mais pas ceux-ci:

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

Je suis venu avec cela et je voulais être sûr d'avoir bien compris. Je ne fais que capturer le a-z.

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

Je crois que cela dit:

  • Trouver un moins que, alors
  • Trouvez (et capturez) a-z une ou plusieurs fois, puis
  • Trouver zéro ou plusieurs espaces, puis
  • Trouvez n'importe quel caractère zéro ou plusieurs fois, gourmand, sauf /, puis
  • Trouver un plus grand que

Ai-je ce droit? Et plus important encore, qu'en pensez-vous?

1324
Jeff

Vous ne pouvez pas analyser [X] HTML avec regex. Parce que HTML ne peut pas être analysé par regex. Regex n'est pas un outil qui peut être utilisé pour analyser correctement le code HTML. Comme j'ai déjà répondu maintes fois aux questions HTML et regex, l'utilisation de regex ne vous permettra pas de consommer du HTML. Les expressions régulières sont un outil insuffisamment sophistiqué pour comprendre les concepts employés par HTML. HTML n'est pas un langage standard et ne peut donc pas être analysé par des expressions régulières. Les requêtes Regex ne sont pas équipées pour décomposer HTML en parties significatives. tant de fois mais ça ne me va pas. Même les expressions régulières irrégulières améliorées utilisées par Perl ne permettent pas d'analyser le code HTML. Tu ne me feras jamais craquer. HTML est un langage d'une complexité suffisante pour qu'il ne puisse pas être analysé par des expressions régulières. Même Jon Skeet ne peut pas analyser HTML à l'aide d'expressions régulières. Chaque fois que vous essayez d'analyser du HTML avec des expressions régulières, l'enfant impie pleure le sang des vierges et les pirates russes pwn votre webapp. Analyser HTML avec regex invoque des âmes contaminées dans le royaume des vivants. HTML et regex vont ensemble comme l'amour, le mariage et l'infanticide rituel. Le <centre> ne peut pas tenir, c'est trop tard. La force de l'expression rationnelle et du code HTML réunis dans le même espace conceptuel détruira votre esprit, à l'instar de beaucoup d'eau. Si vous analysez HTML avec regex, vous cédez à eux et à leurs manières blasphématoires qui nous condamnent tous à un travail inhumain pour celui dont le nom ne peut pas être exprimé dans le plan multilingue de base, il vient. HTML-plus-regexp va liquéfier les nerfs du sentient pendant que vous observez, votre psyché se fanant sous l’impact de l’horreur. Les analyseurs HTML basés sur Rege̿̔̉x sont le cancer qui tue StackOverflow il est trop tard il est trop tard nous ne pouvons pas être sauvés la trangession d'un chi ensuresld assure que la regex va consommer tous les tissus vivants (à l'exception du HTML qui ne peut pas, comme précédemment prophétisé) cher seigneur, aidez-nous, comment peut-on survivre à ce fléau? utiliser regex pour analyser HTML a condamné l'humanité à une éternité de torture et de brèches de sécurité en utilisant regex en tant qu'outil pour traiter HTML établit unech entre ce monde et le monde redouté des entités en panne (comme les entités SGML, mais plus corrompu) un simple coup d'œilse du monde de regex parseurs pour HTML insTant de transporter un pla conscience de rogrammer inà un world de crier sans cesse, il vient, le pestilent slsa regex-infection wilje dévore ton HTAnalyseur ML, application et existence de tous les temps comme Visual Basic, pire encore il vient il comes ne pas fiGht he com̡e̶s, h̵iS unhho͞ly radiańcé debalises HTML, balises HTML leaki̧n͘g fr̶ǫm ̡yo ͟ur eye͢s̸ ̛l̕ik͏e liqUid pain, la chanson de re̸gular exp reanalyse de ssion va extiNguish les voix de morhomme tal du spIci je peux le voir pouvez-vous voir ̲͚̖͔̙î̩́t̲͎̩̱͔́̋̀ il est beauil final snuffing ole mensonges of Man ALL IS LOŚ͖̩͇̗̪̏̈́T ALL I S LOST ee pon̷y il vients il vientes-il comois til ichou permeates all MON FACE MON FACE godh dieu no NO NOO̼O O NΘ arrêter til un * ̶͑̾̾ ̅ͫ͏̙̤g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨes ͎a̧͈͖r̽̾̈́͒͑e n̑ͧ̌ rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ TO TH̘Ë͖́̉ ͠P̯͍̭O̚ N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬ C̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ


Avez-vous essayé d'utiliser un analyseur XML à la place?


Note du modérateur

Cet article est verrouillé pour empêcher toute modification inappropriée de son contenu. Le message ressemble exactement à ce qu'il est censé être - il n’ya aucun problème avec son contenu. Veuillez ne pas le signaler à notre attention.

4420
bobince

S'il est vrai que demander à l'expression rationnelle d'analyser arbitraire HTML revient à demander à un débutant d'écrire un système d'exploitation, il est parfois approprié d'analyser un ensemble limité, conn de HTML.

Si vous souhaitez regrouper un petit nombre de pages HTML, puis les insérer dans une base de données, les expressions rationnelles peuvent fonctionner correctement. Par exemple, j'ai récemment voulu obtenir les noms, les partis et les districts des représentants fédéraux australiens, que j'ai extraits du site Web du Parlement. C'était un travail limité et ponctuel.

Les regexes ont bien fonctionné pour moi et ont été très rapides à mettre en place.

3139

Je pense que la faille ici est que HTML est un grammaire de Chomsky Type 2 (grammaire libre de contexte) et RegEx est un grammaire de Chomsky Type 3 (grammaire normale) . Etant donné qu'une grammaire de type 2 est fondamentalement plus complexe qu'une grammaire de type 3 (voir la hiérarchie de Chomsky ), elle est mathématiquement impossible analyser XML avec RegEx.

Mais beaucoup essaieront, certains diront même le succès - mais jusqu'à ce que d'autres trouvent la faute et vous fassent complètement perdre.

1966
NealB

N'écoute pas ces gars. Vous pouvez totalement pouvez analyser des grammaires sans contexte avec regex si vous divisez la tâche en morceaux plus petits. Vous pouvez générer le modèle correct avec un script qui effectue chacune de ces tâches dans l’ordre:

  1. Résoudre le problème de l'arrêt.
  2. Place un cercle.
  3. Résolvez le problème du voyageur de commerce en O (log n) ou moins. Si ce n'est pas plus que cela, vous manquerez de RAM et le moteur se bloquera.
  4. Le motif sera assez gros, alors assurez-vous d'avoir un algorithme qui compresse sans perte de données aléatoires.
  5. Presque là - divisez le tout par zéro. Peasy facile.

Je n'ai pas tout à fait terminé la dernière partie moi-même, mais je sais que je me rapproche. Il continue à lancer CthulhuRlyehWgahnaglFhtagnExceptions pour une raison quelconque, je vais donc le porter sur VB 6 et utiliser On Error Resume Next. Je mettrai à jour le code une fois que j'aurai enquêté sur cette étrange porte qui vient de s'ouvrir dans le mur. Hmm.

P.S. Pierre de Fermat a également compris comment le faire, mais la marge dans laquelle il écrivait n'était pas assez grande pour le code.

1273
Justin Morgan

Disclaimer : utilisez un analyseur si vous en avez la possibilité. Cela dit...

C'est la regex que j'utilise (!) Pour correspondre aux balises HTML:

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

Ce n'est peut-être pas parfait, mais j'ai exécuté ce code via un lot de HTML. Notez qu'il attrape même des choses étranges comme <a name="badgenerator"">, qui apparaissent sur le Web.

Je suppose que pour que cela ne corresponde pas aux balises autonomes, vous pouvez aussi utiliser le look négatif de Kobi :

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

ou juste combiner si et si non.

Pour les utilisateurs bas: Ceci est un code fonctionnel issu d'un produit réel. Je doute que quiconque lisant cette page aura l’impression que l’utilisation de regexes en HTML est socialement acceptable.

Mise en garde : Je dois noter que cette expression rationnelle échoue toujours en présence de blocs CDATA, de commentaires et d'éléments de script et de style. La bonne nouvelle est que vous pouvez vous débarrasser de ceux qui utilisent une expression régulière ...

1054
itsadok

Certaines personnes vous diront que la Terre est ronde (ou peut-être que la Terre est un sphéroïde oblat si elles veulent utiliser des mots étranges). Ils mentent.

Certaines personnes vous diront que les expressions régulières ne doivent pas être récursives. Ils vous limitent. Ils ont besoin de vous subjuguer, et ils le font en vous gardant dans l'ignorance.

Vous pouvez vivre dans leur réalité ou prendre la pilule rouge.

Comme Lord Marshal (est-il un parent de la classe Marshal .NET?), J’ai vu le Underverse Verset basé sur la pile et renvoyé avec pouvoirs connaissances que vous ne pouvez pas imaginer. Oui, je pense qu’il y avait un ou deux vieux qui les protégeaient, mais ils regardaient le football à la télévision, alors ce n’était pas difficile.

Je pense que le cas XML est assez simple. Le RegEx (dans la syntaxe .NET), dégonflé et codé en base64 pour le rendre plus facile à comprendre par votre esprit faible, devrait ressembler à ceci:

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

Les options à définir sont RegexOptions.ExplicitCapture. Le groupe de capture que vous recherchez est ELEMENTNAME. Si le groupe de capture ERROR n'est pas vide, une erreur d'analyse est survenue et la regex s'est arrêtée.

Si vous avez des problèmes pour le reconvertir en une expression rationnelle lisible par un humain, ceci devrait vous aider:

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());
    }
}

Si vous n'êtes pas sûr, non, je ne plaisante pas (mais peut-être que je mens). Ça va marcher. J'ai construit des tonnes de tests unitaires pour le tester, et j'ai même utilisé (une partie de) les tests de conformité . Il s'agit d'un tokenizer et non d'un analyseur complet. Il ne divisera donc que le XML en ses composants. Il ne va pas analyser/intégrer les DTD.

Oh ... si vous voulez le code source de la regex, avec quelques méthodes auxiliaires:

regex tokenize un xml ou le regex complet

486
xanatos

Dans Shell, vous pouvez analyser HTML en utilisant sed :

  1. Turing.sed
  2. Écrire un analyseur HTML (devoirs)
  3. ???
  4. Profit!

En relation (pourquoi vous ne devriez pas utiliser de correspondance d'expression régulière):

291
dubiousjim

Je conviens que le bon outil pour analyser XML et , en particulier HTML , est un analyseur syntaxique et non un moteur d’expression régulière. Cependant, comme d'autres l'ont fait remarquer, l'utilisation d'une expression rationnelle est parfois plus rapide, plus simple et plus efficace si vous connaissez le format de données.

Microsoft a en fait une section de Meilleures pratiques pour les expressions régulières dans le .NET Framework et parle spécifiquement de Envisager la source d'entrée .

Les expressions régulières ont des limites, mais avez-vous pris en compte les éléments suivants?

Le framework .NET est unique en ce qui concerne les expressions régulières dans la mesure où il prend en charge définitions du groupe d'équilibrage .

Pour cette raison, je crois que vous POUVEZ analyser XML en utilisant des expressions régulières. Notez cependant qu'il doit être un code XML valide (). Les navigateurs sont très indulgents en HTML et autorisent une syntaxe XML incorrecte à l'intérieur de HTML ). Cela est possible car la "Définition du groupe d'équilibrage" permettra au moteur des expressions régulières d'agir en tant que PDA.

Citation de l'article 1 cité ci-dessus:

. Moteur d’expression régulière NET

Comme décrit ci-dessus, les constructions correctement équilibrées ne peuvent pas être décrites par une expression régulière. Cependant, le moteur des expressions régulières .NET fournit quelques constructions permettant de reconnaître les constructions équilibrées.

  • (?<group>) - place le résultat capturé dans la pile de capture avec le groupe de noms.
  • (?<-group>) - affiche la capture la plus haute avec le groupe de noms de la pile de capture.
  • (?(group)yes|no) - correspond à la partie oui s'il existe un groupe portant le nom groupe sinon ne correspond à aucune partie.

Ces constructions permettent à une expression régulière .NET d'émuler un PDA restreint en autorisant essentiellement des versions simples des opérations de pile: Push, pop et empty. Les opérations simples sont à peu près équivalentes à incrémenter, décrémenter et comparer à zéro respectivement. Cela permet au moteur des expressions régulières .NET de reconnaître un sous-ensemble des langages sans contexte, en particulier ceux qui ne nécessitent qu'un simple compteur. Cela permet aux expressions régulières .NET non traditionnelles de reconnaître des constructions individuelles correctement équilibrées.

Considérez l'expression régulière suivante:

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

Utilisez les drapeaux:

  • Une seule ligne
  • IgnorePatternWhitespace (non nécessaire si vous réduisez l'expression rationnelle et supprimez tous les espaces)
  • IgnoreCase (pas nécessaire)

Expression régulière expliquée (en ligne)

(?=<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

Vous pouvez essayer ceci à n meilleur testeur d'expressions régulières .NET .

J'ai utilisé l'échantillon source de:

<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>

Ceci a trouvé la correspondance:

   <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>

bien qu'il soit sorti comme ça:

<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>

Enfin, j'ai vraiment apprécié l'article de Jeff Atwood: Parsing Html The Cthulhu Way . Assez drôle, il cite la réponse à cette question qui compte actuellement plus de 4k voix.

270
Sam

Je suggère d'utiliser QueryPath pour analyser XML et HTML en PHP. C'est fondamentalement la même syntaxe que jQuery, sauf que c'est du côté serveur.

256
John Fiala

Bien que les réponses que vous ne pouvez pas analyser en HTML avec des expressions rationnelles soient correctes, elles ne s'appliquent pas ici. L'OP veut juste analyser une balise HTML avec des expressions rationnelles, ce qui peut être fait avec une expression régulière.

La regex suggérée est fausse, cependant:

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

Si vous ajoutez quelque chose à la regex, en faisant un retour arrière, il peut être forcé de faire correspondre des choses stupides comme <a >>, [^/] est trop permissif. Notez également que <space>*[^/]* est redondant, car le [^/]* peut également correspondre à des espaces.

Ma suggestion serait

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

(?<! ... ) est (dans les expressions rationnelles Perl) le négatif recherché. Il se lit "un <, puis un mot, puis tout ce qui n'est pas un>, dont le dernier ne peut pas être un/suivi de>".

Notez que cela permet des choses comme <a/ > (tout comme la regex originale), donc si vous voulez quelque chose de plus restrictif, vous devez créer une regex pour faire correspondre les paires d'attributs séparées par des espaces.

215
moritz

Essayer:

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

Il est similaire au vôtre, mais le dernier > ne doit pas être après une barre oblique et accepte également h1.

178
Kobi

Sun Tzu, ancien stratège, général et philosophe chinois, a déclaré:

On dit que si vous connaissez vos ennemis et vous-même, vous pouvez gagner cent batailles sans une seule perte. Si vous ne connaissez que vous-même, mais pas votre adversaire, vous pouvez gagner ou perdre. Si vous ne connaissez ni vous ni votre ennemi, vous vous exposerez toujours à un danger.

Dans ce cas, votre ennemi est HTML et vous êtes soit vous-même, soit un regex. Vous pourriez même être Perl avec une regex irrégulière. Connaître le HTML. Se connaitre.

J'ai composé un haïku décrivant la nature du HTML.

HTML has
complexity exceeding
regular language.

J'ai également composé un haïku décrivant la nature de la regex en Perl.

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 );
    }
}

Sortie:

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

Fondamentalement, définissez simplement les noms de nœuds d’éléments à fermeture automatique, chargez la chaîne HTML complète dans une bibliothèque DOM, récupérez tous les éléments, passez en boucle et filtrez ceux qui ne se ferment pas automatiquement et opérez-les.

Je suis sûr que vous savez déjà maintenant que vous ne devriez pas utiliser regex à cette fin.

154
meder omuraliev

Je ne connais pas votre besoin exact, mais si vous utilisez également .NET, ne pouvez-vous pas utiliser Html ​​Agility Pack ?

Extrait:

Il s'agit d'une bibliothèque de code .NET qui vous permet d'analyser des fichiers HTML "hors du Web". L'analyseur est très tolérant avec le code HTML malformé du "monde réel".

148
GONeale

Vous voulez que le premier > ne soit pas précédé d'un /. Regardez ici pour plus de détails sur la façon de le faire. C'est ce qu'on appelle un regard négatif.

Cependant, une implémentation naïve de cela finira par faire correspondre <bar/></foo> dans cet exemple de document

<foo><bar/></foo>

Pouvez-vous fournir un peu plus d'informations sur le problème que vous essayez de résoudre? Est-ce que vous parcourez les balises par programmation?

135
Jherico

Le W3C explique comment analyser une pseudo expression rationnelle:
Lien W3C

Suivez les liens var pour QName, S et Attribute pour obtenir une image plus claire.
Sur cette base, vous pouvez créer une bonne expression rationnelle pour gérer des tâches telles que le retrait des balises.

123
John-David Dalton

Si vous en avez besoin pour PHP:

Le PHP DOMfonctions ne fonctionnera pas correctement s'il n'est pas correctement formaté en XML. Peu importe à quel point leur utilisation est meilleure pour le reste de l'humanité.

simplehtmldom c'est bien, mais je l'ai trouvé un peu bogué, et la mémoire est assez lourde [Va planter sur de grandes pages.]

Je n'ai jamais utilisé Querypath , donc je ne peux pas commenter sur son utilité.

Un autre à essayer est mon DOMParser , qui est très léger sur les ressources et que j'utilise avec bonheur depuis un certain temps. Simple à apprendre et puissant.

Pour Python et Java, des liens similaires ont été postés.

Pour les votants descendants - je n'ai écrit ma classe que lorsque les analyseurs syntaxiques XML se sont avérés incapables de résister à une utilisation réelle. Les votes religieux empêchent simplement l'affichage de réponses utiles - gardez les choses en perspective, s'il vous plaît.

105
SamGoody

Voici la solution:

<?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]);
?>

Pour le tester en profondeur, j'ai entré dans la chaîne des balises à fermeture automatique comme:

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

J'ai aussi entré des tags avec:

  1. un attribut
  2. plus d'un attribut
  3. attributs dont la valeur est liée soit en guillemets simples ou en guillemets doubles
  4. attributs contenant des guillemets simples lorsque le délimiteur est un guillemet double et inversement
  5. "unfetty" attribue un espace avant le symbole "=", après celui-ci et les deux avant et après celui-ci.

Si vous trouvez quelque chose qui ne fonctionne pas dans la preuve de concept ci-dessus, je suis disponible pour analyser le code afin d'améliorer mes compétences.

<EDIT> J'ai oublié que la question de l'utilisateur était d'éviter l'analyse des balises à fermeture automatique. Dans ce cas, le modèle est plus simple, se transformant en ceci:

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

L'utilisateur @ridgerunner a remarqué que le modèle n'autorisait pas attributs non cités ou attributs sans valeur. Dans ce cas, un réglage précis nous apporte le modèle suivant:

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

</ EDIT>

Comprendre le motif

Si quelqu'un est intéressé à en savoir plus sur le modèle, je fournis une ligne:

  1. la première sous-expression (\ w +) correspond au nom de la balise
  2. la deuxième sous-expression contient le motif d'un attribut. Il est composé de:
    1. un ou plusieurs espaces blancs\s +
    2. le nom de l'attribut (\ w +)
    3. zéro ou plusieurs espaces blancs\s * (c'est possible ou non, laisser des espaces ici)
    4. le symbole "="
    5. encore une fois, zéro ou plusieurs espaces
    6. le délimiteur de la valeur d'attribut, un guillemet simple ou double ('| "). Dans le modèle, le guillemet simple est échappé car il coïncide avec le délimiteur de chaîne PHP. Cette sous-expression est capturée avec le entre parenthèses afin qu'il puisse être référencé à nouveau pour analyser la fermeture de l'attribut, c'est pourquoi il est très important.
    7. la valeur de l'attribut, correspondant à presque n'importe quoi: (. *?); dans cette syntaxe spécifique, en utilisant greedy match (le point d'interrogation après l'astérisque), le moteur RegExp active un opérateur de type "look-ahead" qui correspond à tout sauf à ce qui suit cette sous-expression.
    8. voici le plaisir: la partie\4 est un opérateur de backreference, qui fait référence à une sous-expression définie auparavant dans le motif, dans ce cas, je me réfère à la quatrième sous-expression, qui est le premier délimiteur d'attribut trouvé
    9. zéro ou plusieurs espaces blancs\s *
    10. la sous-expression d'attribut se termine ici, avec la spécification de zéro ou plusieurs occurrences possibles, donnée par l'astérisque.
  3. Ensuite, puisqu’une balise peut se terminer par un espace blanc avant le symbole ">", zéro ou plusieurs espaces sont associés au sous-motif\s *.
  4. La balise à associer peut se terminer par un simple symbole ">", ou une éventuelle fermeture XHTML, qui utilise la barre oblique la précédant: (/> |>). La barre oblique est bien sûr évitée puisqu'elle coïncide avec le délimiteur d'expression régulière.

Petit conseil: pour mieux analyser ce code, il est nécessaire de consulter le code source généré car je n’ai fourni aucun caractère spécial HTML échappé.

94
Emanuele Del Grande

Chaque fois que j'ai besoin d'extraire rapidement quelque chose d'un document HTML, j'utilise Tidy pour le convertir en XML, puis XPath ou XSLT pour obtenir ce dont j'ai besoin. Dans votre cas, quelque chose comme ça:

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

J'ai utilisé un outil open source appelé HTMLParser auparavant. Il est conçu pour analyser le HTML de différentes manières et répond parfaitement à cet objectif. Il peut analyser le code HTML en tant que code différent et vous pouvez facilement utiliser son API pour extraire des attributs du nœud. Vérifiez-le et voyez si cela peut vous aider.

90
wen

J'aime analyser le HTML avec des expressions régulières. Je n'essaie pas d'analyser un HTML idiot délibérément brisé. Ce code est mon analyseur principal (édition Perl):

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

Il s'appelle htmlsplit, divise le code HTML en lignes, avec une balise ou un bloc de texte sur chaque ligne. Les lignes peuvent ensuite être traitées avec d'autres outils de texte et scripts, tels que grep , sed , Perl, etc. Je ne plaisante même pas :) Profitez-en.

Il est assez simple de réaménager mon script Perl Slurp-everything-first en un streaming agréable, si vous souhaitez traiter d’énormes pages Web. Mais ce n'est pas vraiment nécessaire.

Je parie que je vais avoir un vote négatif pour cela.

HTML Split


Contre mon attente, cela a eu quelques votes positifs, je vais donc suggérer quelques expressions plus précises:

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

Ils sont bons pour XML/XHTML.

Avec des variations mineures, il peut faire face au HTML désordonné ... ou convertir le HTML -> XHTML en premier.


Le meilleur moyen d'écrire des expressions régulières est d'utiliser le style Lex / Yacc , et non comme un trait opaque ou des monstruosités multilignes commentées. Je ne l'ai pas encore fait ici. ceux-là en ont à peine besoin.

84
Sam Watkins

Voici un analyseur basé sur PHP qui analyse HTML en utilisant des expressions rationnelles impies. En tant qu'auteur de ce projet, je peux vous dire qu'il est possible d'analyser le code HTML avec regex, mais sans efficacité. Si vous avez besoin d’une solution côté serveur (comme je l’ai fait pour mon plugin wp-Typography WordPress =) ), cela fonctionne.

74
kingjeffrey

Il existe quelques regex de Nice pour remplacer HTML par BBCode ici . Notez bien qu'il n'essaie pas d'analyser complètement le code HTML, mais simplement de le désinfecter. Il peut probablement se permettre de supprimer des tags que son simple "analyseur" ne peut pas comprendre.

Par exemple:

$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

Sur la question des méthodes RegExp pour analyser (x) HTML, la réponse à tous ceux qui ont parlé de certaines limites est la suivante: vous n’avez pas été suffisamment entraîné pour contrôler la force de cette arme puissante, depuis PERSONNE a parlé ici de récursivité .

Un collègue indépendant de RegExp m'a informé de cette discussion, qui n'est certainement pas la première du web sur ce sujet ancien et d'actualité.

Après avoir lu quelques articles, la première chose que j'ai faite a été de rechercher la chaîne "? R" dans ce fil. La seconde était de chercher "récursivité".
Non, vache sacrée, aucune correspondance n'a été trouvée.
Comme personne n’a mentionné le mécanisme principal sur lequel est construit un analyseur, j’ai vite compris que personne n’avait compris.

Si un analyseur (x) HTML a besoin de récursivité, un analyseur RegExp sans récursion ne suffit pas. C'est une construction simple.

Il est difficile de maîtriser l'art noir de RegExp . Il existe donc peut-être d'autres possibilités que nous avons laissées de côté lorsque nous essayons de tester notre solution personnelle pour capturer tout le Web. une main ... eh bien, j'en suis sûr :)

Voici le modèle magique:

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

Juste l'essayer.
Il est écrit sous la forme d'une chaîne PHP. Le modificateur "s" permet donc aux classes d'inclure des nouvelles lignes.
Voici un exemple de note sur le manuel PHP que j'ai écrit en janvier: Référence

(Attention, dans cette note, j’ai utilisé à tort le modificateur "m"; il devrait être effacé, même s’il est ignoré par le moteur RegExp, car aucun ^ ou $ anchorage n’a été utilisé).

Nous pouvons maintenant parler des limites de cette méthode d’un point de vue plus éclairé:

  1. selon l'implémentation spécifique du moteur RegExp, la récursivité peut avoir une limite dans le nombre de modèles imbriqués analysés , mais cela dépend de la langue utilisée
  2. bien que corrompu (x) HTML ne conduise pas en erreurs graves, il n'est pas nettoyé .

Quoi qu'il en soit, il ne s'agit que d'un modèle RegExp, mais il révèle la possibilité de développer de nombreuses implémentations puissantes.
J'ai écrit ce modèle pour alimenter le analyseur de descente récursif d'un moteur de gabarit que j'ai construit dans mon framework, et les performances sont vraiment excellentes, que ce soit en temps d'exécution ou en mémoire. utilisation (rien à voir avec les autres moteurs de template qui utilisent la même syntaxe).

67

Comme de nombreuses personnes l’ont déjà souligné, le langage HTML n’est pas un langage courant, ce qui peut rendre l’analyse très difficile. Ma solution consiste à le transformer en un langage standard à l'aide d'un programme ordonné, puis à utiliser un analyseur XML pour utiliser les résultats. Il y a beaucoup de bonnes options pour cela. Mon programme est écrit en utilisant Java avec la bibliothèque jtidy pour convertir le code HTML en XML, puis Jaxen pour xpath dans le résultat.

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

Les parties expliquées:

<: caractère de départ

\s*: il peut y avoir des espaces avant le nom de la balise (moche mais possible).

(\w+): les étiquettes peuvent contenir des lettres et des chiffres (h1). Eh bien, \w correspond également à '_', mais cela ne fait pas de mal, je suppose. Si vous êtes curieux, utilisez plutôt ([a-zA-Z0-9] +).

[^/>]*: tout sauf > et / jusqu'à la fermeture de >

>: fermer >

UNRELATED

Et aux gens qui sous-estiment les expressions régulières en disant qu’elles n’ont que le pouvoir des langages ordinaires:

unenbanban qui n'est pas régulier ni même dépourvu de contexte, peut être associé à ^(a+)b\1b\1$

Références arrière FTW !

60
daghan

Si vous essayez simplement de trouver ces balises (sans ambitions d'analyse), essayez cette expression régulière:

/<[^/]*?>/g

Je l'ai écrit en 30 secondes et testé ici: http://gskinner.com/RegExr/

Il correspond aux types de balises que vous avez mentionnés, tout en ignorant les types que vous avez dit vouloir ignorer.

54
Lonnie Best

Il me semble que vous essayez de faire correspondre les balises sans "/" à la fin. Essaye ça:

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

Il est vrai que lors de la programmation, il est généralement préférable d'utiliser des analyseurs syntaxiques et des API dédiés plutôt que des expressions régulières lors de l'utilisation de HTML, en particulier si la précision est primordiale (par exemple, si votre traitement peut avoir des implications en termes de sécurité). Cependant, je ne pense pas à une vue dogmatique que le balisage de style XML ne devrait jamais être traité avec des expressions régulières. Il existe des cas où les expressions régulières constituent un excellent outil pour le travail, par exemple lors de modifications ponctuelles dans un éditeur de texte, de la réparation de fichiers XML cassés ou de la gestion de formats de fichiers qui ressemblent mais ne sont pas tout à fait au format XML. Il y a certains problèmes à connaître, mais ils ne sont ni insurmontables ni même nécessairement pertinents.

Une expression rationnelle simple telle que <([^>"']|"[^"]*"|'[^']*')*> est généralement suffisante, dans des cas tels que ceux que je viens de mentionner. C'est une solution naïve, tout bien considéré, mais elle autorise correctement les symboles > non codés dans les valeurs d'attribut. Si vous recherchez, par exemple, une balise table, vous pouvez l’adapter en tant que </?table\b([^>"']|"[^"]*"|'[^']*')*>.

Juste pour donner une idée de ce à quoi ressemblerait une regex HTML plus "avancée", voici un travail assez respectable consistant à émuler le comportement de navigateur dans le monde réel et l'algorithme d'analyse HTML5:

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

Les éléments suivants correspondent à une définition assez stricte des balises XML (bien qu'elle ne tienne pas compte de l'ensemble des caractères Unicode autorisés dans les noms XML):

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

Certes, ils ne tiennent pas compte du contexte et de quelques cas Edge, mais même de tels problèmes pourraient être traités si vous le souhaitiez vraiment (par exemple, en effectuant une recherche entre les correspondances d'une autre expression rationnelle).

À la fin de la journée, utilisez l'outil le plus approprié pour le travail, même dans les cas où cet outil se trouve être une regex.

51
slevithan

Bien qu’il ne soit ni approprié ni efficace d’utiliser des expressions régulières à cette fin, celles-ci apportent parfois des solutions rapides aux problèmes de correspondance simples et, à mon avis, il n’est pas si horrible d’utiliser des expressions régulières pour des travaux triviaux.

Il y a un billet de blog définitif à propos de la correspondance des éléments HTML les plus internes écrits par Steven Levithan.

49
Emre Yazici

Si vous ne voulez que les noms de balises, il devrait être possible de le faire par regex.

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

devrait faire ce dont vous avez besoin. Mais je pense que la solution de "moritz" est déjà bien. Je ne l'ai pas vu au début.

Pour tous les votants: Dans certains cas, il est logique d'utiliser regex, car il peut s'agir de la solution la plus simple et la plus rapide. Je conviens qu'en général, vous ne devriez pas analyser HTML avec regex. Mais regex peut être un outil très puissant lorsque vous avez un sous-ensemble de HTML où vous connaissez le format et souhaitez extraire certaines valeurs. Je l'ai fait des centaines de fois et presque toujours obtenu ce que je voulais.

41
morja

Le PO ne semble pas dire ce qu'il doit faire avec les balises. Par exemple, doit-il extraire du texte interne ou simplement examiner les balises?

Je suis fermement dans le camp qui dit que RegEx n'est pas le meilleur analyseur de texte. J'ai écrit une grande quantité de code d'analyse de texte comprenant ce code pour analyser les balises HTML .

Bien qu'il soit vrai que je ne suis pas génial avec RegEx, je considère les expressions rationnelles comme trop rigides et difficiles à conserver pour ce type d'analyse.

39
Jonathan Wood

Cela peut faire:

<.*?[^/]>

Ou sans les balises de fin:

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

Qu'en est-il des guerres de flammes sur les analyseurs HTML? Les analyseurs HTML doivent analyser (et reconstruire!) L'intégralité du document avant qu'il ne puisse classer votre recherche. Les expressions régulières peuvent être plus rapides/élégantes dans certaines circonstances. Mes 2 centimes ...

34
Paul

Je pense que cela pourrait fonctionner

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

Et cela pourrait être testé ici .


Selon w3schools ...

Règles de nommage XML

Les éléments XML doivent suivre ces règles de nommage:

  • Les noms peuvent contenir des lettres, des chiffres et d'autres caractères
  • Les noms ne peuvent pas commencer par un chiffre ou un caractère de ponctuation
  • Les noms ne peuvent pas commencer par les lettres xml (ou XML, ou XML, etc.)
  • Les noms ne peuvent pas contenir d'espaces
  • Tout nom peut être utilisé, aucun mot n'est réservé.

Et le modèle que j'ai utilisé va respecter ces règles.

20
Cylian