Comment analyser HTML / XML et en extraire des informations?
Comment analyser HTML / XML et en extraire des informations?
Réponses:
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.
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.
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
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.
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 .
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 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.
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 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 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 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 é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 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 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.
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
- 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.
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.
- 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.
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
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é.
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.
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.
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
Si vous voulez dépenser de l'argent, jetez un œil à
Je ne suis pas affilié à PHP Architect ou aux auteurs.
Essayez Simple HTML DOM Parser
// 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>';
// 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;
// Dump contents (without tags) from HTML
echo file_get_html('http://www.google.com/')->plaintext;
// 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);
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é.
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.
<!--
, 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.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.
DOMComment
peut lire les commentaires, donc aucune raison d'utiliser Regex pour cela.
DOM
utilise 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é).
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 #id
et .class
ou DIV
pour ->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
->find("a img, a object, div a")
Simple HTML DOM est un excellent analyseur open-source:
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.
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.
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.
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 .
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.
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>';
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 href
attributs dans les img
balises 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 .
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
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']");
$results
contient 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 $results
ne 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é.
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 é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
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.
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>');
[...]
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.
XML_HTMLSax
est plutôt stable - même s'il n'est plus maintenu. Une autre option pourrait être de vous diriger HTML via Html Tidy , puis de l'analyser avec des outils XML standard.
Le framework Symfony a des bundles qui peuvent analyser le HTML, et vous pouvez utiliser le style CSS pour sélectionner les DOM au lieu d'utiliser XPath .
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:
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 DOMDocument
et ajouter des méthodes querySelectorAll
et des querySelector
mé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 DOMXpath
pour 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.
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');
});
JSON et tableau XML à trois lignes:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Ta da!
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/")));
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;
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.
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;
}