Estaba respondiendo algunas preguntas de prueba para una entrevista, y la pregunta era acerca de cómo iba a hacer raspado de pantalla. Es decir, seleccionando contenido de una página web, suponiendo que no tienes una mejor manera estructurada de consultar la información directamente (por ejemplo, un servicio web).Raspado de pantalla: expresiones regulares o expresiones XQuery?
Mi solución fue utilizar una expresión XQuery. La expresión fue bastante larga porque el contenido que necesitaba era bastante profundo en la jerarquía de HTML. Tuve que buscar a través de los antepasados de una manera justa antes de encontrar un elemento con un atributo id
. Por ejemplo, raspando una página de Amazon.com para Dimensiones del producto se ve así:
//a[@id="productDetails"]
/following-sibling::table
//h2[contains(child::text(), "Product Details")]
/following-sibling::div
//li
/b[contains(child::text(), "Product Dimensions:")]
/following-sibling::text()
Esa es una expresión bastante desagradable, pero es por eso Amazon proporciona una API de servicios web. De todos modos, es solo un ejemplo. La pregunta no era sobre Amazon, sino sobre el raspado de la pantalla.
Al entrevistador no le gustó mi solución. Pensó que era frágil, porque un cambio en el diseño de la página de Amazon podría requerir la reescritura de la expresión XQuery. La depuración de una expresión de XQuery que no coincide con nada en la página en la que se aplica es difícil.
No estoy en desacuerdo con sus declaraciones, pero no creo que su solución haya sido una mejora: pensó que es mejor usar una expresión regular , y buscar contenido y etiquetas cerca del peso de envío. Por ejemplo, usando Perl:
$html =~ m{<li>\s*<b>\s*Product Dimensions:\s*</b>\s*(.*?)</li>}s;
Mi argumento en contra es que esto también es susceptible a Amazon cambiar su código HTML. Podrían deletrear etiquetas HTML en mayúsculas (<LI>
), o agregar atributos CSS o cambiar <b>
a <span>
o cambiar la etiqueta "Dimensiones del producto:" a "Dimensiones:" o muchos otros tipos de cambios. Mi punto era que las expresiones regulares no resuelven las debilidades que llamó en mi solución XQuery.
Pero, además, las expresiones regulares pueden encontrar falsos positivos, a menos que agregue suficiente contexto a la expresión. También puede hacer coincidir involuntariamente contenido que esté dentro de un comentario, o una cadena de atributo, o una sección CDATA.
Mi pregunta es, ¿qué tecnología utilizas para raspar la pantalla? ¿Por qué elegiste esa solución? ¿Hay alguna razón convincente para usar uno? ¿O nunca usas el otro? ¿Hay una tercera opción además de las que mostré arriba?
PD: Supongamos por el argumento que no existe una API de servicio web u otra forma más directa de adquirir el contenido deseado.
Esta es la razón principal para evitar el raspado web basado en XML. Ningún procesador XML es tan indulgente como un navegador. La página solo necesita romper una regla de buena formación para que XQuery sea completamente inútil. – harpo