web-dev-qa-db-fra.com

Comment analyser et traiter HTML / XML en PHP?

Comment analyser HTML/XML et en extraire des informations?

2051
RobertPitt

Extensions XML natives

Je préfère utiliser l’une des extensions XML natives car elles sont livrées avec PHP, elles sont généralement plus rapides que toutes les bibliothèques tierces et me donnent tout le contrôle dont j’ai besoin sur le balisage.

DOM

L’extension DOM vous permet d’utiliser des documents XML via l’API DOM avec PHP 5. Il s’agit d’une implémentation du Document Object Model Core Level 3 du W3C, une interface neutre vis-à-vis de la plate-forme et du langage qui permet des scripts pour accéder et mettre à jour de manière dynamique le contenu, la structure et le style des documents.

DOM est capable d’analyser et de modifier le code HTML du monde réel (cassé) et il peut le faire requêtes XPath . Il est basé sur libxml .

Il faut un peu de temps pour être productif avec DOM, mais ce temps en vaut la peine, IMO. Comme DOM est une interface indépendante du langage, vous trouverez des implémentations dans de nombreux langages. Si vous devez changer de langage de programmation, vous saurez alors comment utiliser l'API DOM de ce langage.

Un exemple d'utilisation de base peut être trouvé dans Saisir l'attribut href d'un élément A et un aperçu conceptuel général peut être trouvé à l'adresse DOMDocument in php

L'utilisation de l'extension DOM a été largement couverte par StackOverflow . Si vous choisissez de l'utiliser, vous pouvez être sûr que la plupart des problèmes que vous rencontrez peuvent être résolus en recherchant/parcourant Stack Overflow.

XMLReader

L'extension XMLReader est un analyseur XML d'extraction. Le lecteur agit comme un curseur qui avance sur le flux de documents et s’arrête à chaque nœud sur le chemin.

XMLReader, comme DOM, est basé sur libxml. Je ne sais pas comment déclencher le module d'analyse syntaxique HTML. Il est donc probable que l'utilisation de XMLReader pour analyser du code HTML rompu pourrait être moins robuste que l'utilisation de DOM, où vous pouvez lui indiquer explicitement d'utiliser le module d'analyse syntaxique HTML de libxml.

Un exemple d'utilisation basique peut être trouvé à obtenir toutes les valeurs des balises h1 en utilisant php

analyseur XML

Cette extension vous permet de créer des analyseurs XML, puis de définir des gestionnaires pour différents événements XML. Chaque analyseur XML a également quelques paramètres que vous pouvez ajuster.

La bibliothèque XML Parser est également basée sur libxml et implémente un analyseur XML Push de style SAX . C'est peut-être un meilleur choix pour la gestion de la mémoire que DOM ou SimpleXML, mais il sera plus difficile de travailler avec l'analyseur Pull implémenté par XMLReader.

SimpleXml

L'extension SimpleXML fournit un ensemble d'outils très simple et facilement utilisable pour convertir XML en un objet pouvant être traité avec des sélecteurs de propriétés et des itérateurs de tableaux normaux.

SimpleXML est une option lorsque vous savez que le code HTML est XHTML valide. Si vous avez besoin d'analyser du HTML cassé, n'envisagez même pas SimpleXml, car il va s'étouffer.

Vous trouverez un exemple d'utilisation de base à l'adresse n programme simple pour le nœud CRUD et les valeurs de nœud du fichier xml et il y a de nombreux exemples supplémentaires dans le PHP Manual =.


Bibliothèques tierces (basées sur libxml)

Si vous préférez utiliser une bibliothèque tierce, nous vous suggérons d'utiliser une bibliothèque utilisant réellement DOM / libxml au lieu d'analyser des chaînes.

FluentDom - Repo

FluentDOM fournit une interface XML fluide de type jQuery pour le DOMDocument en PHP. Les sélecteurs sont écrits en XPath ou CSS (à l'aide d'un convertisseur CSS en XPath). Les versions actuelles étendent le DOM en mettant en œuvre des interfaces standard et ajoutent des fonctionnalités du DOM Living Standard. FluentDOM peut charger des formats tels que JSON, CSV, JsonML, RabbitFish et autres. Peut être installé via Composer.

HtmlPageDom

Wa72\HtmlPageDom` est une bibliothèque PHP facilitant la manipulation de documents HTML à l’aide de It require DomCrawler des composants Symfony2 pour parcourir l’arborescence DOM et l’étend en ajoutant des méthodes de manipulation de l’arborescence DOM. de documents HTML.

phpQuery (non mis à jour depuis des années)

phpQuery est une API DOM (Document Object Model) basée sur la bibliothèque JavaScript jQuery écrite en PHP5 et gérée par un sélecteur côté CSS3. Elle fournit une interface de ligne de commande (CLI) supplémentaire.

Voir aussi: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom fournit des outils pour travailler avec des documents et des structures DOM. Nous proposons actuellement Zend_Dom_Query, qui fournit une interface unifiée pour interroger des documents DOM à l'aide de sélecteurs XPath et CSS.

QueryPath

QueryPath est une bibliothèque PHP pour manipuler XML et HTML. Il est conçu pour fonctionner non seulement avec les fichiers locaux, mais également avec les services Web et les ressources de base de données. Il implémente une grande partie de l'interface jQuery (y compris des sélecteurs de style CSS), mais il est fortement optimisé pour une utilisation côté serveur. Peut être installé via Composer.

fDOMDocument

fDOMDocument étend le DOM standard pour qu'il utilise des exceptions en toutes occasions d'erreur à la place de PHP avertissements ou notifications. Ils ajoutent également diverses méthodes et raccourcis personnalisés pour plus de commodité et pour simplifier l'utilisation de DOM.

sabre/xml

sabre/xml est une bibliothèque qui englobe et étend les classes XMLReader et XMLWriter afin de créer un système de mappage et un modèle de conception "XML à objet/tableau" simples. L'écriture et la lecture de XML sont en un seul passage et peuvent donc être rapides et nécessitent peu de mémoire sur les gros fichiers xml.

FluidXML

FluidXML est une bibliothèque PHP permettant de manipuler XML avec une API concise et fluide. Il utilise XPath et le modèle de programmation fluide pour être amusant et efficace.


Tierce partie (non basée sur libxml)

L’utilisation de DOM/libxml présente l’avantage de vous permettre d’obtenir de bonnes performances, car vous êtes basé sur une extension native. Cependant, toutes les bibliothèques tierces ne suivent pas cette voie. Certains d'entre eux énumérés ci-dessous

PHP Simple HTML DOM Parser

  • Un analyseur HTML DOM écrit en PHP5 + vous permet de manipuler le HTML très facilement!
  • Requiert PHP 5+.
  • Prend en charge le code HTML invalide.
  • Recherchez des balises sur une page HTML avec des sélecteurs, comme jQuery.
  • Extrayez le contenu du HTML en une seule ligne.

Je ne recommande généralement pas cet analyseur. La base de code est horrible et l'analyseur lui-même est plutôt lent et gourmand en mémoire. Tous les sélecteurs jQuery (tels que sélecteurs enfants ) ne sont pas possibles. Toutes les bibliothèques basées sur libxml devraient facilement surpasser cette performance.

PHP Html Parser

PHPHtmlParser est un analyseur syntaxique HTML simple et flexible qui vous permet de sélectionner des étiquettes à l’aide de n’importe quel sélecteur css, comme jQuery. L’objectif est d’aider au développement d’outils nécessitant un moyen simple et rapide de supprimer le code HTML, qu’il soit valide ou non! Ce projet a été initialement pris en charge par sunra/php-simple-html-dom-parser, mais ce soutien semble s’être arrêté, ce projet est donc mon adaptation de son travail précédent.

Encore une fois, je ne recommanderais pas cet analyseur. Il est plutôt lent avec une utilisation élevée du processeur. Il n’existe pas non plus de fonction pour effacer la mémoire des objets DOM créés. Ces problèmes sont particulièrement graves avec les boucles imbriquées. La documentation elle-même est inexacte et mal orthographiée, aucune réponse aux correctifs n’a été apportée depuis le 14 avril 16.

Ganon

  • Un tokenizer universel et un analyseur DOM HTML/XML/RSS
    • Capacité à manipuler des éléments et leurs attributs
    • Prend en charge les codes HTML et UTF8 non valides
  • Peut effectuer des requêtes avancées de type CSS3 sur des éléments (comme jQuery - espaces de noms pris en charge)
  • Un embellisseur HTML (comme HTML Tidy)
    • Minify CSS et Javascript
    • Trier les attributs, changer la casse des caractères, corriger l'indentation, etc.
  • Extensible
    • Analyse de documents à l'aide de rappels basés sur le caractère/jeton actuel
    • Opérations séparées en fonctions plus petites pour faciliter la gestion
  • Rapide et facile

Jamais utilisé. Je ne peux pas dire si c'est bon.


HTML 5

Vous pouvez utiliser ce qui précède pour analyser HTML5, mais il peut y avoir des bizarreries en raison du balisage autorisé par HTML5. Donc, pour HTML5, vous voulez utiliser un analyseur syntaxique dédié, comme

html5lib

Une implémentation de Python et PHP d'un analyseur HTML basé sur la spécification WHATWG HTML5 pour une compatibilité maximale avec les principaux navigateurs Web de bureau.

Nous pourrions voir plus d'analyseurs syntaxiques dédiés une fois que HTML5 est finalisé. Il y a aussi un article de blog par le W3 intitulé How-To pour l'analyse de HTML 5 qui vaut la peine d'être vérifié.


Services Web

Si vous ne souhaitez pas programmer PHP, vous pouvez également utiliser les services Web. En général, j'ai trouvé très peu d'utilité pour ces applications, mais ce n'est que moi et mes cas d'utilisation.

ScraperWiki .

L’interface externe de ScraperWiki vous permet d’extraire des données sous la forme que vous souhaitez utiliser sur le Web ou dans vos propres applications. Vous pouvez également extraire des informations sur l'état d'un racleur.


Expressions régulières

Dernier et moins recommandé , vous pouvez extraire des données à partir de HTML avec expressions régulières . En général, il est déconseillé d'utiliser des expressions régulières sur HTML.

La plupart des extraits que vous trouverez sur le Web pour correspondre au balisage sont fragiles. Dans la plupart des cas, ils ne travaillent que pour un élément HTML très particulier. De petites modifications, telles que l'ajout d'espaces ou l'ajout ou la modification d'attributs dans une balise, peuvent provoquer l'échec de RegEx lorsqu'il n'est pas écrit correctement. Vous devriez savoir ce que vous faites avant d'utiliser RegEx sur HTML.

Les analyseurs HTML connaissent déjà les règles syntaxiques du HTML. Les expressions régulières doivent être enseignées pour chaque nouveau RegEx que vous écrivez. Les RegEx conviennent dans certains cas, mais cela dépend vraiment de votre cas d'utilisation.

Vous pouvez écrire des analyseurs syntaxiques plus fiables , mais écrire un analyseur personnalisé complet et fiable avec des expressions régulières est une perte de temps lorsque les bibliothèques susmentionnées existent déjà. un bien meilleur travail là-dessus.

Voir aussi Analyser Html à la manière de Cthulh


Livres

Si vous voulez dépenser de l'argent, jetez un coup d'œil à

Je ne suis pas affilié à PHP Architect ou aux auteurs.

1845
Gordon

Essayez Simple HTML DOM Parser

  • Un analyseur HTML DOM écrit en PHP 5+ qui vous permet de manipuler le HTML très facilement!
  • Requiert PHP 5+.
  • Prend en charge le code HTML invalide.
  • Recherchez des balises sur une page HTML avec des sélecteurs, comme jQuery.
  • Extrayez le contenu du HTML en une seule ligne.
  • Télécharger


Exemples:

Comment obtenir des éléments 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>';


Comment modifier des éléments 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;


Extraire le contenu du HTML:

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


Gratter 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);
319
Naveed

Il suffit d’utiliser DOMDocument-> loadHTML () et d’en finir. L'algorithme d'analyse HTML de libxml est assez bon et rapide, et contrairement à la croyance populaire, ne s'étouffe pas avec du HTML mal formé.

232
Edward Z. Yang

Pourquoi ne devriez-vous pas et alors que vous devriez utiliser des expressions régulières?

Tout d'abord, un abus de langage courant: Les expressions rationnelles ne sont pas pour " analyser " HTML. Les expressions rationnelles peuvent cependant "( extraire des données " . Extraire est ce pour quoi ils sont faits. L’inconvénient majeur de l’extraction HTML regex sur les kits d’outils SGML ou les analyseurs XML de base est leur effort syntaxique et leur fiabilité variable.

Considérez que faire une regex d’extraction HTML quelque peu fiable:

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

est beaucoup moins lisible qu’un simple équivalent phpQuery ou QueryPath:

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

Il existe cependant des cas d'utilisation spécifiques où ils peuvent aider.

  • De nombreux frontaux de traversée du DOM ne révèlent pas les commentaires HTML <!--, qui sont toutefois parfois les ancres les plus utiles pour l'extraction. En particulier, les variations pseudo-HTML <$var> ou SGML sont faciles à apprivoiser avec les expressions rationnelles.
  • Souvent, les expressions régulières peuvent sauver le post-traitement. Cependant, les entités HTML requièrent souvent un contrôle manuel.
  • Enfin, pour e , les tâches extrêmement simples telles que l'extraction de <img src = urls sont en fait un outil probable. L’avantage de la vitesse par rapport aux analyseurs SGML/XML ne concerne que ces procédures d’extraction très élémentaires.

Il est parfois même conseillé de pré-extraire un fragment de code HTML à l'aide d'expressions régulières /<!--CONTENT-->(.+?)<!--END-->/ et de traiter le reste à l'aide des interfaces de programme d'analyse HTML plus simples.

Remarque: En fait, j'ai ceci app , où j'utilise l'analyse syntaxique XML et les expressions régulières à la place. Pas plus tard que la semaine dernière, l'analyse syntaxique de PyQuery a éclaté et la regex fonctionnait toujours. Oui bizarre, et je ne peux pas l'expliquer moi-même. Mais c'est arrivé.
Donc, s'il vous plaît, n'éliminez pas les considérations du monde réel, simplement parce que cela ne correspond pas à la regex = meme evil. Mais ne votons pas trop là-dessus. C'est juste une note de bas de page pour ce sujet.

145
mario

phpQuery et QueryPath sont extrêmement similaires dans la réplication de l'API jQuery fluide. C'est aussi pourquoi ils sont deux des approches les plus faciles pour correctement analyser HTML en PHP.

Exemples pour QueryPath

Fondamentalement, vous créez d'abord une arborescence DOM interrogeable à partir d'une chaîne HTML:

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

L'objet résultant contient une représentation arborescente complète du document HTML. Il peut être parcouru à l'aide de méthodes DOM. Mais l'approche courante consiste à utiliser des sélecteurs CSS comme dans jQuery:

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

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

Généralement, vous voulez utiliser les sélecteurs de balises #id et .class ou DIV simples pour ->find(). Mais vous pouvez également utiliser les instructions XPath , qui sont parfois plus rapides. Les méthodes jQuery typiques telles que ->children() et ->text() et en particulier ->attr() simplifient l'extraction des fragments HTML appropriés. (Et ont déjà leurs entités SGML décodées.)

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

QueryPath permet également d'injecter de nouvelles balises dans le flux (->append), puis de générer et d'ajuster ultérieurement un document mis à jour (->writeHTML). Il peut non seulement analyser du HTML mal formé, mais également divers dialectes XML (avec des espaces de noms), et même extraire des données à partir de microformats HTML (XFN, vCard).

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

.

phpQuery ou QueryPath?

En règle générale, QueryPath convient mieux à la manipulation de documents. Bien que phpQuery implémente également certaines méthodes pseudo AJAX (uniquement les requêtes HTTP) pour ressembler davantage à jQuery. On dit que phpQuery est souvent plus rapide que QueryPath (à cause de moins de fonctionnalités globales).

Pour plus d’informations sur les différences, voir cette comparaison sur la machine à remonter de tagbyte.org . (La source originale a disparu, alors voici un lien vers les archives Internet. Oui, vous pouvez toujours localiser les pages et les personnes manquantes.)

Et voici ne introduction complète à QueryPath .

Avantages

  • Simplicité et fiabilité
  • Alternatives simples à utiliser ->find("a img, a object, div a")
  • Élimination correcte des données (par rapport à la récupération d’expression régulière)
130
mario

Simple HTML DOM est un excellent analyseur open source:

simplehtmldom.sourceforge

Il traite les éléments DOM d'une manière orientée objet, et la nouvelle itération couvre largement le code non conforme. Il existe également d’excellentes fonctions, comme celle que vous voyez en JavaScript, telles que la fonction "rechercher", qui renverront toutes les occurrences des éléments de ce nom de balise.

Je l'ai utilisé dans un certain nombre d'outils, en le testant sur de nombreux types de pages Web, et je pense que cela fonctionne très bien.

88
Robert Elwell

Une approche générale que je n'ai pas vue mentionnée ici consiste à exécuter HTML à travers Tidy , qui peut être configuré pour cracher du XHTML à validité garantie. Ensuite, vous pouvez utiliser n'importe quelle ancienne bibliothèque XML dessus.

Mais pour votre problème spécifique, vous devriez jeter un oeil à ce projet: http://fivefilters.org/content-only/ - c'est une version modifiée du Lisibilité algorithme, conçu pour extraire uniquement le contenu textuel (pas les en-têtes et les pieds de page) d'une page.

59
Eli

Pour 1a et 2: je voterais pour la nouvelle classe Symfony Componet, DOMCrawler ( DomCrawler ). Cette classe autorise les requêtes similaires aux sélecteurs CSS. Jetez un coup d'œil à cette présentation pour voir des exemples concrets: news-of-the-symfony2-world .

Le composant est conçu pour fonctionner de manière autonome et peut être utilisé sans Symfony.

Le seul inconvénient est que cela ne fonctionnera qu'avec PHP 5.3 ou plus récent.

55
Timo

Ceci est communément appelé grattage de l'écran , en passant. La bibliothèque que j'ai utilisée pour cela est Simple HTML Dom Parser .

52
Joel Verhagen

Nous avons déjà créé pas mal de robots pour nos besoins. À la fin de la journée, ce sont généralement de simples expressions régulières qui font le mieux. Bien que les bibliothèques répertoriées ci-dessus conviennent à la raison de leur création, si vous savez ce que vous recherchez, les expressions régulières sont un moyen plus sûr, car vous pouvez également gérer les informations non valides HTML / XHTML structures, qui échoueraient si elles étaient chargées via la plupart des analyseurs.

41
jancha

Je recommande PHP Simple HTML DOM Parser .

Il a vraiment de belles fonctionnalités, comme:

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

Cela ressemble à une bonne description de la tâche de la technologie W3C XPath . Il est facile d’exprimer des requêtes telles que "renvoyer tous les attributs href dans des balises img imbriquées dans <foo><bar><baz> elements." N'étant pas un buffPHP, je ne peux pas vous dire sous quelle forme XPath peut être disponible. Si vous pouvez appeler un programme externe pour traiter le fichier HTML, vous devriez pouvoir utiliser une version en ligne de commande de XPath. Pour une introduction rapide, voir http://en.wikipedia.org/wiki/XPath .

36
Jens

Alternatives tierces à SimpleHtmlDom qui utilisent DOM à la place de l'analyse syntaxique des chaînes: phpQuery , Zend_Dom , QueryPath et FluentDom .

29
danidacar

Oui, vous pouvez utiliser simple_html_dom à cette fin. Cependant, j'ai beaucoup travaillé avec simple_html_dom, en particulier pour le démantèlement de sites Web, et je l'ai trouvé trop vulnérable. Il fait le travail de base mais je ne le recommanderai pas de toute façon.

Je n'ai jamais utilisé curl à cette fin, mais ce que j'ai appris, c'est que curl peut faire le travail beaucoup plus efficacement et est beaucoup plus solide.

Veuillez vérifier ce lien: scraping-sites-with-curl

24
Rafay

QueryPath c'est bien, mais faites attention à "l'état de suivi", car si vous ne réalisez pas ce que cela signifie, vous risquez de perdre beaucoup de temps à déboguer pour essayer de comprendre ce qui s'est passé et pourquoi le code ne fonctionne pas.

Cela signifie que chaque appel du jeu de résultats modifie le jeu de résultats dans l'objet, ce n'est pas chaînable comme dans jquery où chaque lien est un nouvel ensemble, vous avez un seul jeu qui correspond aux résultats de votre requête et chaque appel de fonction modifie cet ensemble unique.

pour obtenir un comportement semblable à jquery, vous devez créer une branche avant d'effectuer une opération de type filtre/modifier, ce qui signifie que cela va refléter beaucoup plus étroitement ce qui se passe dans jQuery.

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

$results contient maintenant le jeu de résultats pour input[name='forename'] PAS la requête d'origine "div p" cela m'a fait beaucoup de peine, ce que j'ai trouvé était que QueryPath suit les filtres et trouve et tout ce qui modifie vos résultats et les stocke dans l'objet. vous devez le faire à la place

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

alors $results ne sera pas modifié et vous pourrez réutiliser le jeu de résultats encore et encore. Peut-être une personne mieux informée pourra-t-elle clarifier cela un peu, mais c'est en gros ce que j'ai trouvé.

23
Christopher Thomas

Advanced Html Dom est un simple remplacement HTML DOM qui offre la même interface, mais il est basé sur DOM, ce qui signifie qu'aucun des problèmes de mémoire associés ne se produit.

Il dispose également d’un support CSS complet, y compris les extensions jQuery .

19
pguardiario

Pour HTML5 , la bibliothèque html5 est abandonnée depuis des années. La seule bibliothèque HTML5 que je puisse trouver avec une mise à jour récente et des enregistrements de maintenance est html5-php qui vient d’être mise à la version bêta 1.0 il ya un peu plus d’une semaine.

18
Reid Johnson

J'ai écrit un analyseur XML d'usage général qui peut facilement gérer des fichiers Go. Il est basé sur XMLReader et est très facile à utiliser:

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

Voici le repo de github: XmlExtractor

17
Paul Warelis

J'ai créé une bibliothèque nommée PHPPowertools/DOM-Query , qui vous permet d'explorer des documents HTML5 et XML comme vous le feriez avec jQuery.

Sous le capot, il utilise symfony/DomCrawler pour la conversion des sélecteurs CSS en XPath . Il utilise toujours le même DomDocument, même lors du transfert d'un objet à un autre, pour garantir des performances correctes.


Exemple d'utilisation:

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éthodes supportées:


  1. renommé 'select', pour des raisons évidentes
  2. renommé 'void', puisque 'empty' est un mot réservé en PHP

REMARQUE :

La bibliothèque comprend également son propre chargeur automatique à configuration zéro pour les bibliothèques compatibles PSR-0. L'exemple inclus devrait fonctionner sans aucune configuration supplémentaire. Alternativement, vous pouvez l'utiliser avec composer.

17
John Slegers

Vous pouvez essayer d'utiliser quelque chose comme HTML Tidy pour nettoyer tout code HTML "cassé" et convertir le code HTML en XHTML, que vous pourrez ensuite analyser avec un analyseur XML.

15
CesarB

Une autre option que vous pouvez essayer est QueryPath . Il est inspiré de jQuery, mais sur le serveur sous PHP et utilisé dans Drupal .

15

XML_HTMLSax est plutôt stable - même s'il n'est plus maintenu. Une autre option pourrait être de vous diriger vers HTML à travers Html ​​Tidy , puis de l’analyser avec des outils XML standard.

12
troelskn

Le framework Symfony contient des ensembles permettant d'analyser le code HTML. Vous pouvez utiliser le style CSS pour sélectionner DOM au lieu d'utiliser XPath .

11
Tuong Le

Il existe de nombreuses façons de traiter les DOM HTML/XML, dont la plupart ont déjà été mentionnées. Par conséquent, je ne ferai aucune tentative pour les énumérer moi-même.

Je veux simplement ajouter que je préfère personnellement utiliser l'extension DOM et pourquoi:

  • iit utilise au mieux les performances du code C sous-jacent
  • c'est OO PHP (et me permet de le sous-classer)
  • c'est plutôt faible (ce qui me permet de l'utiliser comme base non gonflée pour un comportement plus avancé)
  • il fournit un accès à toutes les parties du DOM (contrairement à SimpleXml, qui ignore certaines des fonctionnalités XML les moins connues)
  • sa syntaxe utilisée pour l'analyse DOM est similaire à celle utilisée en Javascript natif.

Et bien que la possibilité d’utiliser des sélecteurs CSS pour DOMDocument me manque, il existe un moyen plutôt simple et pratique d’ajouter cette fonctionnalité: sous-classer le DOMDocument et ajouter JS-like querySelectorAll et querySelector méthodes de votre sous-classe.

Pour analyser les sélecteurs, je recommande d'utiliser le très minimaliste composant CssSelector du framework Symfony . Ce composant traduit simplement les sélecteurs CSS en sélecteurs XPath, qui peuvent ensuite être introduits dans un DOMXpath pour récupérer la liste de noeuds correspondante.

Vous pouvez ensuite utiliser cette sous-classe (encore très bas niveau) comme base pour des classes plus élevées, destinées par exemple à. analyser des types de XML très spécifiques ou ajouter davantage de comportements de type jQuery.

Le code ci-dessous provient directement de ma bibliothèque DOM-Query et utilise la technique que j'ai décrite.

Pour l'analyse 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);
                }
            }
        }
    }

    [...]
}

Voir aussi Analyse de documents XML avec des sélecteurs CSS par le créateur de Symfony, Fabien Potencier, sur sa décision de créer le composant CssSelector pour Symfony et son utilisation.

11
John Slegers

Avec FluidXML , vous pouvez interroger et itérer XML à l'aide de XPath et Sélecteurs CSS .

$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

9
Daniele Orlando

JSON et tableau à partir de XML en trois lignes:

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

Ta da!

7
Antonio Max

Il y a plusieurs raisons de ne pas analyser HTML par expression régulière. Mais si vous avez le contrôle total sur le code HTML qui sera généré, vous pouvez le faire avec une simple expression régulière.

Ci-dessus, une fonction qui analyse HTML par expression régulière. Notez que cette fonction est très sensible et exige que le code HTML obéisse à certaines règles, mais cela fonctionne très bien dans de nombreux scénarios. Si vous voulez un simple analyseur et que vous ne voulez pas installer de bibliothèques, essayez ceci:

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/")));
7
Daniel Loureiro

J'ai créé une bibliothèque appelée HTML5DOMDocument qui est disponible gratuitement sur https://github.com/ivopetkov/html5-dom-document-php

Il prend également en charge les sélecteurs de requête qui, à mon avis, seront extrêmement utiles dans votre cas. Voici un exemple de code:

$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;
2
Ivo Petkov

Si vous connaissez le sélecteur jQuery, vous pouvez utiliser ScarletsQuery pour 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);

Cette bibliothèque prend généralement moins de 1 seconde pour traiter le code HTML hors connexion.
Il accepte également le code HTML non valide ou les guillemets manquants sur les attributs de balises.

0
StefansArya

La meilleure méthode pour analyser 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;
}
0
user8031209