Question

Je vois tous les jours des questions demandant comment analyser ou extraire quelque chose de quelque chaîne HTML et la première réponse / commentaire est toujours « Ne pas utiliser RegEx pour analyser HTML, de peur que vous vous sentez la colère! » (Cette dernière partie est parfois omise).

Ce qui est assez déroutant pour moi, j'ai toujours pensé qu'en général, la meilleure façon d'analyser une chaîne complexe consiste à utiliser une expression régulière. Alors, comment fonctionne un analyseur HTML? Ne pas utiliser des expressions régulières pour analyser.

Un argument particulier pour utiliser une expression régulière est qu'il n'y a pas toujours une alternative d'analyse syntaxique (tel que JavaScript, où DOMDocument n'est pas une option universellement disponible). jQuery, par exemple, semble se débrouillent très bien en utilisant une expression régulière pour convertir une chaîne HTML vers des noeuds DOM.

Je ne sais pas si oui ou non à cw cela, il est une véritable question que je veux répondre et pas vraiment destiné à être un fil de discussion.

Était-ce utile?

La solution

En général, en utilisant un tokeniser. Le projet spécification HTML5 a un algorithme vaste pour traiter « monde réel HTML » .

Autres conseils

  

Alors, comment fonctionne un analyseur HTML? Ne pas utiliser des expressions régulières pour analyser?

Eh bien, non.

Si vous arrivez en arrière dans votre cerveau à une théorie bien sûr de calcul, si vous avez pris un, ou un cours de compilateurs, ou quelque chose de similaire, vous souvenez peut-être qu'il existe différents types de langages et modèles de calcul. Je ne suis pas qualifié pour entrer dans tous les détails, mais je peux examiner quelques-unes des principaux points avec vous.

Le plus simple type de langage et calcul (à ces fins) est une langue régulière. Ceux-ci peuvent être générés avec des expressions régulières, et reconnues par les automates finis. En gros, cela signifie que « l'analyse syntaxique » chaînes dans ces langues utilisent l'état, mais pas la mémoire auxiliaire. HTML est certainement pas une langue régulière. Si vous pensez à ce sujet, la liste des balises peuvent être imbriquées arbitrairement profondément. Par exemple, les tables peuvent contenir des tables et chaque table peut contenir beaucoup de balises imbriquées. Avec des expressions régulières, vous pourriez être en mesure de choisir une paire de balises, mais certainement pas quoi que ce soit de façon arbitraire emboîtés.

Une langue simple et classique qui n'est pas régulier est entre parenthèses appariées correctement. Essayez que vous pourriez, vous ne serez jamais en mesure de construire une expression régulière (ou automate fini) qui fonctionnera toujours. Vous avez besoin de mémoire pour garder la trace de la profondeur d'imbrication.

Une machine d'état avec une pile de mémoire est la suivante force du modèle de calcul. On appelle cela un automate de poussée vers le bas, et il reconnaît les langues générées par grammaires hors contexte. Ici, nous pouvons reconnaître entre parenthèses appariés correctement -. En effet, une pile est le modèle de mémoire parfaite pour elle

Eh bien, est-ce assez bon pour HTML? Malheureusement non. Peut-être pour super-duper XML soigneusement validé, en fait, dans lequel toutes les balises ALWAYS parfaitement. Dans HTML dans le monde réel, vous pouvez facilement trouver des petits bouts comme <b><i>wow!</b></i>. Cela ne signifie évidemment pas le nid, donc pour l'analyser correctement, une pile est tout simplement pas assez puissant.

Le niveau suivant de calcul est générée par des langues grammaires générales et reconnues par les machines de Turing. Ceci est généralement acceptée comme étant effectivement le modèle de calcul la plus forte il y a - une machine d'état, la mémoire auxiliaire, dont la mémoire peut être modifiée partout. C'est ce que les langages de programmation peuvent faire. Ceci est le niveau de complexité où vit HTML.

Pour tout résumer ici en une phrase: pour analyser HTML général, vous avez besoin d'un vrai langage de programmation, et non pas une expression régulière

.

HTML est analysé de la même manière d'autres langues sont analysées: lexing et analyse syntaxique. L'étape lexing décompose le flux de caractères individuels en jetons significatifs. L'étape d'analyse assemble les jetons, en utilisant des états et de la mémoire, dans un document logiquement cohérent qui peut être sollicité.

Les expressions régulières ne sont qu'une forme d'analyseur. Un analyseur HTML honnête à la bonté sera beaucoup plus complexe que ce qui peut être exprimé en regexes, en utilisant la descente récursive , la prédiction, et plusieurs autres techniques d'interpréter correctement le texte. Si vous voulez vraiment entrer, vous pouvez consulter & lex yacc et des outils similaires.

L'interdiction d'utiliser des expressions rationnelles pour l'analyse syntaxique HTML devrait probablement être écrit plus correctement que: « Ne pas utiliser naïfs expressions régulières pour analyser HTML ... » (de peur que vous sentez la colère ) "... et traiter les résultats avec prudence." Pour certains objectifs spécifiques, une expression régulière peut bien être tout à fait convenable, mais vous devez être très prudent d'être conscient des limites de votre regex et aussi prudent comme il convient à la source du texte que vous êtes analyse (par exemple, si elle est entrée utilisateur, être très prudent en effet).

Parsing HTML est la transformation d'un texte linéaire dans une structure arborescente. Les expressions régulières ne peuvent pas gérer généralement des structures d'arbres. L'expression régulière dont vous avez besoin à chaque point pour obtenir le jeton suivant change tout le temps. Vous pouvez utiliser des expressions régulières dans un analyseur, mais vous aurez besoin d'un ensemble d'expressions régulières pour chaque état possible d'analyse syntaxique.

Si vous voulez avoir une solution 100%: propre code Vous devez écrire votre personnalisé qui effectue une itération dans le code HTML de caractère par caractère et vous devez avoir une énorme quantité de logique pour déterminer si vous devez arrêter le noeud courant et commencer la suivante.

La raison en est que c'est valide HTML:

<ul>
<li>One
<li>Two
<li>Three
</ul>

Mais alors est la suivante:

<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>

Si vous êtes ok avec « solution à 90% »: Ensuite, en utilisant un analyseur XML pour charger un document est très bien. Ou en utilisant Regex (bien que le XML est plus facile si vous êtes alors maître du contenu).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top