validate pattern only html regex xhtml

html - validate - pattern only numbers



RegEx coinciden con las etiquetas abiertas excepto las etiquetas autocontenidas XHTML (30)

Necesito hacer coincidir todas estas etiquetas de apertura:

<p> <a href="foo">

Pero no estos:

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

Se me ocurrió esto y quería asegurarme de que lo tengo bien. Solo estoy capturando el az .

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

Creo que dice:

  • Encuentra un menor que, entonces
  • Encuentra (y captura) az una o más veces, luego
  • Encuentra cero o más espacios, entonces
  • Encuentra cualquier carácter cero o más veces, codicioso, excepto / , luego
  • Encontrar un mayor que

¿Tengo ese derecho? Y lo más importante, ¿qué te parece?



En shell, puedes analizar HTML usando:

  • aunque sed

    1. Turing.sed
    2. Escribir HTML analizador (tarea)
    3. ???
    4. ¡Lucro!
  • hxselect del hxselect html-xml-utils

  • vim / ex (que puede saltar fácilmente entre etiquetas html ), por ejemplo:

    • Eliminar etiqueta de estilo con código interno:

      $ curl -s http://example.com/ | ex -s +''/<style.*/norm nvatd'' +%p -cq! /dev/stdin

  • grep , por ejemplo:

    • extrayendo html externo de H1:

      $ curl -s http://example.com/ | grep -o ''<h1>.*</h1>'' <h1>Example Domain</h1>

    • extrayendo el cuerpo:

      $ curl -s http://example.com/ | tr ''/n'' '' '' | grep -o ''<body>.*</body>'' <body> <div> <h1>Example Domain</h1> ...

  • html2text para el análisis de texto sin formato:

    • como tablas de análisis :

      $ html2text foo.txt | column -ts''|''

  • usando xpath ( XML::XPath módulo perl), vea el ejemplo aquí

  • Perl o Python (ver ejemplo de @Gilles )

  • para analizar varios archivos a la vez, consulte: ¿Cómo analizar cientos de archivos de código fuente HTML en shell?

Relacionados (por qué no deberías usar la expresión regular):


Estoy de acuerdo en que la herramienta correcta para analizar XML y especialmente HTML es un analizador y no un motor de expresiones regulares. Sin embargo, como han señalado otros, a veces usar una expresión regular es más rápido, más fácil y hace el trabajo si conoce el formato de los datos.

En realidad, Microsoft tiene una sección de Mejores prácticas para expresiones regulares en el .NET Framework y habla específicamente sobre Considerar la fuente de entrada .

Las expresiones regulares tienen limitaciones, pero ¿has considerado lo siguiente?

El marco .NET es único cuando se trata de expresiones regulares, ya que admite definiciones de grupos de equilibrio .

Por esta razón, creo que PUEDES analizar XML usando expresiones regulares. Sin embargo, tenga en cuenta que debe ser un XML válido (los navegadores son muy indulgentes con el HTML y permiten una sintaxis XML incorrecta dentro del HTML ) Esto es posible ya que la "Definición de grupo de equilibrio" permitirá que el motor de expresiones regulares actúe como un PDA.

Cita del artículo 1 citado anteriormente:

Motor de Expresión Regular .NET

Como se describió anteriormente, las construcciones adecuadamente equilibradas no se pueden describir mediante una expresión regular. Sin embargo, el motor de expresiones regulares .NET proporciona algunas construcciones que permiten reconocer construcciones equilibradas.

  • (?<group>) : empuja el resultado capturado en la pila de captura con el grupo de nombres.
  • (?<-group>) : muestra la captura más alta con el grupo de nombres fuera de la pila de captura.
  • (?(group)yes|no) : coincide con la parte sí si existe un grupo con el nombre del grupo, de lo contrario no coincide con ninguna parte.

Estas construcciones permiten que una expresión regular .NET emule un PDA restringido permitiendo esencialmente versiones simples de las operaciones de pila: push, pop y empty. Las operaciones simples son prácticamente equivalentes a incrementar, disminuir y comparar a cero respectivamente. Esto permite que el motor de expresiones regulares .NET reconozca un subconjunto de lenguajes libres de contexto, en particular los que solo requieren un contador simple. Esto a su vez permite que las expresiones regulares .NET no tradicionales reconozcan construcciones individuales adecuadamente equilibradas.

Considera la siguiente expresión regular:

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

Usa las banderas:

  • Linea sola
  • IgnorePatternWhitespace (no es necesario si contrae la expresión regular y elimina todos los espacios en blanco)
  • IgnoreCase (no es necesario)

Expresión regular explicada (en línea)

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

Puedes probar esto en A Better .NET Regular Expression Tester .

Utilicé la fuente de muestra 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>

Esto encontró el partido:

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

aunque en realidad salió así:

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

Por último, me gustó mucho el artículo de Jeff Atwood: Parsing Html The Cthulhu Way . Curiosamente, cita la respuesta a esta pregunta que actualmente tiene más de 4k votos.


Hay personas que te dirán que la Tierra es redonda (o quizás que la Tierra es un esferoide oblato si quieren usar palabras extrañas). Están mintiendo.

Hay personas que te dirán que las expresiones regulares no deben ser recursivas. Ellos te están limitando. Necesitan subyugarte, y lo hacen manteniéndote en la ignorancia.

Puedes vivir en su realidad o tomar la píldora roja.

Al igual que Lord Marshal (¿es un pariente de la clase Marshal .NET?), He visto el Regex-Verse basado en la pila Underversa y regresé con poderes que no puedes imaginar. Sí, creo que había un Viejo o dos que los protegían, pero estaban viendo fútbol en la televisión, así que no fue difícil.

Creo que el caso XML es bastante simple. El RegEx (en la sintaxis de .NET), desinflado y codificado en base64 para facilitar su comprensión por parte de su débil mente, debería ser algo como esto:

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

Las opciones para establecer es RegexOptions.ExplicitCapture . El grupo de captura que está buscando es ELEMENTNAME . Si el ERROR grupo de captura no está vacío, hubo un error de análisis y el Regex se detuvo.

Si tiene problemas para reconvertirlo a una expresión regular legible para humanos, esto debería ayudar:

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 no está seguro, no, no estoy bromeando (pero quizás esté mintiendo). Funcionará. He construido toneladas de pruebas unitarias para probarlo, e incluso he usado (parte de) las pruebas de conformidad . Es un tokenizador, no un analizador completo, por lo que solo dividirá el XML en sus componentes. No analizará / integrará las DTD.

Oh ... si quieres el código fuente de la expresión regular, con algunos métodos auxiliares:

regex para tokenizar un xml o el regex llano completo


No escuches a estos chicos. Puede analizar totalmente las gramáticas libres de contexto con expresiones regulares si divide la tarea en partes más pequeñas. Puede generar el patrón correcto con un script que haga cada uno de estos en orden:

  1. Resuelve el problema de la detención.
  2. Cuadrar un círculo.
  3. Calcule el problema del vendedor ambulante en O (log n) o menos. Si es más que eso, te quedarás sin memoria RAM y el motor se bloqueará.
  4. El patrón será bastante grande, así que asegúrate de tener un algoritmo que comprima los datos aleatorios sin pérdidas.
  5. Casi allí, simplemente divide todo por cero. Pan comido.

No he terminado la última parte, pero sé que me estoy acercando. Sigue lanzando CthulhuRlyehWgahnaglFhtagnException s por alguna razón, así que lo CthulhuRlyehWgahnaglFhtagnException a VB 6 y lo CthulhuRlyehWgahnaglFhtagnException On Error Resume Next . Actualizaré con el código una vez que investigue esta extraña puerta que se acaba de abrir en la pared. Hmm

El PS Pierre de Fermat también descubrió cómo hacerlo, pero el margen que estaba escribiendo no era lo suficientemente grande para el código.


No se puede analizar [X] HTML con expresiones regulares. Porque HTML no puede ser analizado por regex. Regex no es una herramienta que se puede utilizar para analizar correctamente HTML. Como he respondido en las preguntas de HTML y expresiones regulares aquí muchas veces antes, el uso de expresiones regulares no le permitirá consumir HTML. Las expresiones regulares son una herramienta que no es lo suficientemente sofisticada para comprender las construcciones empleadas por HTML. HTML no es un lenguaje regular y, por lo tanto, no puede ser analizado por expresiones regulares. Las consultas Regex no están equipadas para desglosar HTML en sus partes significativas. Tantas veces pero no me está llegando. Incluso las expresiones regulares irregulares mejoradas utilizadas por Perl no están a la altura de analizar HTML. Nunca me harás rajar. HTML es un lenguaje de complejidad suficiente que no puede ser analizado por expresiones regulares. Incluso Jon Skeet no puede analizar HTML usando expresiones regulares. Cada vez que intentas analizar HTML con expresiones regulares, el niño profano llora la sangre de las vírgenes y los piratas informáticos rusos desarrollan tu aplicación web. Al analizar HTML con expresiones regulares convoca almas contaminadas en el reino de los vivos. HTML y expresiones regulares van juntos como el amor, el matrimonio y el infanticidio ritual. El <center> no puede mantenerlo es demasiado tarde. La fuerza de expresiones regulares y HTML juntas en el mismo espacio conceptual destruirá tu mente como tanta masilla acuosa. Si analizas HTML con expresiones regulares, te estás entregando a Ellos y sus formas blasfemas que nos condenan a todos a un trabajo inhumano para Aquel cuyo nombre no puede expresarse en el Plano Bilingüe Básico, él viene. HTML-plus-regexp licuará los nervios de los sintientes mientras usted observa, su psique marchita en el ataque del horror. Los analizadores de HTML basados ​​en Rege̿̔̉x son el cáncer que está matando a . Es demasiado tarde, es demasiado tarde. No podemos guardar la transacción de un niño. Se asegura que la expresión regular consumirá todo el tejido vivo (excepto el HTML que no puede, como se profetizó anteriormente), querido señor. ¿Cómo puede alguien sobrevivir a este flagelo usando expresiones regulares para analizar HTML ha condenado a la humanidad a una eternidad de temores de tortura y agujeros de seguridad utilizando rege x como una herramienta para procesar HTML? establece una brecha entre este mundo y el temido reino de las entidades en quiebra (como Entidades SGML, pero más corruptas, un simple vistazo al mundo de los analizadores de HTML para transportar constantemente la conciencia de un programador en lugar de gritos incesantes, él viene , el pestilente de la infección de infecciones. l devorar a su HT ML analizador, la aplicación y la existencia de todos los tiempos como Visual Basic sólo peor venga, com es no luchar h e viene, HI s UNHOLY Resplandor de stro҉ying todos Enli ̈Ghtenment, etiquetas HTML con fugas fr̶ǫm ur yo ojos como líq uido p ain, el canto de análisis regulares exp re sión se EXTI nguish las voces de hombre mor Tal desde el sp aquí puedo ver que puedes verlo Es bello, inal snuf duda, la mentira del hombre. TODO ES LO QUE SE ENCUENTRA CON EL PUEBLO, EL PODER, EL PUEBLO, ELLOS VAN A LOS inal snuf COMUNICADOS O inal snuf AL MIS FAC E MI CARA h dios n NO NOO̼ O ENCENDIDO Θ para y an * ̶͑̾̾ g͇̫͛͆̾ͫ̑͆l͖͉̗̩̳̟̍ͫͥͨ e̠̅s ͎a̧͈͖r̽̾̈́͒͑e n ot rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆ ZA̡͊͠͝LGΌ ISͮ̂҉̯͈͕̹̘̱ T O͇̹̺ͅƝ̴ȳ̳ TH Ë͖́̉P͠O N̐Y̡ H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝ S̨̥̫͎̭ͯ̿̔̀ͅ

¿Has intentado usar un analizador XML en su lugar?

Nota del moderador

Esta publicación está bloqueada para evitar ediciones inapropiadas de su contenido. La publicación se ve exactamente como debe verse, no hay problemas con su contenido. Por favor, no lo marque para nuestra atención.


Si bien es cierto que pedir expresiones regulares para analizar HTML arbitrario es como pedirle a un principiante que escriba un sistema operativo, a veces es apropiado analizar un conjunto de HTML conocido y limitado .

Si tiene un pequeño conjunto de páginas HTML de las que desea raspar los datos y luego rellenarlos en una base de datos, las expresiones regulares pueden funcionar bien. Por ejemplo, recientemente quise obtener los nombres, partidos y distritos de los Representantes federales de Australia, que obtuve del sitio web del Parlamento. Este fue un trabajo limitado, de una sola vez.

Los Regexes funcionaron bien para mí y fueron muy rápidos de configurar.


Si bien las respuestas que no puede analizar HTML con expresiones regulares son correctas, no se aplican aquí. El OP solo quiere analizar una etiqueta HTML con expresiones regulares, y eso es algo que se puede hacer con una expresión regular.

La expresión regular sugerida es incorrecta, sin embargo:

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

Si agrega algo a la expresión regular, al realizar el seguimiento se puede forzar para que coincida con cosas tontas como <a >> , [^/] es demasiado permisivo. También tenga en cuenta que <space>*[^/]* es redundante, porque [^/]* también puede hacer coincidir espacios.

Mi sugerencia seria

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

Donde (?<! ... ) es (en las expresiones regulares de Perl) el look-behind negativo. Lee "a <, luego una palabra, luego cualquier cosa que no sea una>, la última de las cuales puede no ser una /, seguida de>".

Tenga en cuenta que esto permite cosas como <a/ > (al igual que la expresión regular original), por lo que si desea algo más restrictivo, debe crear una expresión regular para hacer coincidir los pares de atributos separados por espacios.


Sugiero usar QueryPath para analizar XML y HTML en PHP. Es básicamente la misma sintaxis que jQuery, solo que está en el lado del servidor.


Tratar:

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

Es similar al tuyo, pero el último >no debe ser después de una barra, y también acepta h1.


Descargo de responsabilidad : use un analizador si tiene la opción. Dicho esto ...

Esta es la expresión regular que uso (!) Para hacer coincidir las etiquetas HTML:

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

Puede que no sea perfecto, pero corrí este código a través de un montón de HTML. Tenga en cuenta que incluso <a name="badgenerator""> cosas extrañas como <a name="badgenerator""> , que aparecen en la web.

Supongo que para que no coincida con las etiquetas autocontenidas, querrías usar el look-behind negativo de Kobi :

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

o simplemente combinar si y si no.

Para downvoters: Este es un código de trabajo de un producto real. Dudo que alguien que lea esta página tenga la impresión de que es socialmente aceptable usar expresiones regulares en HTML.

Advertencia : debo tener en cuenta que esta expresión regular aún se descompone en presencia de bloques CDATA, comentarios, elementos de estilo de comandos y estilo de escritura. La buena noticia es que puede deshacerse de aquellos que usan un regex ...


Aquí está la solución:

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

Para probarlo profundamente, ingresé en la cadena de etiquetas de cierre automático como:

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

También ingresé etiquetas con:

  1. un atributo
  2. más de un atributo
  3. atributos cuyo valor está enlazado en comillas simples o en comillas dobles
  4. atributos que contienen comillas simples cuando el delimitador es una comilla doble y viceversa
  5. Los atributos "unpretty" con un espacio antes del símbolo "=", después de él y ambos antes y después.

Si encuentra algo que no funciona en la prueba de concepto anterior, estoy disponible para analizar el código para mejorar mis habilidades.

<EDIT> Olvidé que la pregunta del usuario era evitar el análisis de las etiquetas de cierre automático. En este caso el patrón es más sencillo, convirtiéndose en este:

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

El usuario @ridgerunner notó que el patrón no permite atributos sin comillas o atributos sin valor . En este caso un ajuste fino nos trae el siguiente patrón:

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

</EDIT>

Entendiendo el patrón

Si alguien está interesado en aprender más sobre el patrón, proporciono alguna línea:

  1. la primera subexpresión (/ w +) coincide con el nombre de la etiqueta
  2. la segunda subexpresión contiene el patrón de un atributo. Está compuesto por:
    1. uno o más espacios en blanco / s +
    2. el nombre del atributo (/ w +)
    3. cero o más espacios en blanco / s * (es posible o no, dejando espacios en blanco aquí)
    4. el símbolo "="
    5. de nuevo, cero o más espacios en blanco
    6. el delimitador del valor del atributo, una comilla simple o doble (''| "). En el patrón, la comilla simple se escapa porque coincide con el delimitador de cadena PHP. Esta subexpresión se captura con los paréntesis para que pueda ser referenciada Una vez más para analizar el cierre del atributo, es por eso que es muy importante.
    7. el valor del atributo, emparejado por casi cualquier cosa: (. *?); en esta sintaxis específica, utilizando la coincidencia codiciosa (el signo de interrogación después del asterisco), el motor RegExp habilita un operador similar a "mirar hacia adelante", que coincide con cualquier cosa menos lo que sigue a esta subexpresión
    8. aquí viene la diversión: la parte / 4 es un operador de referencia inversa , que se refiere a una sub-expresión definida antes en el patrón, en este caso, me refiero a la cuarta sub-expresión, que es el primer delimitador de atributo encontrado
    9. cero o más espacios en blanco / s *
    10. la subexpresión del atributo termina aquí, con la especificación de cero o más ocurrencias posibles, dada por el asterisco.
  3. Luego, dado que una etiqueta puede terminar con un espacio en blanco antes del símbolo ">", cero o más espacios en blanco coinciden con el sub-patrón / s *.
  4. La etiqueta a coincidir puede terminar con un simple ">" símbolo, o un posible cierre XHTML, que hace uso de la barra inclinada anterior: (/> |>). La barra es, por supuesto, escapada ya que coincide con el delimitador de expresiones regulares.

Pequeño consejo: para analizar mejor este código, es necesario mirar el código fuente generado, ya que no proporcioné ningún tipo de caracteres HTML que escapen.


Aunque no es adecuado y efectivo usar expresiones regulares para ese propósito, a veces las expresiones regulares brindan soluciones rápidas para problemas de coincidencia simples y, en mi opinión, no es tan horrible utilizar expresiones regulares para trabajos triviales.

Hay una publicación de blog definitiva sobre cómo combinar elementos internos de HTML escritos por Steven Levithan.


Me parece que estás intentando hacer coincidir las etiquetas sin una "/" al final. Prueba esto:

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


Si necesita esto para PHP:

Las functionsDOM de PHP no funcionarán correctamente a menos que tengan el formato XML correcto. No importa cuánto mejor sea su uso para el resto de la humanidad.functions

simplehtmldom es bueno, pero lo encontré un poco con errores, y es bastante pesado en memoria [Se estrellará en páginas grandes.]

Nunca he usado QueryPath , así que no puedo comentar sobre su utilidad.

Otro que DOMParser probar es mi DOMParser que es muy ligero en cuanto a recursos y lo he estado utilizando felizmente por un tiempo. Fácil de aprender y potente.

Para Python y Java, se publicaron enlaces similares.

Para los downvoters: solo escribí mi clase cuando los analizadores XML no pudieron soportar el uso real. Las votaciones religiosas simplemente evitan que se publiquen respuestas útiles; mantenga las cosas dentro de la perspectiva de la pregunta, por favor.


Si simplemente está tratando de encontrar esas etiquetas (sin ambiciones de análisis) intente esta expresión regular:

/<[^/]*?>/g

Lo escribí en 30 segundos y lo probé aquí: http://gskinner.com/RegExr/

Coincide con los tipos de etiquetas que mencionaste, mientras que ignora los tipos que dijiste que querías ignorar.


Sun Tzu, un antiguo estratega, general y filósofo chino, dijo:

Se dice que si conoces a tus enemigos y te conoces a ti mismo, puedes ganar cien batallas sin una sola pérdida. Si solo te conoces a ti mismo, pero no a tu oponente, puedes ganar o perder. Si no te conoces a ti mismo ni a tu enemigo, siempre te pondrás en peligro.

En este caso, su enemigo es HTML y usted es uno mismo o regex. Incluso podría ser Perl con expresiones regulares irregulares. Saber HTML Conocete a ti mismo.

He compuesto un haiku que describe la naturaleza de HTML.

HTML has complexity exceeding regular language.

También he compuesto un haiku que describe la naturaleza de la expresión regular en Perl.

The regex you seek is defined within the phrase <([a-zA-Z]+)(?:[^>]*[^/]*)?>


Aquí hay un analizador basado en PHP que analiza HTML usando alguna expresión regular impía. Como autor de este proyecto, puedo decirles que es posible analizar HTML con expresiones regulares, pero no es eficiente. Si necesita una solución del lado del servidor (como lo hice con mi complemento wp-Typography WordPress ), esto funciona.


Como muchas personas ya han señalado, el HTML no es un lenguaje regular, lo que puede dificultar el análisis. Mi solución a esto es convertirlo en un lenguaje regular usando un programa ordenado y luego usar un analizador XML para consumir los resultados. Hay muchas buenas opciones para esto. Mi programa se escribe usando Java con la biblioteca jtidy para convertir el HTML en XML y luego Jaxen en xpath en el resultado.


Cuando necesito extraer rápidamente algo de un documento HTML, uso Tidy para convertirlo a XML y luego uso XPath o XSLT para obtener lo que necesito. En tu caso, algo como esto:

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


El W3C explica el análisis en una forma de pseudo regexp:
Enlace W3C

Siga los enlaces para var QName, Sy Attributepara obtener una imagen más clara.
En base a eso, puedes crear una expresión regular bastante buena para manejar cosas como eliminar etiquetas.


Hay algunos regexes agradables para reemplazar HTML con BBCode here . Para todos los que no lo son, tenga en cuenta que no está intentando analizar HTML completamente, solo para desinfectarlo. Probablemente pueda permitirse matar etiquetas que su simple "analizador" no puede entender.

Por ejemplo:

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


He utilizado una herramienta de código abierto llamada HTMLParser antes. Está diseñado para analizar HTML de varias maneras y cumple su cometido bastante bien. Puede analizar HTML como treenode diferente y puede usar fácilmente su API para obtener atributos fuera del nodo. Compruébelo y vea si esto puede ayudarle.


Me gusta analizar HTML con expresiones regulares. No intento analizar HTML idiota que se rompe deliberadamente. Este código es mi analizador principal (edición 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

Se llama htmlsplit, divide el HTML en líneas, con una etiqueta o parte de texto en cada línea. Las líneas pueden procesarse aún más con otras herramientas de texto y scripts, como grep , sed , Perl, etc. Ni siquiera estoy bromeando.

Es lo suficientemente simple como para reorganizar mi script de Perl slurp-everything-first en una buena opción de transmisión, si desea procesar enormes páginas web. Pero no es realmente necesario.

Apuesto a que voy a ser votado por esto.

División HTML

Contra mi expectativa, esto tuvo algunos votos positivos, por lo que sugeriré algunas expresiones regulares mejores:

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

Son buenos para XML / XHTML.

Con pequeñas variaciones, puede hacer frente al HTML desordenado ... o convertir el HTML -> XHTML primero.

La mejor manera de escribir expresiones regulares es en el estilo de Lex / Yacc , no como opacos de una sola línea o como monstruosidades multilínea comentadas. Todavía no hice eso aquí; estos apenas lo necesitan.


No sé su necesidad exacta para esto, pero si también está utilizando .NET, ¿no podría usar Html Agility Pack ?

Extracto:

Es una biblioteca de códigos .NET que le permite analizar archivos HTML "fuera de la web". El analizador es muy tolerante con el HTML del "mundo real" mal formado.


Quieres que el primero >no vaya precedido por un /. Busque here detalles sobre cómo hacer eso. Se conoce como aspecto negativo por detrás.

Sin embargo, una implementación ingenua de eso terminará coincidiendo <bar/></foo>en este documento de ejemplo

<foo><bar/></foo>

¿Puede proporcionar un poco más de información sobre el problema que está tratando de resolver? ¿Estás iterando a través de etiquetas programáticamente?


Recientemente escribí un desinfectante HTML en Java. Se basa en un enfoque mixto de expresiones regulares y código Java. Personalmente, odio las expresiones regulares y su insensatez (legibilidad, facilidad de mantenimiento, etc.), pero si reduce el alcance de sus aplicaciones, puede adaptarse a sus necesidades. De todos modos, mi desinfectante usa una lista blanca para las etiquetas HTML y una lista negra para algunos atributos de estilo.

Para su comodidad, he configurado un área de juegos para que pueda probar si el código coincide con sus requisitos: área de juegos y código de Java . Sus comentarios serán apreciados.

Hay un pequeño artículo que describe este trabajo en mi blog: http://roberto.open-lab.com


Sobre la pregunta de los métodos RegExp para analizar (x) HTML, la respuesta a todos los que hablaron sobre algunos límites es: no has sido entrenado lo suficiente como para gobernar la fuerza de esta poderosa arma, ya que NADIE aquí habló sobre la recursión .

Un colega de RegExp-agnostic me notificó esta discusión, que ciertamente no es la primera en la web sobre este tema antiguo y candente.

Después de leer algunas publicaciones, lo primero que hice fue buscar la cadena "? R" en este hilo. El segundo fue buscar sobre "recursión".
No, vaca sagrada, no se encontró ninguna coincidencia.
Como nadie mencionó el mecanismo principal en el que se basa el analizador, pronto me di cuenta de que nadie entendía el problema.

Si un analizador (x) HTML necesita recursión, un analizador RegExp sin recursión no es suficiente para este propósito. Es una construcción simple.

El arte negro de RegExp es difícil de dominar , así que tal vez haya otras posibilidades que dejamos de lado al probar y probar nuestra solución personal para capturar toda la web con una mano ... Bueno, estoy seguro de ello :)

Aquí está el patrón mágico:

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

Solo inténtalo.
Está escrito como una cadena PHP, por lo que el modificador "s" hace que las clases incluyan líneas nuevas.
Aquí hay una nota de muestra en el manual de PHP que escribí en enero: Reference

(Tenga cuidado, en esa nota usé incorrectamente el modificador "m"; debería borrarse, a pesar de que el motor RegExp lo descarta, ya que no se usó ancla ^ o $).

Ahora, podríamos hablar sobre los límites de este método desde un punto de vista más informado:

  1. De acuerdo con la implementación específica del motor RegExp, la recursión puede tener un límite en el número de patrones anidados analizados , pero depende del idioma utilizado.
  2. Aunque el código HTML dañado (x) no genera errores graves, no está saneado .

De todos modos, es solo un patrón RegExp, pero revela la posibilidad de desarrollar muchas implementaciones poderosas.
Escribí este patrón para alimentar el analizador de descenso recursivo de un motor de plantillas que incorporé en mi marco, y los rendimientos son realmente excelentes, tanto en tiempos de ejecución como en uso de memoria (nada que ver con otros motores de plantillas que usan la misma sintaxis).


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

Salida:

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

Básicamente, simplemente defina los nombres de los nodos de elementos que se cierran automáticamente, cargue toda la cadena html en una biblioteca DOM, capture todos los elementos, recorra y filtre los que no se cierran automáticamente y opere sobre ellos.

Estoy seguro de que ya sabes que no deberías usar expresiones regulares para este propósito.


</s*(/w+)[^/>]*>

Las partes explicadas:

< : personaje inicial

/s* : puede tener espacios en blanco antes del nombre de la etiqueta (feo pero posible).

(/w+): las etiquetas pueden contener letras y números (h1). Bueno, /wtambién coincide con ''_'', pero no duele, supongo. Si es curioso usarlo ([a-zA-Z0-9] +) en su lugar.

[^/>]*: cualquier cosa excepto >y /hasta el cierre.>

> : clausura >

NO RELACIONADO

Y para aquellos que subestiman las expresiones regulares diciendo que solo son tan poderosos como los lenguajes regulares:

A n ba n ba n que no es regular y ni siquiera está libre de contexto, puede combinarse con^(a+)b/1b/1$

Backreferencing FTW !