Comment analyser et traiter HTML / XML en PHP?


Réponses:


1897

Extensions XML natives

Je préfère utiliser l'une des extensions XML natives car elles sont fournies avec PHP, 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'opérer sur des documents XML via l'API DOM avec PHP 5. C'est une implémentation du Document Object Model Core Level 3 du W3C, une interface indépendante de la plate-forme et du langage qui permet aux programmes et aux scripts d'accéder et de mettre à jour dynamiquement. le contenu, la structure et le style des documents.

DOM est capable d'analyser et de modifier du HTML réel (cassé) et il peut effectuer des requêtes XPath . Il est basé sur libxml .

Il faut du temps pour être productif avec DOM, mais ce temps en vaut la peine IMO. Étant donné que DOM est une interface indépendante du langage, vous trouverez des implémentations dans de nombreux langages, donc si vous devez changer votre langage de programmation, il est probable que vous saurez déjà comment utiliser l'API DOM de ce langage.

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

Comment utiliser l'extension DOM a été largement traité sur StackOverflow , donc 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 d'extraction XML. Le lecteur agit comme un curseur qui avance sur le flux de documents et s'arrête à chaque nœud en cours de route.

XMLReader, comme DOM, est basé sur libxml. Je ne sais pas comment déclencher le module HTML Parser, donc les chances d'utiliser XMLReader pour analyser le HTML cassé pourraient être moins robustes que l'utilisation de DOM où vous pouvez explicitement lui dire d'utiliser le module HTML Parser de libxml.

Un exemple d'utilisation de base peut être trouvé pour 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 possède également quelques paramètres que vous pouvez ajuster.

La bibliothèque XML Parser est également basée sur libxml et implémente un analyseur push XML de style SAX . Il peut être un meilleur choix pour la gestion de la mémoire que DOM ou SimpleXML, mais sera plus difficile à utiliser que l'analyseur par extraction 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 qui peut être traité avec des sélecteurs de propriété normaux et des itérateurs de tableau.

SimpleXML est une option lorsque vous savez que le HTML est du XHTML valide. Si vous devez analyser du code HTML cassé, ne pensez même pas à SimpleXml car il s'étouffera.

Un exemple d'utilisation de base peut être trouvé dans Un programme simple pour le nœud CRUD et les valeurs de nœud du fichier xml et il y a beaucoup d'exemples supplémentaires dans le manuel PHP .


Bibliothèques tierces (basées sur libxml)

Si vous préférez utiliser une bibliothèque tierce, je vous suggère d'utiliser une bibliothèque qui utilise réellement DOM / libxml en dessous au lieu d'analyser les 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 (en utilisant un convertisseur CSS en XPath). Les versions actuelles étendent les interfaces standard d'implémentation du DOM et ajoutent des fonctionnalités du DOM Living Standard. FluentDOM peut charger des formats comme JSON, CSV, JsonML, RabbitFish et autres. Peut être installé via Composer.

HtmlPageDom

Wa72 \ HtmlPageDom` est une bibliothèque PHP pour une manipulation facile des documents HTML en utilisant Elle nécessite DomCrawler des composants Symfony2 pour parcourir l'arborescence DOM et l'étend en ajoutant des méthodes pour manipuler l'arborescence DOM des documents HTML.

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

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

Voir également: https://github.com/electrolinux/phpquery

Zend_Dom

Zend_Dom fournit des outils pour travailler avec des documents et des structures DOM. Actuellement, nous proposons Zend_Dom_Query, qui fournit une interface unifiée pour interroger les documents DOM à l'aide des 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 des fichiers locaux, mais également avec des services Web et des ressources de base de données. Il implémente une grande partie de l'interface jQuery (y compris les 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 utiliser des exceptions à toutes les occasions d'erreurs au lieu des avertissements ou des avis PHP. Ils ajoutent également diverses méthodes et raccourcis personnalisés pour plus de commodité et pour simplifier l'utilisation du DOM.

sabre / xml

sabre / xml est une bibliothèque qui encapsule et étend les classes XMLReader et XMLWriter pour créer un système de mappage et un modèle de conception "xml vers 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 pour manipuler XML avec une API concise et fluide. Il exploite XPath et le modèle de programmation fluide pour être amusant et efficace.


Tierce partie (non basée sur libxml)

L'avantage de s'appuyer sur DOM / libxml est que vous obtenez de bonnes performances prédéfinies car vous êtes basé sur une extension native. Cependant, toutes les bibliothèques tierces ne suivent pas cette voie. Certains d'entre eux sont énumérés ci-dessous

Analyseur DOM HTML simple PHP

  • Un analyseur DOM HTML écrit en PHP5 + vous permet de manipuler le HTML de manière très simple!
  • Nécessite PHP 5+.
  • Prend en charge le code HTML non valide.
  • Trouvez des balises sur une page HTML avec des sélecteurs comme jQuery.
  • Extrayez le contenu du HTML sur 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 les sélecteurs enfants ) ne sont pas possibles. N'importe laquelle des bibliothèques basées sur libxml devrait surpasser cela facilement.

Analyseur PHP Html

PHPHtmlParser est un analyseur html simple et flexible qui vous permet de sélectionner des balises à l'aide de n'importe quel sélecteur css, comme jQuery. L'objectif est d'assister au développement d'outils qui nécessitent un moyen simple et rapide de scraper du html, qu'il soit valide ou non! Ce projet était originalement soutenu par sunra / php-simple-html-dom-parser mais le support semble s'être arrêté donc ce projet est 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'y a pas non plus de fonction pour effacer la mémoire des objets DOM créés. Ces problèmes évoluent particulièrement avec les boucles imbriquées. La documentation elle-même est inexacte et mal orthographiée, sans réponse aux correctifs 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 HTML non valide et UTF8
  • 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)
    • Réduisez CSS et Javascript
    • Trier les attributs, changer la casse des caractères, corriger l'indentation, etc.
  • Extensible
    • Analyser des documents à l'aide de rappels basés sur le caractère / jeton actuel
    • Opérations séparées en fonctions plus petites pour un remplacement facile
  • Rapide et facile

Je ne l'ai 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 HTML5 autorisé. Donc, pour HTML5, vous souhaitez envisager d'utiliser un analyseur dédié, comme

html5lib

Une implémentation 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 dédiés une fois le HTML5 finalisé. Il existe également un article de blog du W3 intitulé How-To for html 5 parsing qui mérite d'être consulté.


Services Web

Si vous n'avez pas envie de programmer PHP, vous pouvez également utiliser les services Web. En général, j'ai trouvé très peu d'utilité pour ceux-ci, mais c'est juste 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 de n'importe quel grattoir.


Expressions régulières

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

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

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

Vous pouvez écrire des analyseurs 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à et font un bien meilleur travail à ce sujet.

Voir aussi Parsing Html The Cthulhu Way


Livres

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

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


10
@Naveed qui dépend de vos besoins. Je n'ai pas besoin de requêtes CSS Selector, c'est pourquoi j'utilise exclusivement DOM avec XPath. phpQuery vise à être un port jQuery. Zend_Dom est léger. Vous devez vraiment les vérifier pour voir lequel vous préférez.
Gordon

2
@ Ms2ger Surtout, mais pas complètement. Comme déjà indiqué ci-dessus, vous pouvez utiliser les analyseurs basés sur libxml mais il y a des cas particuliers où ceux-ci s'étoufferont. Si vous avez besoin d'une compatibilité maximale, il vaut mieux utiliser un analyseur dédié. Je préfère garder la distinction.
Gordon

9
Votre argument pour ne pas utiliser PHP Simple HTML DOM Parser semble théorique.
Petah

3
Depuis le 29 mars 2012, DOM ne prend pas en charge html5, XMLReader ne prend pas en charge HTML et la dernière validation sur html5lib pour PHP date de septembre 2009. Que faut-il utiliser pour analyser HTML5, HTML4 et XHTML?
Shiplu Mokaddim

4
@Nasha J'ai délibérément exclu la tristement célèbre diatribe Zalgo de la liste ci-dessus parce qu'elle n'est pas trop utile en elle-même et conduit à un certain culte de la cargaison depuis qu'elle a été écrite. Les gens ont été giflés avec ce lien, peu importe à quel point une expression rationnelle aurait été une solution. Pour un avis plus équilibré, s'il vous plaît voir le lien que je n'inclus au lieu et passer par les commentaires à stackoverflow.com/questions/4245008/...
Gordon

322

Essayez Simple HTML DOM Parser

  • Un analyseur DOM HTML écrit en PHP 5+ qui vous permet de manipuler le HTML de manière très simple!
  • Nécessite PHP 5+.
  • Prend en charge le code HTML non valide.
  • Trouvez des balises sur une page HTML avec des sélecteurs comme jQuery.
  • Extrayez le contenu du HTML sur 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);

8
Eh bien, premièrement, je dois me préparer à des éléments tels que les mauvais DOM, le code Invlid, ainsi que l'analyse js par rapport au moteur DNSBL, cela sera également utilisé pour rechercher les sites / contenus malveillants, ainsi que le fait que j'ai construit mon site autour d'un cadre i ont construit, il doit être propre, lisible et bien structuré. SimpleDim est génial mais le code est légèrement désordonné
RobertPitt

9
@Robert, vous pouvez également consulter htmlpurifier.org pour les informations relatives à la sécurité.
Gordon

3
Il a un point valable: simpleHTMLDOM est difficile à étendre, à moins que vous n'utilisiez un motif de décoration, que je trouve difficile à manier. Je me suis retrouvé frissonnant juste à apporter des changements aux classes sous-jacentes elles-mêmes.
Erik

1
Ce que j'ai fait, c'est d'exécuter mon html dans Tidy avant de l'envoyer à SimpleDOM.
MB34

1
Je l'utilise actuellement, je l'exécute dans le cadre d'un projet pour traiter quelques centaines d'URL. Cela devient très lent et des délais d'expiration réguliers persistent. C'est un excellent script pour débutants et intuitivement simple à apprendre, mais tout simplement trop basique pour des projets plus avancés.
luke_mclachlan

236

Utilisez simplement DOMDocument-> loadHTML () et terminez avec. L'algorithme d'analyse HTML de libxml est assez bon et rapide, et contrairement à la croyance populaire, ne s'étouffe pas avec le HTML mal formé.


19
Vrai. Et cela fonctionne avec les classes intégrées XPath et XSLTProcessor de PHP, qui sont idéales pour l'extraction de contenu.
Kornel

8
Pour du HTML vraiment déformé, vous pouvez toujours l'exécuter via htmltidy avant de le transmettre à DOM. Chaque fois que je dois extraire des données de HTML, j'utilise toujours DOM, ou au moins simplexml.
Frank Farmer

9
Une autre chose avec le chargement de HTML malformé i qu'il serait sage d'appeler libxml_use_internal_errors (true) pour éviter les avertissements qui arrêteront l'analyse.
Husky

6
J'ai utilisé DOMDocument pour analyser environ 1000 sources html (dans différentes langues encodées avec différents jeux de caractères) sans aucun problème. Vous pourriez rencontrer des problèmes d'encodage avec cela, mais ils ne sont pas insurmontables. Vous devez savoir 3 choses: 1) loadHTML utilise le jeu de caractères de la balise META pour déterminer l'encodage 2) # 2 peut conduire à une détection de codage incorrecte si le contenu html ne comprend pas ces informations 3) de mauvais caractères UTF-8 peuvent déclencher l'analyseur. Dans de tels cas, utilisez une combinaison de mb_detect_encoding () et de l'encodage / conversion / suppression du code de caractères UTF-8 de Simplepie RSS Parser pour contourner ce problème.
Zero

1
DOM prend réellement en charge XPath, jetez un œil à DOMXPath .
Ryan McCue

147

Pourquoi vous ne devriez pas et quand utiliser des expressions régulières?

Tout d'abord, un abus de langage courant: les expressions rationnelles ne sont pas destinées à " analyser " le HTML. Les regex peuvent cependant " extraire " données. Extraire est ce pour quoi ils sont faits. L'inconvénient majeur de l'extraction de regex HTML par rapport aux boîtes à outils SGML appropriées ou aux analyseurs XML de base est leur effort syntaxique et leur fiabilité variable.

Considérez que faire une expression rationnelle 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 bien moins lisible qu'un simple équivalent de 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 DOM ne révèlent pas de commentaires HTML <!--, qui sont cependant parfois les ancres les plus utiles pour l'extraction. En particulier, les variations pseudo-HTML <$var>ou les résidus SGML sont faciles à apprivoiser avec les expressions rationnelles.
  • Souvent, les expressions régulières peuvent sauver le post-traitement. Cependant, les entités HTML nécessitent souvent un gardiennage manuel.
  • Et enfin, pour des tâches extrêmement simples comme extraire <img src = urls, elles sont en fait un outil probable. L'avantage de la vitesse par rapport aux analyseurs SGML / XML vient principalement de jouer pour ces procédures d'extraction très basiques.

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

Remarque: J'ai en fait cette application , où j'utilise l'analyse syntaxique XML et les expressions régulières alternativement. Pas plus tard que la semaine dernière, l'analyse syntaxique de PyQuery s'est rompue et l'expression régulière fonctionne toujours. Oui bizarre, et je ne peux pas l'expliquer moi-même. Mais c'est arrivé.
Donc, s'il vous plaît, ne votez pas contre les considérations du monde réel, juste parce que cela ne correspond pas au mème regex = evil. Mais ne votons pas non plus trop. Ce n'est qu'une petite note pour ce sujet.


20
DOMCommentpeut lire les commentaires, donc aucune raison d'utiliser Regex pour cela.
Gordon

4
Ni les kits d'outils SGML ni les analyseurs XML ne conviennent pour analyser du HTML réel. Pour cela, seul un analyseur HTML dédié est approprié.
Alohci

12
@Alohci DOMutilise libxml et libxml a un module d' analyseur HTML séparé qui sera utilisé lors du chargement de HTML loadHTML()pour qu'il puisse très bien charger du HTML "réel" (lu cassé).
Gordon

6
Eh bien, juste un commentaire à propos de votre point de vue "considération du monde réel". Bien sûr, il existe des situations utiles pour Regex lors de l'analyse HTML. Et il existe également des situations utiles pour utiliser GOTO. Et il existe des situations utiles pour les variables-variables. Donc, aucune implémentation particulière n'est définitivement décomposée pour son utilisation. Mais c'est un signe d'alerte TRÈS fort. Et le développeur moyen n'est probablement pas suffisamment nuancé pour faire la différence. Donc, en règle générale, Regex GOTO et Variables-Variables sont tous mauvais. Il y a des utilisations non malveillantes, mais ce sont les exceptions (et rares à cela) ... (IMHO)
ircmaxell

11
@mario: En fait, le HTML peut être 'correctement' analysé en utilisant des expressions rationnelles, bien que cela prenne généralement plusieurs d'entre elles pour faire un travail équitable. C'est juste une douleur royale dans le cas général. Dans des cas spécifiques avec une entrée bien définie, elle frôle l’insignifiance. Ce sont les cas sur lesquels les gens devraient utiliser des expressions rationnelles. Les gros vieux analyseurs lourds affamés sont vraiment ce dont vous avez besoin pour les cas généraux, bien qu'il ne soit pas toujours clair pour l'utilisateur occasionnel où tracer cette ligne. Quel que soit le code le plus simple et le plus facile, il gagne.
tchrist

131

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

Exemples pour QueryPath

Fondamentalement, vous créez d'abord un arbre 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 des 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 souhaitez utiliser des sélecteurs simples #idet .classou DIVpour ->find(). Mais vous pouvez également utiliser des instructions XPath , qui sont parfois plus rapides. Les méthodes jQuery typiques comme ->children()et ->text()et particulièrement ->attr()simplifient l'extraction des bons extraits HTML. (Et ont déjà décodé leurs entités SGML.)

 $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 sortir et d'affiner un document mis à jour ( ->writeHTML). Il peut non seulement analyser le HTML mal formé, mais aussi divers dialectes XML (avec des espaces de noms), et même extraire des données de microformats HTML (XFN, vCard).

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

.

phpQuery ou QueryPath?

Généralement, QueryPath est mieux adapté à la manipulation de documents. Bien que phpQuery implémente également certaines pseudo-méthodes AJAX (juste des requêtes HTTP) pour ressembler plus étroitement à jQuery. On dit que phpQuery est souvent plus rapide que QueryPath (en raison de moins de fonctionnalités globales).

Pour plus d'informations sur les différences, consultez cette comparaison sur la machine de retour de tagbyte.org . (La source d'origine a disparu, alors voici un lien vers des archives Internet. Oui, vous pouvez toujours localiser les pages manquantes, les gens.)

Et voici une introduction complète à QueryPath .

Les avantages

  • Simplicité et fiabilité
  • Alternatives simples à utiliser ->find("a img, a object, div a")
  • Déséchappement correct des données (par rapport à la grepping des expressions régulières)

88

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 a beaucoup de couverture pour le code non conforme. Il existe également d'excellentes fonctions comme vous le verriez en JavaScript, comme la fonction "find", qui retournera toutes les instances d'é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.


61

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

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


56

Pour 1a et 2: je voterais pour la nouvelle classe Symfony Componet DOMCrawler ( DomCrawler ). Cette classe permet des requêtes similaires aux sélecteurs CSS. Jetez un oeil à cette présentation pour des exemples du monde réel: 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 qu'il ne fonctionnera qu'avec PHP 5.3 ou plus récent.


Les requêtes css de type jquery sont bien dites, car il y a des choses qui manquent dans la documentation w3c, mais qui sont présentes en tant que fonctionnalités supplémentaires dans jquery.
Nikola Petkanski

53

Soit dit en passant, c'est ce que l'on appelle le grattage d'écran . La bibliothèque que j'ai utilisée pour cela est Simple HTML Dom Parser .


8
Pas strictement vrai ( en.wikipedia.org/wiki/Screen_scraping#Screen_scraping ). L'indice est dans "écran"; dans le cas décrit, aucun écran n'est impliqué. Bien que, certes, le terme ait subi énormément d’abus récents.
Bobby Jack

4
Je ne gratte pas l'écran, le contenu qui sera analysé sera autorisé par le fournisseur de contenu en vertu de mon accord.
RobertPitt

41

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 soient bonnes pour 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 des structures HTML / XHTML non valides , qui échoueraient si elles étaient chargées via la plupart des analyseurs.



36

Cela ressemble à une bonne description des tâches de la technologie W3C XPath . Il est facile d'exprimer des requêtes comme «renvoyer tous les hrefattributs dans les imgbalises imbriquées <foo><bar><baz> elements». N'étant pas un buff PHP, 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 .


29

Alternatives tierces à SimpleHtmlDom qui utilisent DOM au lieu de String Parsing: phpQuery , Zend_Dom , QueryPath et FluentDom .


3
Si vous copiez déjà mes commentaires, liez-les au moins correctement;) Cela devrait être: des alternatives tierces suggérées à SimpleHtmlDom qui utilisent réellement DOM au lieu de l'analyse syntaxique de chaîne: phpQuery , Zend_Dom , QueryPath et FluentDom .
Gordon

1
Les bonnes réponses sont une excellente source. stackoverflow.com/questions/3606792/…
danidacar

24

Oui, vous pouvez utiliser simple_html_dom à cette fin. Cependant, j'ai beaucoup travaillé avec le simple_html_dom, en particulier pour la mise au rebut du 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é le curl à cette fin, mais ce que j'ai appris, c'est que le curl peut faire le travail beaucoup plus efficacement et est beaucoup plus solide.

Veuillez consulter ce lien: scraping-website-with-curl


2
curl peut obtenir le fichier, mais il n'analysera pas le HTML pour vous. Voilà la partie difficile.
cHao

23

QueryPath est bon, mais attention au "suivi de l'état" car si vous ne réalisez pas ce que cela signifie, cela peut vous faire perdre beaucoup de temps de débogage à essayer de découvrir ce qui s'est passé et pourquoi le code ne fonctionne pas.

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

afin d'obtenir un comportement semblable à jquery, vous devez vous brancher avant de faire une opération de filtrage / modification similaire, ce qui signifie qu'il reflétera ce qui se passe dans jquery de plus près.

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

$resultscontient maintenant le jeu de résultats pour input[name='forename']PAS la requête d'origine, "div p"cela m'a beaucoup déclenché, ce que j'ai trouvé, c'est 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 $resultsne sera pas modifié et vous pouvez réutiliser le jeu de résultats encore et encore, peut-être que quelqu'un avec beaucoup plus de connaissances peut clarifier un peu cela, mais c'est essentiellement comme ça d'après ce que j'ai trouvé.


20

Advanced Html Dom est un simple remplacement de DOM HTML 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 a également un support CSS complet, y compris les extensions jQuery .


J'ai de bons résultats d'Advanced Html Dom, et je pense que cela devrait être sur la liste dans la réponse acceptée. Une chose importante à savoir cependant pour quiconque compte sur son "Le but de ce projet est d'être un remplacement drop-in basé sur DOM pour la simple bibliothèque dom html de PHP ... Si vous utilisez file / str_get_html alors vous n'avez pas besoin de changer quoi que ce soit. " archive.is/QtSuj#selection-933.34-933.100 est que vous devrez peut-être apporter des modifications à votre code pour tenir compte de certaines incompatibilités. J'en ai noté quatre que je connais dans les problèmes de github du projet. github.com/monkeysuffrage/advanced_html_dom/issues
ChrisJJ

Travaillé ! Merci
Faisal Shani

18

Pour HTML5 , html5 lib est abandonné depuis des années maintenant. 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 en version bêta 1.0 il y a un peu plus d'une semaine.


17

J'ai écrit un analyseur XML à usage général qui peut facilement gérer les fichiers GB. Il est basé sur XMLReader et il 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 dépôt github: XmlExtractor


17

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

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


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 prises en charge:


  1. Renommé «sélectionner», pour des raisons évidentes
  2. Renommé «void», car «vide» 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 hors de la boîte sans aucune configuration supplémentaire. Alternativement, vous pouvez l'utiliser avec le compositeur.


Ressemble au bon outil pour le travail mais ne se charge pas pour moi en PHP 5.6.23 dans Worpress. Des instructions supplémentaires sur la façon de l'inclure correctement?. Inclus avec: define ("BASE_PATH", dirname ( FILE )); define ("LIBRARY_PATH", BASE_PATH. DIRECTORY_SEPARATOR. 'lib / vendor'); nécessite LIBRARY_PATH. DIRECTORY_SEPARATOR. 'Loader.php'; Loader :: init (tableau (LIBRARY_PATH, USER_PATH)); dans functions.php
lithiumlab

15

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


15

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




11

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 n'essaierai pas de les énumérer moi-même.

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

  • iit fait un usage optimal de l'avantage de performance du code C sous-jacent
  • c'est OO PHP (et me permet de le sous-classer)
  • c'est un niveau assez bas (ce qui me permet de l'utiliser comme une base non gonflée pour un comportement plus avancé)
  • il donne accès à toutes les parties du DOM (contrairement, par exemple, à SimpleXml, qui ignore certaines des fonctionnalités XML moins connues)
  • il a une syntaxe utilisée pour l'exploration DOM qui est similaire à la syntaxe utilisée dans Javascript natif.

Et bien que la possibilité d'utiliser des sélecteurs CSS me manque DOMDocument, il existe un moyen assez simple et pratique d'ajouter cette fonctionnalité: sous-classer le DOMDocumentet ajouter des méthodes querySelectorAllet des querySelectorméthodes de type JS à votre sous-classe.

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

Vous pouvez ensuite utiliser cette sous-classe (toujours de très bas niveau) comme base pour des classes de plus haut niveau, destinées par exemple à. analyser des types de XML très spécifiques ou ajouter un comportement similaire à jQuery.

Le code ci-dessous vient 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 Analyser des 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 comment l'utiliser.


9

Avec FluidXML, vous pouvez interroger et itérer XML à l'aide de sélecteurs XPath et 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


7

JSON et tableau XML à trois lignes:

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

Ta da!


7

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

Ci-dessus, c'est une fonction qui analyse HTML par expression régulière. Notez que cette fonction est très sensible et exige que le HTML obéisse à certaines règles, mais il 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/")));

2

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, je pense, 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;

0

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 html hors ligne.
Il accepte également le HTML non valide ou le devis manquant sur les attributs de balise.


0

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.