2012-01-26 16 views
19

Estoy raspando valores de páginas HTML usando XPath dentro de un programa java para obtener una etiqueta específica y ocasionalmente uso de expresiones regulares para limpiar los datos que recibo.Usando XPath Contiene contra HTML en Java

Después de algunas investigaciones, llegué a HTML Cleaner (http://htmlcleaner.sourceforge.net/) como la forma más confiable de analizar HTML sin procesar en un buen formato XML. HTML Cleaner, sin embargo, solo es compatible con XPath 1.0 y me parece que necesito funciones como 'contiene'. por ejemplo, en este pedazo de XML:

<div> 
    <td id='1234 foo 5678'>Hello</td> 
</div> 

Me gustaría ser capaz de obtener el texto 'Hola' con la siguiente XPath:

//div/td[contains(@id, 'foo')]/text() 

¿Hay alguna manera de conseguir esta funcionalidad? Tengo varias ideas, pero preferiría no reinventar la rueda si yo no necesito:

  • Si hay una manera de llamar evaluateXPath de Limpiador HTML y devolver un TagNode (que no he encontrado), I puede usar un serializador XML en el TagNode devuelto y encadenar XPaths para lograr la funcionalidad deseada.
  • Podría usar HTML Cleaner para limpiar XML, serializarlo de nuevo en una cadena y usarlo con otra biblioteca XPath, pero no puedo encontrar un buen evaluador Javaath que funcione en una cadena.
  • Uso de las funciones TagNode como getElementsByAttValue, pude recrear esencialmente evaluación XPath e insertar en el contiene funcionalidad utilizando String.contains

pregunta corta: ¿Hay alguna manera de utilizar XPath contiene el HTML dentro de una biblioteca existente de Java?

+0

'contiene 'está en XPath 1.0: http://www.w3.org/TR/xpath/#function-contains –

+1

Debería haber sido más sp ecific- HTML cleaner utiliza un subconjunto de XPath 1.0 que no permite contener. –

+0

Mi opinión es que los desarrolladores de HTMLCleaner perdieron mucho tiempo escribiendo una implementación de XPath completamente innecesaria (y no conforme). No hay razón para usarlo alguna vez. Ver mi respuesta para un ejemplo completo. –

Respuesta

31

En cuanto a esto:

podía usar limpiador para limpiar HTML a XML, serializarlo de nuevo a una cadena , y usar eso con otra biblioteca de XPath, pero no puedo encontrar un buen java XPath evaluador que trabaja en una cadena.

Esto es exactamente lo que haría (excepto que no es necesario para operar en una cadena (ver más abajo)).

Muchos analizadores HTML intentan hacer demasiado. HTMLCleaner, por ejemplo, no implementa correctamente/completamente la especificación XPath 1.0 (contains (por ejemplo) esan XPath 1.0 function). La buena noticia es que no lo necesita. Todo lo que necesita de HTMLCleaner es que analice la información mal formada. Una vez que haya hecho eso, es mejor que utilice las interfaces XML estándar para tratar el documento resultante (ahora bien formado).

Primero convertir el documento en un estándar org.w3c.dom.Document así:

TagNode tagNode = new HtmlCleaner().clean(
     "<div><table><td id='1234 foo 5678'>Hello</td>"); 
org.w3c.dom.Document doc = new DomSerializer(
     new CleanerProperties()).createDOM(tagNode); 

Y a continuación, utilizar las interfaces JAXP estándar para consultarlo:

XPath xpath = XPathFactory.newInstance().newXPath(); 
String str = (String) xpath.evaluate("//div//td[contains(@id, 'foo')]/text()", 
         doc, XPathConstants.STRING); 
System.out.println(str); 

Salida:

Hello 
+0

Eso realmente funciona. Lamentablemente, no hay ningún repositorio para HtmlCleaner, pero el archivo está aquí: https://sourceforge.net/projects/htmlcleaner/?source=typ_redirect – Marc

+0

It (HtmlCleaner) está en maven central. https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22net.sourceforge.htmlcleaner%22%20AND%20a%3A%22htmlcleaner%22 –

Cuestiones relacionadas