Veo preguntas todos los días que preguntan cómo analizar o extraer algo de alguna cadena HTML y la primera respuesta / comentario es siempre "¡No use RegEx para analizar HTML, no sea que sienta la ira!" (esa última parte a veces se omite).
Esto es bastante confuso para mí, siempre pensé que, en general, la mejor manera de analizar cualquier cadena complicada es usar una expresión regular. Entonces, ¿cómo funciona un analizador de HTML? ¿No usa expresiones regulares para analizar.
Un argumento particular para usar una expresión regular es que no siempre existe una alternativa de análisis (como JavaScript, donde DOMDocument no es una opción disponible universalmente). jQuery, por ejemplo, parece manejarse bien usando una expresión regular para convertir una cadena HTML en nodos DOM.
No estoy seguro de si usar CW o no, es una pregunta genuina que quiero que se responda y que no pretende ser un hilo de discusión.
fuente
Respuestas:
Por lo general, mediante el uso de un tokenizador. El borrador de la especificación HTML5 tiene un algoritmo extenso para manejar "HTML del mundo real".
fuente
Bueno no.
Si regresa en su cerebro a un curso de teoría de la computación, si tomó uno, o un curso de compiladores, o algo similar, puede recordar que existen diferentes tipos de lenguajes y modelos computacionales. No estoy calificado para entrar en todos los detalles, pero puedo revisar algunos de los puntos principales con usted.
El tipo más simple de lenguaje y computación (para estos propósitos) es un lenguaje regular. Estos pueden generarse con expresiones regulares y reconocerse con autómatas finitos. Básicamente, eso significa que las cadenas de "análisis" en estos lenguajes utilizan el estado, pero no la memoria auxiliar. Ciertamente, HTML no es un lenguaje común. Si lo piensa, la lista de etiquetas se puede anidar de forma arbitraria y profunda. Por ejemplo, las tablas pueden contener tablas y cada tabla puede contener muchas etiquetas anidadas. Con expresiones regulares, es posible que pueda elegir un par de etiquetas, pero ciertamente no nada anidado arbitrariamente.
Un lenguaje simple clásico que no es regular tiene paréntesis correctamente emparejados. Por más que lo intente, nunca podrá construir una expresión regular (o un autómata finito) que siempre funcione. Necesita memoria para realizar un seguimiento de la profundidad de anidación.
Una máquina de estado con una pila de memoria es la siguiente fortaleza del modelo computacional. A esto se le llama autómata push-down y reconoce los lenguajes generados por gramáticas libres de contexto. Aquí, podemos reconocer los paréntesis que coinciden correctamente; de hecho, una pila es el modelo de memoria perfecto para ello.
Bueno, ¿es esto lo suficientemente bueno para HTML? Tristemente no. Tal vez para un XML cuidadosamente validado, de hecho, en el que todas las etiquetas siempre se alinean perfectamente. En HTML del mundo real, puede encontrar fácilmente fragmentos como
<b><i>wow!</b></i>
. Obviamente, esto no se anida, por lo que para analizarlo correctamente, una pila no es lo suficientemente potente.El siguiente nivel de computación son los lenguajes generados por gramáticas generales y reconocidos por las máquinas de Turing. En general, se acepta que este es efectivamente el modelo computacional más sólido que existe: una máquina de estado, con memoria auxiliar, cuya memoria se puede modificar en cualquier lugar. Esto es lo que pueden hacer los lenguajes de programación. Este es el nivel de complejidad donde habita HTML.
Para resumir todo aquí en una oración: para analizar HTML general, necesita un lenguaje de programación real, no una expresión regular.
HTML se analiza de la misma forma en que se analizan otros lenguajes: lexing y parsing. El paso de lexing divide el flujo de caracteres individuales en tokens significativos. El paso de análisis ensambla los tokens, utilizando estados y memoria, en un documento lógicamente coherente sobre el que se puede actuar.
fuente
Las expresiones regulares son solo una forma de analizador. Un analizador HTML honesto será significativamente más complicado de lo que se puede expresar en expresiones regulares, utilizando descenso recursivo , predicción y varias otras técnicas para interpretar correctamente el texto. Si realmente quiere entrar en él, puede consultar lex & yacc y herramientas similares.
La prohibición contra el uso de expresiones regulares para el análisis de HTML probablemente debería escribirse más correctamente como: "No use expresiones regulares ingenuas para analizar HTML ..." (para que no sienta la ira) "... y trate los resultados con precaución". Para ciertos objetivos específicos, una expresión regular puede ser perfectamente adecuada, pero debe tener mucho cuidado para conocer las limitaciones de su expresión regular y ser tan cauteloso como sea apropiado para la fuente del texto que está analizando (por ejemplo, si es entrada del usuario, tenga mucho cuidado).
fuente
Analizar HTML es la transformación de un texto lineal en una estructura de árbol. Las expresiones regulares generalmente no pueden manejar estructuras de árbol. La expresión regular que necesita en cada punto para obtener el siguiente token cambia todo el tiempo. Puede usar expresiones regulares en un analizador, pero necesitará un conjunto completo de expresiones regulares para cada posible estado de análisis.
fuente
Si desea tener una solución al 100%: debe escribir su propio código personalizado que repita el HTML carácter por carácter y debe tener una gran cantidad de lógica para determinar si debe detener el nodo actual e iniciar el siguiente.
La razón es que este es HTML válido:
Pero también esto:
Si está de acuerdo con la "solución al 90%": Entonces, usar un analizador XML para cargar un documento está bien. O usando Regex (aunque el xml es más fácil si luego eres el maestro del contenido).
fuente