¿Cómo analiza y procesa HTML / XML en PHP?

Respuestas:

1897

Extensiones XML nativas

Prefiero usar una de las extensiones XML nativas, ya que vienen con PHP, generalmente son más rápidas que todas las librerías de terceros y me dan todo el control que necesito sobre el marcado.

DOM

La extensión DOM le permite operar en documentos XML a través de la API DOM con PHP 5. Es una implementación del Modelo de Objetos del Documento Núcleo Nivel 3 del W3C, una interfaz de plataforma y lenguaje neutral que permite que los programas y los scripts accedan y actualicen dinámicamente El contenido, estructura y estilo de los documentos.

DOM es capaz de analizar y modificar HTML del mundo real (roto) y puede hacer consultas XPath . Está basado en libxml .

Lleva algún tiempo ser productivo con DOM, pero ese tiempo vale la pena en mi opinión. Dado que DOM es una interfaz independiente del idioma, encontrará implementaciones en muchos idiomas, por lo que si necesita cambiar su lenguaje de programación, es probable que ya sepa cómo usar la API DOM de ese idioma.

Un ejemplo de uso básico se puede encontrar en Agarrando el atributo href de un elemento A y se puede encontrar una descripción conceptual general en DOMDocument en php

El uso de la extensión DOM se ha cubierto ampliamente en StackOverflow , por lo que si elige usarlo, puede estar seguro de que la mayoría de los problemas con los que se encuentra pueden resolverse buscando / explorando Stack Overflow.

XMLReader

La extensión XMLReader es un analizador de extracción XML. El lector actúa como un cursor que avanza en la secuencia de documentos y se detiene en cada nodo en el camino.

XMLReader, como DOM, se basa en libxml. No sé cómo activar el módulo analizador de HTML, por lo que es probable que el uso de XMLReader para analizar HTML roto sea menos robusto que el uso de DOM, donde puede decirle explícitamente que use el módulo analizador HTML de libxml.

Un ejemplo de uso básico se puede encontrar en obtener todos los valores de etiquetas h1 usando php

Analizador XML

Esta extensión le permite crear analizadores XML y luego definir controladores para diferentes eventos XML. Cada analizador XML también tiene algunos parámetros que puede ajustar.

La biblioteca XML Parser también se basa en libxml e implementa un SAX analizador push XML de estilo . Puede ser una mejor opción para la administración de memoria que DOM o SimpleXML, pero será más difícil de trabajar que el analizador de extracción implementado por XMLReader.

SimpleXml

La extensión SimpleXML proporciona un conjunto de herramientas muy simple y fácil de usar para convertir XML en un objeto que puede procesarse con selectores de propiedades normales e iteradores de matriz.

SimpleXML es una opción cuando sabes que el HTML es XHTML válido. Si necesita analizar HTML roto, ni siquiera considere SimpleXml porque se ahogará.

Puede encontrar un ejemplo de uso básico en Un programa simple para CRUD nodo y valores de nodo del archivo xml y hay muchos ejemplos adicionales en el Manual de PHP .


Bibliotecas de terceros (basadas en libxml)

Si prefiere usar una biblioteca de terceros, le sugiero que use una biblioteca que realmente use DOM / libxml debajo en lugar del análisis de cadenas.

FluentDom - Repo

FluentDOM proporciona una interfaz XML fluida similar a jQuery para DOMDocument en PHP. Los selectores están escritos en XPath o CSS (usando un convertidor CSS a XPath). Las versiones actuales amplían el DOM implementando interfaces estándar y agregan características del DOM Living Standard. FluentDOM puede cargar formatos como JSON, CSV, JsonML, RabbitFish y otros. Se puede instalar a través de Composer.

HtmlPageDom

Wa72 \ HtmlPageDom` es una biblioteca PHP para una fácil manipulación de documentos HTML usando Requiere DomCrawler de los componentes de Symfony2 para atravesar el árbol DOM y lo extiende agregando métodos para manipular el árbol DOM de documentos HTML.

phpQuery (no actualizado por años)

phpQuery es una API del Modelo de Objetos de Documento (DOM) dirigida por el selector CSS3 del lado del servidor, basada en la Biblioteca JavaScript jQuery escrita en PHP5 y proporciona una Interfaz de Línea de Comando (CLI) adicional.

Ver también: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom proporciona herramientas para trabajar con documentos y estructuras DOM. Actualmente, ofrecemos Zend_Dom_Query, que proporciona una interfaz unificada para consultar documentos DOM utilizando selectores XPath y CSS.

QueryPath

QueryPath es una biblioteca PHP para manipular XML y HTML. Está diseñado para trabajar no solo con archivos locales, sino también con servicios web y recursos de bases de datos. Implementa gran parte de la interfaz jQuery (incluidos los selectores de estilo CSS), pero está muy optimizada para el uso del lado del servidor. Se puede instalar a través de Composer.

fDOMDocument

fDOMDocument extiende el DOM estándar para usar excepciones en todas las ocasiones de errores en lugar de advertencias o avisos de PHP. También agregan varios métodos personalizados y accesos directos para mayor comodidad y para simplificar el uso de DOM.

sable / xml

saber / xml es una biblioteca que envuelve y extiende las clases XMLReader y XMLWriter para crear un sistema de mapeo y un patrón de diseño "xml to object / array" simple. Escribir y leer XML es de una sola pasada y, por lo tanto, puede ser rápido y requerir poca memoria en archivos xml grandes.

FluidXML

FluidXML es una biblioteca PHP para manipular XML con una API concisa y fluida. Aprovecha XPath y el patrón de programación fluido para ser divertido y efectivo.


Terceros (no basados ​​en libxml)

El beneficio de construir sobre DOM / libxml es que obtienes un buen rendimiento fuera de la caja porque estás basado en una extensión nativa. Sin embargo, no todas las librerías de terceros siguen esta ruta. Algunos de ellos se enumeran a continuación.

PHP Simple HTML DOM Parser

  • ¡Un analizador HTML DOM escrito en PHP5 + le permite manipular HTML de una manera muy fácil!
  • Requiere PHP 5+.
  • Soporta HTML inválido.
  • Busque etiquetas en una página HTML con selectores como jQuery.
  • Extraer contenidos de HTML en una sola línea.

Generalmente no recomiendo este analizador. El código base es horrible y el analizador en sí es bastante lento y requiere mucha memoria. No todos los selectores jQuery (como los selectores secundarios ) son posibles. Cualquiera de las bibliotecas basadas en libxml debería superar esto fácilmente.

PHP Html Parser

PHPHtmlParser es un analizador html simple, flexible que le permite seleccionar etiquetas usando cualquier selector css, como jQuery. El objetivo es ayudar en el desarrollo de herramientas que requieren una forma rápida y fácil de desechar html, ¡ya sea válido o no! Este proyecto fue originalmente respaldado por sunra / php-simple-html-dom-parser pero el soporte parece haberse detenido, por lo que este proyecto es mi adaptación de su trabajo anterior.

Nuevamente, no recomendaría este analizador. Es bastante lento con un alto uso de CPU. Tampoco hay una función para borrar la memoria de los objetos DOM creados. Estos problemas escalan particularmente con bucles anidados. La documentación en sí es inexacta y está mal escrita, sin respuestas a las correcciones desde el 14 de abril de 16.

Ganon

  • Un tokenizador universal y un analizador de DOM HTML / XML / RSS
    • Capacidad para manipular elementos y sus atributos.
    • Admite HTML y UTF8 no válidos
  • Puede realizar consultas avanzadas de tipo CSS3 en elementos (como jQuery - se admiten espacios de nombres)
  • Un embellecedor HTML (como HTML Tidy)
    • Minificar CSS y Javascript
    • Ordenar atributos, cambiar mayúsculas y minúsculas, corregir sangría, etc.
  • Extensible
    • Análisis de documentos mediante devoluciones de llamada basadas en el carácter / token actual
    • Operaciones separadas en funciones más pequeñas para anular fácilmente
  • Rapido y facil

Nunca lo usé. No puedo decir si es bueno.


HTML 5

Puede usar lo anterior para analizar HTML5, pero puede haber peculiaridades debido al marcado que permite HTML5. Entonces, para HTML5, debe considerar usar un analizador dedicado, como

html5lib

Implementaciones de Python y PHP de un analizador HTML basado en la especificación HTML5 WHATWG para una máxima compatibilidad con los principales navegadores web de escritorio.

Es posible que veamos analizadores más dedicados una vez que se finalice HTML5. También hay una publicación en el blog de W3 titulada How-To para el análisis html 5 que vale la pena echarle un vistazo.


Servicios web

Si no tiene ganas de programar PHP, también puede usar los servicios web. En general, encontré muy poca utilidad para estos, pero solo somos yo y mis casos de uso.

ScraperWiki .

La interfaz externa de ScraperWiki le permite extraer datos en la forma que desee para usar en la web o en sus propias aplicaciones. También puede extraer información sobre el estado de cualquier raspador.


Expresiones regulares

Por último y menos recomendado , puede extraer datos de HTML con expresiones regulares . En general, se desaconseja el uso de expresiones regulares en HTML.

La mayoría de los fragmentos que encontrará en la web para que coincidan con el marcado son frágiles. En la mayoría de los casos, solo funcionan para una pieza de HTML muy particular. Pequeños cambios de marcado, como agregar espacios en blanco en alguna parte, o agregar o cambiar atributos en una etiqueta, pueden hacer que el RegEx falle cuando no se escribe correctamente. Debe saber lo que está haciendo antes de usar RegEx en HTML.

Los analizadores HTML ya conocen las reglas sintácticas de HTML. Deben enseñarse expresiones regulares para cada nuevo RegEx que escriba. RegEx está bien en algunos casos, pero realmente depende de su caso de uso.

Puede escribir analizadores más confiables , pero escribir un completo y confiable analizador personalizado con expresiones regulares es una pérdida de tiempo cuando las bibliotecas mencionadas ya existen y hacen un trabajo mucho mejor en esto.

Ver también Parsing Html The Cthulhu Way


Libros

Si quieres gastar algo de dinero, mira

No estoy afiliado con PHP Architect ni con los autores.

Gordon
fuente
10
@Naveed que depende de tus necesidades. No necesito consultas CSS Selector, por lo que uso DOM con XPath exclusivamente. phpQuery pretende ser un puerto jQuery. Zend_Dom es ligero. Realmente tienes que verlos para ver cuál te gusta más.
Gordon
2
@ Ms2ger Principalmente, pero no completamente. Como ya se señaló anteriormente, puede usar los analizadores basados ​​en libxml, pero hay casos especiales en los que se ahogarán. Si necesita la máxima compatibilidad, es mejor que tenga un analizador dedicado. Prefiero mantener la distinción.
Gordon
99
Su punto para no usar PHP Simple HTML DOM Parser parece discutible.
Petah
3
A partir del 29 de marzo de 2012, DOM no es compatible con html5, XMLReader no es compatible con HTML y la última confirmación en html5lib para PHP es en septiembre de 2009. ¿Qué usar para analizar HTML5, HTML4 y XHTML?
Shiplu Mokaddim
44
@Nasha Excluí deliberadamente la infame diatriba de Zalgo de la lista anterior porque no es demasiado útil por sí sola y conduce a un gran culto a la carga desde que fue escrita. La gente fue abofeteada con ese vínculo, sin importar cuán apropiada hubiera sido una expresión regular como solución. Para obtener una opinión más equilibrada, consulte el enlace que incluí
Gordon
322

Prueba Simple HTML DOM Parser

  • ¡Un analizador HTML DOM escrito en PHP 5+ que te permite manipular HTML de una manera muy fácil!
  • Requiere PHP 5+.
  • Soporta HTML inválido.
  • Busque etiquetas en una página HTML con selectores como jQuery.
  • Extraer contenidos de HTML en una sola línea.
  • Descargar


Ejemplos:

Cómo obtener elementos HTML:

// Create DOM from URL or file
$html = file_get_html('http://www.example.com/');

// Find all images
foreach($html->find('img') as $element)
       echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
       echo $element->href . '<br>';


Cómo modificar elementos HTML:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html;


Extraer contenido de HTML:

// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;


Raspar Slashdot:

// Create DOM from URL
$html = file_get_html('http://slashdot.org/');

// Find all article blocks
foreach($html->find('div.article') as $article) {
    $item['title']     = $article->find('div.title', 0)->plaintext;
    $item['intro']    = $article->find('div.intro', 0)->plaintext;
    $item['details'] = $article->find('div.details', 0)->plaintext;
    $articles[] = $item;
}

print_r($articles);
Naveed
fuente
8
Bueno, en primer lugar hay cosas para las que debo prepararme, como DOM incorrectos, código Invlid, también analizando contra el motor DNSBL, esto también se usará para detectar sitios / contenido malicioso, también como he creado mi sitio en torno a un marco que construido debe ser limpio, legible y bien estructurado. SimpleDim es genial, pero el código es un poco desordenado
RobertPitt
99
@Robert también es posible que desee consultar htmlpurifier.org para las cosas relacionadas con la seguridad.
Gordon
3
Tiene un punto válido: simpleHTMLDOM es difícil de extender, a menos que use un patrón de decorador, lo que me parece difícil de manejar. Me he estremecido solo haciendo cambios en las clases subyacentes.
Erik
1
Lo que hice fue ejecutar mi html a través de ordenado antes de enviarlo a SimpleDOM.
MB34
1
Actualmente estoy usando esto, ejecutándolo como parte de un proyecto para procesar unos cientos de URL. Se está volviendo muy lento y persisten los tiempos de espera regulares. Es un gran script para principiantes e intuitivamente simple de aprender, pero demasiado básico para proyectos más avanzados.
luke_mclachlan
236

Simplemente use DOMDocument-> loadHTML () y termine con eso. El algoritmo de análisis HTML de libxml es bastante bueno y rápido, y contrario a la creencia popular, no se ahoga con HTML mal formado.

Edward Z. Yang
fuente
19
Cierto. Y funciona con las clases de XPath y XSLTProcessor integradas de PHP, que son excelentes para extraer contenido.
Kornel
8
Para HTML realmente maltratado, siempre puede ejecutarlo a través de htmltidy antes de pasarlo a DOM. Cada vez que necesito raspar datos de HTML, siempre uso DOM, o al menos simplexml.
Frank Farmer
99
Otra cosa con la carga de HTML con formato incorrecto i es que sería aconsejable llamar a libxml_use_internal_errors (true) para evitar advertencias que detendrán el análisis.
Husky
66
He utilizado DOMDocument para analizar aproximadamente 1000 fuentes html (en varios idiomas codificados con diferentes charsets) sin ningún problema. Puede encontrar problemas de codificación con esto, pero no son insuperables. Necesita saber 3 cosas: 1) loadHTML usa el juego de caracteres de metaetiqueta para determinar la codificación 2) # 2 puede conducir a una detección de codificación incorrecta si el contenido html no incluye esta información 3) los caracteres UTF-8 incorrectos pueden disparar el analizador. En tales casos, use una combinación de mb_detect_encoding () y el código de caracteres UTF-8 de codificación / conversión / eliminación de Simplepie RSS Parser para soluciones alternativas.
Cero
1
DOM realmente admite XPath, eche un vistazo a DOMXPath .
Ryan McCue
147

¿Por qué no deberías y cuándo deberías usar expresiones regulares?

En primer lugar, un nombre inapropiado común: las expresiones regulares no son para " analizar " HTML. Sin embargo, las expresiones regulares pueden " extraer " datos. La extracción es para lo que están hechos. El principal inconveniente de la extracción de expresiones regulares HTML sobre kits de herramientas SGML adecuados o analizadores XML de línea de base es su esfuerzo sintáctico y fiabilidad variable.

Considere que hacer una expresión regular de extracción de HTML algo confiable:

<a\s+class="?playbutton\d?[^>]+id="(\d+)".+?    <a\s+class="[\w\s]*title
[\w\s]*"[^>]+href="(http://[^">]+)"[^>]*>([^<>]+)</a>.+?

es mucho menos legible que un simple phpQuery o QueryPath equivalente:

$div->find(".stationcool a")->attr("title");

Sin embargo, hay casos de uso específicos donde pueden ayudar.

  • Muchas interfaces frontales del DOM no revelan comentarios HTML <!--, que a veces son los anclajes más útiles para la extracción. En particular, las variaciones pseudo-HTML <$var>o los residuos SGML son fáciles de domesticar con expresiones regulares.
  • A menudo, las expresiones regulares pueden guardar el procesamiento posterior. Sin embargo, las entidades HTML a menudo requieren cuidado manual.
  • Y, por último, para tareas extremadamente simples como extraer <img src = urls, de hecho son una herramienta probable. La ventaja de velocidad sobre los analizadores SGML / XML en su mayoría solo juega para estos procedimientos de extracción muy básicos.

A veces incluso es aconsejable extraer previamente un fragmento de HTML utilizando expresiones regulares /<!--CONTENT-->(.+?)<!--END-->/y procesar el resto utilizando las interfaces de analizador de HTML más simples.

Nota: Realmente tengo esta aplicación , donde utilizo el análisis XML y las expresiones regulares alternativamente. La semana pasada, el análisis de PyQuery se rompió y la expresión regular aún funcionó. Sí raro, y no puedo explicarlo yo mismo. Pero así sucedió.
Así que por favor no rechace las consideraciones del mundo real, solo porque no coincide con el meme regex = evil. Pero tampoco votemos demasiado por esto. Es solo una nota al margen de este tema.

Mario
fuente
20
DOMCommentpuede leer comentarios, así que no hay razón para usar Regex para eso.
Gordon
44
Ni los kits de herramientas SGML ni los analizadores XML son adecuados para analizar HTML del mundo real. Para eso, solo un analizador HTML dedicado es apropiado.
Alohci
12
@Alohci DOMusa libxml y libxml tiene un módulo analizador de HTML separado que se usará al cargar HTML, por loadHTML()lo que puede cargar mucho HTML "del mundo real" (lectura rota).
Gordon
66
Bueno, solo un comentario sobre su punto de vista de "consideración del mundo real". Claro, hay situaciones útiles para Regex al analizar HTML. Y también hay situaciones útiles para usar GOTO. Y hay situaciones útiles para variables variables. Por lo tanto, ninguna implementación particular es definitivamente code-rot para usarlo. Pero es una señal de advertencia MUY fuerte. Y es probable que el desarrollador promedio no sea lo suficientemente matizado como para notar la diferencia. Entonces, como regla general, Regex GOTO y Variable-Variables son todas malvadas. Hay usos no malvados, pero esas son las excepciones (y raro en eso) ... (En mi humilde opinión)
ircmaxell
11
@mario: En realidad, el HTML se puede analizar "correctamente" usando expresiones regulares, aunque generalmente se necesitan varios para hacer un trabajo justo por tit. Es solo un dolor real en el caso general. En casos específicos con entradas bien definidas, raya en trivial. Esos son los casos en los que las personas deberían usar expresiones regulares. Los analizadores viejos, grandes y hambrientos son realmente lo que necesita para casos generales, aunque no siempre está claro para el usuario casual dónde dibujar esa línea. Cualquiera que sea el código más simple y fácil, gana.
tchrist
131

phpQuery y QueryPath son extremadamente similares en la replicación de la fluida API jQuery. Por eso también son dos de los más fáciles enfoques para adecuadamente analizar HTML en PHP.

Ejemplos para QueryPath

Básicamente, primero crea un árbol DOM consultable desde una cadena HTML:

 $qp = qp("<html><body><h1>title</h1>..."); // or give filename or URL

El objeto resultante contiene una representación de árbol completa del documento HTML. Se puede recorrer utilizando métodos DOM. Pero el enfoque común es usar selectores CSS como en jQuery:

 $qp->find("div.classname")->children()->...;

 foreach ($qp->find("p img") as $img) {
     print qp($img)->attr("src");
 }

Sobre todo usted desea utilizar simples #idy .classo DIVetiqueta de selectores->find() . Pero también puede usar declaraciones XPath , que a veces son más rápidas. También los métodos típicos de jQuery, como ->children()y, en ->text()particular, ->attr()simplifican la extracción de los fragmentos HTML correctos. (Y ya tienen sus entidades SGML decodificadas).

 $qp->xpath("//div/p[1]");  // get first paragraph in a div

QueryPath también permite inyectar nuevas etiquetas en la secuencia ( ->append), y luego generar y prettificar un documento actualizado ( ->writeHTML). No solo puede analizar HTML con formato incorrecto, sino también varios dialectos XML (con espacios de nombres) e incluso extraer datos de microformatos HTML (XFN, vCard).

 $qp->find("a[target=_blank]")->toggleClass("usability-blunder");

.

phpQuery o QueryPath?

En general, QueryPath es más adecuado para la manipulación de documentos. Mientras que phpQuery también implementa algunos métodos pseudo AJAX (solo solicitudes HTTP) para parecerse más a jQuery. Se dice que phpQuery es a menudo más rápido que QueryPath (debido a la menor cantidad de funciones generales).

Para más información sobre las diferencias ver esta comparación en la máquina wayback de tagbyte.org . (La fuente original desapareció, así que aquí hay un enlace a un archivo de Internet. Sí, todavía puede localizar páginas faltantes, personas).

Y aqui esta una introducción completa a QueryPath .

Ventajas

  • Simplicidad y confiabilidad
  • Alternativas simples de usar ->find("a img, a object, div a")
  • Unescaping de datos adecuado (en comparación con el grepping de expresiones regulares)
Mario
fuente
88

Simple HTML DOM es un excelente analizador de código abierto:

simplehtmldom.sourceforge

Trata los elementos DOM de una manera orientada a objetos, y la nueva iteración tiene mucha cobertura para el código no compatible. También hay algunas funciones excelentes como las que verías en JavaScript, como la función "buscar", que devolverá todas las instancias de elementos de ese nombre de etiqueta.

Lo he usado en varias herramientas, probándolo en muchos tipos diferentes de páginas web, y creo que funciona muy bien.

Robert Elwell
fuente
61

Un enfoque general que no he visto mencionado aquí es ejecutar HTML a través de Tidy , que se puede configurar para escupir XHTML válido garantizado. Entonces puede usar cualquier biblioteca XML anterior en él.

Pero para su problema específico, debería echar un vistazo a este proyecto: http://fivefilters.org/content-only/ : es una versión modificada del algoritmo de legibilidad , que está diseñado para extraer solo el contenido textual (no los encabezados) y pies de página) de una página.

Eli
fuente
56

Para 1a y 2: votaría por la nueva clase de Componente Symfony DOMCrawler ( DomCrawler ). Esta clase permite consultas similares a los selectores CSS. Eche un vistazo a esta presentación para ver ejemplos del mundo real: news-of-the-symfony2-world .

El componente está diseñado para funcionar de manera independiente y puede usarse sin Symfony.

El único inconveniente es que solo funcionará con PHP 5.3 o posterior.

Timo
fuente
Las consultas CSS jquery-like se dicen bien, porque hay algunas cosas que faltan en la documentación de w3c, pero están presentes como características adicionales en jquery.
Nikola Petkanski
53

Esto se conoce comúnmente como raspado de pantalla , por cierto. La biblioteca que he usado para esto es Simple HTML Dom Parser .

Joel Verhagen
fuente
8
No es estrictamente cierto ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ). La pista está en "pantalla"; en el caso descrito, no hay pantalla involucrada. Aunque, es cierto, el término ha sufrido una gran cantidad de mal uso reciente.
Bobby Jack el
44
No estoy raspando la pantalla, el contenido que será analizado será autorizado por el proveedor de contenido bajo mi acuerdo.
RobertPitt
41

Hemos creado bastantes rastreadores para nuestras necesidades antes. Al final del día, generalmente son expresiones regulares simples las que hacen lo mejor. Si bien las bibliotecas enumeradas anteriormente son buenas por la razón por la que se crearon, si sabe lo que está buscando, las expresiones regulares son una forma más segura de hacerlo, ya que también puede manejar estructuras HTML / XHTML no válidas , que fallarían si se cargaran a través de la mayoría de los analizadores.

jancha
fuente
38

Recomiendo PHP Simple HTML DOM Parser .

Realmente tiene buenas características, como:

foreach($html->find('img') as $element)
       echo $element->src . '<br>';
Greg
fuente
36

Esto suena como una buena descripción de la tarea de la tecnología W3C XPath . Es fácil expresar consultas como "devolver todos los hrefatributos en las imgetiquetas que están anidadas <foo><bar><baz> elements". Al no ser un fanático de PHP, no puedo decirte en qué forma XPath puede estar disponible. Si puede llamar a un programa externo para procesar el archivo HTML, debería poder usar una versión de línea de comandos de XPath. Para una introducción rápida, consulte http://en.wikipedia.org/wiki/XPath .

Jens
fuente
24

Sí, puede usar simple_html_dom para este propósito. Sin embargo, he trabajado bastante con simple_html_dom, particularmente para el desguace web y he encontrado que es demasiado vulnerable. Hace el trabajo básico pero no lo recomendaré de todos modos.

Nunca he usado curl para este propósito, pero lo que he aprendido es que curl puede hacer el trabajo de manera mucho más eficiente y es mucho más sólido.

Echa un vistazo a este enlace: scraping-websites-with-curl

Rafay
fuente
2
curl puede obtener el archivo, pero no analizará HTML por usted. Esa es la parte difícil.
cHao
23

QueryPath es bueno, pero tenga cuidado con el "estado de seguimiento" porque si no se da cuenta de lo que significa, puede significar que pierda mucho tiempo de depuración tratando de averiguar qué sucedió y por qué el código no funciona.

Lo que significa es que cada llamada en el conjunto de resultados modifica el conjunto de resultados en el objeto, no es encadenable como en jquery donde cada enlace es un conjunto nuevo, tiene un conjunto único que son los resultados de su consulta y cada llamada de función se modifica Ese conjunto único.

Para obtener un comportamiento similar a jquery, debe bifurcarse antes de hacer una operación de filtro / modificación similar, lo que significa que reflejará lo que sucede en jquery mucho más de cerca.

$results = qp("div p");
$forename = $results->find("input[name='forename']");

$resultsahora contiene el conjunto de resultados para input[name='forename']NO la consulta original, "div p"esto me hizo tropezar mucho, lo que encontré fue que QueryPath rastrea los filtros y encuentra y todo lo que modifica sus resultados y los almacena en el objeto. necesitas hacer esto en su lugar

$forename = $results->branch()->find("input[name='forname']")

entonces $resultsno se modificará y puede reutilizar el conjunto de resultados una y otra vez, tal vez alguien con mucho más conocimiento pueda aclarar esto un poco, pero básicamente es así por lo que he encontrado.

Christopher Thomas
fuente
20

Advanced Html Dom es un simple reemplazo de HTML DOM que ofrece la misma interfaz, pero está basado en DOM, lo que significa que no ocurre ninguno de los problemas de memoria asociados.

También tiene soporte completo de CSS, incluidas las extensiones jQuery .

pguardiario
fuente
Obtuve buenos resultados de Advanced Html Dom, y creo que debería estar en la lista de la respuesta aceptada. Sin embargo, es importante saberlo para cualquiera que confíe en su "El objetivo de este proyecto es ser un reemplazo directo basado en DOM para la simple biblioteca html dom de PHP ... Si usa file / str_get_html, entonces no necesita Cambia cualquier cosa." archive.is/QtSuj#selection-933.34-933.100 es que es posible que deba realizar cambios en su código para acomodar algunas incompatibilidades. He notado cuatro conocidos por mí en los problemas de github del proyecto. github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ
Trabajó ! Gracias
Faisal Shani
18

Para HTML5 , html5 lib ha sido abandonada por años. La única biblioteca HTML5 que puedo encontrar con una actualización reciente y registros de mantenimiento es html5-php, que se acaba de llevar a beta 1.0 hace poco más de una semana.

Reid Johnson
fuente
17

He escrito un analizador XML de propósito general que puede manejar fácilmente archivos GB. Está basado en XMLReader y es muy fácil de usar:

$source = new XmlExtractor("path/to/tag", "/path/to/file.xml");
foreach ($source as $tag) {
    echo $tag->field1;
    echo $tag->field2->subfield1;
}

Aquí está el repositorio de github : XmlExtractor

Paul Warelis
fuente
17

Creé una biblioteca llamada PHPPowertools / DOM-Query , que le permite rastrear documentos HTML5 y XML tal como lo hace con jQuery.

Bajo el capó, utiliza Symfony / DomCrawler para la conversión de selectores CSS a selectores XPath . Siempre usa el mismo DomDocument, incluso cuando pasa un objeto a otro, para garantizar un rendimiento decente.


Ejemplo de uso:

namespace PowerTools;

// Get file content
$htmlcode = file_get_contents('https://github.com');

// Define your DOMCrawler based on file string
$H = new DOM_Query($htmlcode);

// Define your DOMCrawler based on an existing DOM_Query instance
$H = new DOM_Query($H->select('body'));

// Passing a string (CSS selector)
$s = $H->select('div.foo');

// Passing an element object (DOM Element)
$s = $H->select($documentBody);

// Passing a DOM Query object
$s = $H->select( $H->select('p + p'));

// Select the body tag
$body = $H->select('body');

// Combine different classes as one selector to get all site blocks
$siteblocks = $body->select('.site-header, .masthead, .site-body, .site-footer');

// Nest your methods just like you would with jQuery
$siteblocks->select('button')->add('span')->addClass('icon icon-printer');

// Use a lambda function to set the text of all site blocks
$siteblocks->text(function( $i, $val) {
    return $i . " - " . $val->attr('class');
});

// Append the following HTML to all site blocks
$siteblocks->append('<div class="site-center"></div>');

// Use a descendant selector to select the site's footer
$sitefooter = $body->select('.site-footer > .site-center');

// Set some attributes for the site's footer
$sitefooter->attr(array('id' => 'aweeesome', 'data-val' => 'see'));

// Use a lambda function to set the attributes of all site blocks
$siteblocks->attr('data-val', function( $i, $val) {
    return $i . " - " . $val->attr('class') . " - photo by Kelly Clark";
});

// Select the parent of the site's footer
$sitefooterparent = $sitefooter->parent();

// Remove the class of all i-tags within the site's footer's parent
$sitefooterparent->select('i')->removeAttr('class');

// Wrap the site's footer within two nex selectors
$sitefooter->wrap('<section><div class="footer-wrapper"></div></section>');

[...]

Métodos soportados:


  1. Renombrado 'select', por razones obvias
  2. Renombrado 'vacío', ya que 'vacío' es una palabra reservada en PHP

NOTA :

La biblioteca también incluye su propio autocargador de configuración cero para bibliotecas compatibles con PSR-0. El ejemplo incluido debería funcionar de fábrica sin ninguna configuración adicional. Alternativamente, puede usarlo con el compositor.

John Slegers
fuente
Parece la herramienta adecuada para el trabajo, pero no se está cargando para mí en PHP 5.6.23 en Worpress. ¿Alguna instrucción adicional sobre cómo incluirlo correctamente? Incluido con: define ("BASE_PATH", dirname ( FILE )); define ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); requiere LIBRARY_PATH. DIRECTORIO_SEPARADOR. 'Loader.php'; Loader :: init (matriz (LIBRARY_PATH, USER_PATH)); en functions.php
lithiumlab
15

Podría intentar usar algo como HTML Tidy para limpiar cualquier HTML "roto" y convertir el HTML a XHTML, que luego puede analizar con un analizador XML.

CesarB
fuente
15

Otra opción que puedes probar es QueryPath . Está inspirado en jQuery, pero en el servidor en PHP y se usa en Drupal .

Ric
fuente
12

XML_HTMLSaxes bastante estable, incluso si ya no se mantiene. Otra opción podría ser canalizar HTML a través de Html Tidy y luego analizarlo con herramientas XML estándar.

troelskn
fuente
11

El marco de Symfony tiene paquetes que pueden analizar el HTML, y puede usar el estilo CSS para seleccionar los DOM en lugar de usar XPath .

Tuong Le
fuente
11

Hay muchas formas de procesar HTML / XML DOM de las cuales la mayoría ya se han mencionado. Por lo tanto, no haré ningún intento de enumerarlos yo mismo.

Simplemente quiero agregar que personalmente prefiero usar la extensión DOM y por qué:

  • Hace un uso óptimo de la ventaja de rendimiento del código C subyacente
  • es OO PHP (y me permite subclasificarlo)
  • es bastante bajo (lo que me permite usarlo como una base no hinchada para un comportamiento más avanzado)
  • proporciona acceso a cada parte del DOM (a diferencia de, por ejemplo, SimpleXml, que ignora algunas de las características XML menos conocidas)
  • tiene una sintaxis utilizada para el rastreo de DOM que es similar a la sintaxis utilizada en Javascript nativo.

Y aunque echo de menos la capacidad de usar selectores de CSS DOMDocument, hay una manera bastante simple y conveniente de agregar esta característica: subclasificar DOMDocumenty agregar JS-like querySelectorAlly querySelectormétodos a su subclase.

Para analizar los selectores, recomiendo usar el componente CssSelector muy minimalista del marco de Symfony . Este componente solo traduce los selectores CSS a los selectores XPath, que luego se pueden alimentar a un DOMXpathpara recuperar la Nodelist correspondiente.

Luego puede usar esta subclase (todavía de muy bajo nivel) como base para más clases de alto nivel, por ejemplo. analizar tipos muy específicos de XML o agregar más comportamientos similares a jQuery.

El siguiente código viene directamente de mi biblioteca DOM-Query y usa la técnica que describí.

Para el análisis HTML:

namespace PowerTools;

use \Symfony\Component\CssSelector\CssSelector as CssSelector;

class DOM_Document extends \DOMDocument {
    public function __construct($data = false, $doctype = 'html', $encoding = 'UTF-8', $version = '1.0') {
        parent::__construct($version, $encoding);
        if ($doctype && $doctype === 'html') {
            @$this->loadHTML($data);
        } else {
            @$this->loadXML($data);
        }
    }

    public function querySelectorAll($selector, $contextnode = null) {
        if (isset($this->doctype->name) && $this->doctype->name == 'html') {
            CssSelector::enableHtmlExtension();
        } else {
            CssSelector::disableHtmlExtension();
        }
        $xpath = new \DOMXpath($this);
        return $xpath->query(CssSelector::toXPath($selector, 'descendant::'), $contextnode);
    }

    [...]

    public function loadHTMLFile($filename, $options = 0) {
        $this->loadHTML(file_get_contents($filename), $options);
    }

    public function loadHTML($source, $options = 0) {
        if ($source && $source != '') {
            $data = trim($source);
            $html5 = new HTML5(array('targetDocument' => $this, 'disableHtmlNsInDom' => true));
            $data_start = mb_substr($data, 0, 10);
            if (strpos($data_start, '<!DOCTYPE ') === 0 || strpos($data_start, '<html>') === 0) {
                $html5->loadHTML($data);
            } else {
                @$this->loadHTML('<!DOCTYPE html><html><head><meta charset="' . $encoding . '" /></head><body></body></html>');
                $t = $html5->loadHTMLFragment($data);
                $docbody = $this->getElementsByTagName('body')->item(0);
                while ($t->hasChildNodes()) {
                    $docbody->appendChild($t->firstChild);
                }
            }
        }
    }

    [...]
}

Consulte también Análisis de documentos XML con selectores CSS del creador de Symfony Fabien Potencier sobre su decisión de crear el componente CssSelector para Symfony y cómo usarlo.

John Slegers
fuente
9

Con FluidXML puede consultar e iterar XML utilizando XPath y CSS Selectors .

$doc = fluidxml('<html>...</html>');

$title = $doc->query('//head/title')[0]->nodeValue;

$doc->query('//body/p', 'div.active', '#bgId')
        ->each(function($i, $node) {
            // $node is a DOMNode.
            $tag   = $node->nodeName;
            $text  = $node->nodeValue;
            $class = $node->getAttribute('class');
        });

https://github.com/servo-php/fluidxml

Daniele Orlando
fuente
7

JSON y matriz de XML en tres líneas:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

Ta da!

Antonio Max
fuente
7

Hay varias razones para no analizar HTML por expresión regular. Pero, si tiene un control total de lo que se generará HTML, puede hacerlo con una expresión regular simple.

Arriba es una función que analiza HTML por expresión regular. Tenga en cuenta que esta función es muy sensible y exige que el HTML obedezca ciertas reglas, pero funciona muy bien en muchos escenarios. Si desea un analizador simple y no desea instalar bibliotecas, pruebe esto:

function array_combine_($keys, $values) {
    $result = array();
    foreach ($keys as $i => $k) {
        $result[$k][] = $values[$i];
    }
    array_walk($result, create_function('&$v', '$v = (count($v) == 1)? array_pop($v): $v;'));

    return $result;
}

function extract_data($str) {
    return (is_array($str))
        ? array_map('extract_data', $str)
        : ((!preg_match_all('#<([A-Za-z0-9_]*)[^>]*>(.*?)</\1>#s', $str, $matches))
            ? $str
            : array_map(('extract_data'), array_combine_($matches[1], $matches[2])));
}

print_r(extract_data(file_get_contents("http://www.google.com/")));
Daniel Loureiro
fuente
2

He creado una biblioteca llamada HTML5DOMDocument que está disponible gratuitamente en https://github.com/ivopetkov/html5-dom-document-php

También admite selectores de consultas que creo que serán extremadamente útiles en su caso. Aquí hay un código de ejemplo:

$dom = new IvoPetkov\HTML5DOMDocument();
$dom->loadHTML('<!DOCTYPE html><html><body><h1>Hello</h1><div class="content">This is some text</div></body></html>');
echo $dom->querySelector('h1')->innerHTML;
Ivo Petkov
fuente
0

Si está familiarizado con el selector jQuery, puede usar ScarletsQuery para PHP

<pre><?php
include "ScarletsQuery.php";

// Load the HTML content and parse it
$html = file_get_contents('https://www.lipsum.com');
$dom = Scarlets\Library\MarkupLanguage::parseText($html);

// Select meta tag on the HTML header
$description = $dom->selector('head meta[name="description"]')[0];

// Get 'content' attribute value from meta tag
print_r($description->attr('content'));

$description = $dom->selector('#Content p');

// Get element array
print_r($description->view);

Esta biblioteca suele tardar menos de 1 segundo en procesar html sin conexión.
También acepta HTML no válido o una cita faltante en los atributos de la etiqueta.

StefansArya
fuente
0

El mejor método para analizar xml:

$xml='http://www.example.com/rss.xml';
$rss = simplexml_load_string($xml);
$i = 0;
foreach ($rss->channel->item as $feedItem) {
  $i++;
  echo $title=$feedItem->title;
  echo '<br>';
  echo $link=$feedItem->link;
  echo '<br>';
  if($feedItem->description !='') {
    $des=$feedItem->description;
  } else {
    $des='';
  }
  echo $des;
  echo '<br>';
  if($i>5) break;
}
usuario8031209
fuente