Laisser un commentaire

Extraire des informations du DOM en php

Il arrive que l’on soit amené à rechercher des informations dans un fichier HTML ou XML. Si on parcourt des pages web à la recherche d’une information précise, telle qu’une adresse email par exemple, il va falloir extraire cette information du reste du code de la page. On peut faire cela principalement de deux manières : soit en utilisant les expressions rationelles, soit en utilisant le DOM xpath de PHP. Cette dernière solution s’avère très puissante et efficace. D’autant plus si l’on sait où se trouve l’information dans le DOM, elle aura aussi l’avantage d’être plus rapide – autant en vitesse d’exécution qu’en temps de développement.

xpath permet d’effectuer des recherches dans un arbre XML, donc l’HTML. La classe xpath a de multiples fonctions, nous verrons ici seulement la méthode query, qui permet d’effectuer des recherches dans l’arbre.

xpath est très puissant, notamment lorsqu’il s’agit de récupérer des informations localisées dans le DOM HTML, cependant, si vous ne savez pas où se situent les informations, ou pour exécuter des recherches ailleurs que dans le DOM, vous pouvez tirer parti des expressions rationnelles, alias REGEX.

La requete xpath suivante sélectionne l’ensemble des éléments du body :

//body

// permet de sélectionner un élément indépendamment de ce qu’il y a avant, c’est donc une adresse relative. Si on veut sélectionner l’ensemble des div de la page, on fera :

//body/div
//div

Ces deux requêtes sont dans ce cadre similaires puisque la première demande “toutes les div qui ont body pour parent” et la seconde demande “toutes les div de la page”. Dans le même principe, si l’on veut par exemple tous les textes des liens d’une liste (à savoir <li><a href="#">texte</a>) :

//li/a

Précisons un peu les choses ! Nous voudrions maintenant récupérer les textes des liens d’une liste qui ont la classe “test” :

//li/a[@class='test']

Il en va de même pour tous les attributs. Si l’on veut récupérer un contenu selon son attribut title, on fera a[@title='le titre'].

Puisque nous parlons d’attributs, si nous voulons maintenant mettre la main sur l’adresse du lien (donc son href) et non le texte, voici comment nous procéderions :

//li/a/@href

Il y a encore une petite chose qui est bien pratique au niveau des requêtes. Si nous voulons trouver la quatrième li d’une ul, voilà comment on peut procéder :

//ul/li[4]

Maintenant que nous savons créer les requêtes, voyons comment tout cela prend forme en php. La fonction query de xpath retourne un nœud dom, même s’il est vide.

$html = new DOMDocument();
@$html->loadHtmlFile('http://buzut.fr/extraire-des-informations-du-dom-en-php/');
$xpath = new DOMXPath($html);
$domExemple = $xpath->query("//pre");

$i = 0;
foreach ($domExemple as $exemple) {
    $result[$i++] = $exemple->nodeValue;
}

Sachez qu’il est également possible de charger du HTML directement depuis une variable, on utilisera pour ça loadHTML. Il est d’ailleurs souvent préférable de récupérer le HTML avec curl qui est bien plus puissant (loadHtmlFile échoue souvent). Petit exemple avec curl :

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$raw = curl_exec($ch);
curl_close($ch);

$html = new DOMDocument();
@$html->loadHTML($raw);
$xpath = new DOMXPath($html);
$domExemple = $xpath->query("//pre");

$i = 0;
foreach ($domExemple as $exemple) {
    $result[$i++] = $exemple->nodeValue;
}

$result contient maintenant un tableau de tous les blocs de codes d’exemple de cet article. Vous notez que $domExemple est un objet de type DOMNodeList. Pour en récupérer le contenu, on fait donc une boucle et on récupère donc le contenu de chacun des nœuds via la méthode nodeValue.

Vous n’avez rien de plus à savoir pour récupérer la plupart des contenus sur les pages web !

Commentaires

Rejoignez la discussion !

Vous pouvez utiliser Markdown pour les liens [ancre de lien](url), la mise en *italique* et en **gras**. Enfin pour le code, vous pouvez utiliser la syntaxe `inline` et la syntaxe bloc

```
ceci est un bloc
de code
```