2009-03-24 13 views
14

¿Alguien puede decirme una forma simple de encontrar las etiquetas href y src en un archivo html usando expresiones regulares en Java?
Y luego, ¿cómo obtengo la URL asociada con la etiqueta?¿Cómo usar expresiones regulares para analizar HTML en Java?

Gracias por cualquier sugerencia.

+0

cuestión canónica: * [etiquetas de apertura de los partidos, excepto RegEx etiquetas auto-contenida XHTML] (http://stackoverflow.com/questions/1732348/) * Depende de –

Respuesta

53

Usar expresiones regulares para extraer valores de HTML siempre es un error. La sintaxis HTML es mucho más compleja de lo que parece en primer lugar y es muy fácil para una página atrapar incluso una expresión regular muy compleja.

Use un HTML Parser en su lugar. Ver también What are the pros and cons of the leading Java HTML parsers?

+3

qué estás haciendo. Si está procesando una gran cantidad de HTML de fuentes aleatorias, un analizador HTML puede fallar en algunos de ellos y probablemente requerirá más memoria y procesamiento que una expresión regular. Por ejemplo, el rastreador web Heritrix utiliza expresiones regulares para la extracción de enlaces en páginas HTML. – Kris

+0

La solución depende de la pregunta ... – ReneS

+1

Primero responda la pregunta original y luego sugiera cómo optimizarla. Muchas personas visitan esta pregunta en SO con la esperanza de aprender a analizar HTML utilizando expresiones regulares, pero en su lugar encontrar algo que no estaban buscando. El uso de expresiones regulares es rápido y sucio y no es necesario descargar una biblioteca por separado para que funcione. –

3

He buscado en la expresión regular Biblioteca (http://regexlib.com/Search.aspx?k=href y http://regexlib.com/Search.aspx?k=src)

Lo mejor que encontré fue

((?<html>(href|src)\s*=\s*")|(?<css>url\())(?<url>.*?)(?(html)"|\)) 

visita estos links para más expresiones:

http://regexlib.com/REDetails.aspx?regexp_id=2261

http://regexlib.com/REDetails.aspx?regexp_id=758

http://regexlib.com/REDetails.aspx?regexp_id=774

http://regexlib.com/REDetails.aspx?regexp_id=1437

+2

Odio ese sitio. Veo que todavía no se molestan en mencionar a qué sabor se dirige una expresión dada. Esta expresión regular (id = 2261) usa capturas con nombre y condicionales, ninguno de los cuales es compatible con Java. –

5

Si quiere seguir el camino de análisis de HTML, que Dave y yo recomiendo que aquí está el código para analizar una cadena de datos de etiquetas de anclaje e imprimir su href.

dado que solo usa etiquetas de anclaje, debería estar bien solo con expresiones regulares, pero si quiere hacer más, vaya con un analizador. El Mozilla HTML Parser es el mejor que hay.

File parserLibraryFile = new File("lib/MozillaHtmlParser/native/bin/MozillaParser" + EnviromentController.getSharedLibraryExtension()); 
       String parserLibrary = parserLibraryFile.getAbsolutePath(); 
       // mozilla.dist.bin directory : 
       final File mozillaDistBinDirectory = new File("lib/MozillaHtmlParser/mozilla.dist.bin."+ EnviromentController.getOperatingSystemName()); 

     MozillaParser.init(parserLibrary,mozillaDistBinDirectory.getAbsolutePath()); 
MozillaParser parser = new MozillaParser(); 
Document domDocument = parser.parse(data); 
NodeList list = domDocument.getElementsByTagName("a"); 

for (int i = 0; i < list.getLength(); i++) { 
    Node n = list.item(i); 
    NamedNodeMap m = n.getAttributes(); 
    if (m != null) { 
     Node attrNode = m.getNamedItem("href"); 
     if (attrNode != null) 
      System.out.println(attrNode.getNodeValue()); 
7

no utiliza expresiones regulares utilizan NekoHTML o TagSoup que son un puente que proporciona una SAX o DOM como en el enfoque de XML para visitar a un documento HTML.

20

Las otras respuestas son ciertas. Java Regex API no es una herramienta adecuada para lograr su objetivo. Use herramientas de alto nivel eficientes, seguras y bien probadas mencionadas en las otras respuestas.

Si su pregunta se refiere más bien API expresión regular que un problema de la vida real (propósitos, por ejemplo, el aprendizaje) - que puede hacer con el siguiente código:

String html = "foo <a href='link1'>bar</a> baz <a href='link2'>qux</a> foo"; 
Pattern p = Pattern.compile("<a href='(.*?)'>"); 
Matcher m = p.matcher(html); 
while(m.find()) { 
    System.out.println(m.group(0)); 
    System.out.println(m.group(1)); 
} 

y la salida es:

<a href='link1'> 
link1 
<a href='link2'> 
link2 

Tenga en cuenta que calificador perezoso/reacio *? debe usarse para reducir la agrupación a la etiqueta única. El grupo 0 es el partido completo, el grupo 1 es el siguiente partido del grupo (el siguiente par de paréntesis).

+0

Gracias. Si bien no es una expresión regular "works-everywhere", esto funciona para los datos devueltos por las últimas tendencias de google y he estado tirando de mi cabello para analizarlo durante mucho tiempo ... – rjha94

1

Las expresiones regulares solo pueden analizar los idiomas regulares, por eso se llaman expresiones regulares. HTML no es un lenguaje normal, ergo no puede ser analizado por expresiones regulares.

analizadores de HTML, por otro lado, puede analizar HTML, es por eso que se llaman analizadores de HTML.

En su lugar, debe usar su analizador HTML favorito.

1

Contrariamente a la opinión popular, las expresiones regulares son herramientas útiles para extraer datos de texto no estructurado (que es HTML).

Si está realizando una extracción de datos HTML compleja (por ejemplo, busca todos los párrafos en una página), entonces el análisis de HTML probablemente sea el camino a seguir. Pero si solo necesita obtener algunas URL de HREF, una expresión regular funcionaría bien y sería muy difícil romperla.

intentar algo como esto:

/<a[^>]+href=["']?([^'"> ]+)["']?[^>]*>/i 
Cuestiones relacionadas