159 votes

Comment extraire l'image src, le titre et l'alt du html en utilisant php ?

Je voudrais créer une page où toutes les images qui se trouvent sur mon site Web sont répertoriées avec leur titre et leur représentation alternative.

J'ai déjà écrit un petit programme pour trouver et charger tous les fichiers HTML, mais maintenant je suis coincé sur la façon d'extraire src , title y alt de ce HTML :

<img src="/image/fluffybunny.jpg" title="Harvey the bunny" alt="a cute little fluffy bunny" />

Je suppose que cela devrait être fait avec un regex, mais comme l'ordre des balises peut varier, et que j'ai besoin de toutes les balises, je ne sais pas vraiment comment analyser cela de manière élégante (je pourrais le faire de manière difficile, char par char, mais c'est pénible).

1 votes

264voto

karim Points 1091
$url="http://example.com";

$html = file_get_contents($url);

$doc = new DOMDocument();
@$doc->loadHTML($html);

$tags = $doc->getElementsByTagName('img');

foreach ($tags as $tag) {
       echo $tag->getAttribute('src');
}

0 votes

Je suis curieux de savoir si cela fonctionne plus vite que preg_match

5 votes

J'adore la facilité avec laquelle on peut le lire ! xpath et regex fonctionnent aussi mais ce n'est jamais aussi facile à lire 18 mois plus tard.

1 votes

Bien que court et simple, c'est un énorme gaspillage de ressources... utiliser DOMDocument pour extraire les attributs d'une balise représente beaucoup ( !!!) de frais généraux.

210voto

e-satis Points 146299

EDIT : maintenant que je sais mieux

L'utilisation de regexp pour résoudre ce genre de problème est une mauvaise idée et conduira probablement à un code non maintenu et non fiable. Mieux vaut utiliser un Analyseur HTML .

Solution avec regexp

Dans ce cas, il est préférable de diviser le processus en deux parties :

  • récupérer toutes les balises img
  • extraire leurs métadonnées

Je suppose que votre document n'est pas strict xHTML et que vous ne pouvez donc pas utiliser un analyseur XML. Par exemple, avec le code source de cette page web :

/* preg_match_all match the regexp in all the $html string and output everything as 
an array in $result. "i" option is used to make it case insensitive */

preg_match_all('/<img[^>]+>/i',$html, $result); 

print_r($result);
Array
(
    [0] => Array
        (
            [0] => <img src="/Content/Img/stackoverflow-logo-250.png" width="250" height="70" alt="logo link to homepage" />
            [1] => <img class="vote-up" src="/content/img/vote-arrow-up.png" alt="vote up" title="This was helpful (click again to undo)" />
            [2] => <img class="vote-down" src="/content/img/vote-arrow-down.png" alt="vote down" title="This was not helpful (click again to undo)" />
            [3] => <img src="http://www.gravatar.com/avatar/df299babc56f0a79678e567e87a09c31?s=32&d=identicon&r=PG" height=32 width=32 alt="gravatar image" />
            [4] => <img class="vote-up" src="/content/img/vote-arrow-up.png" alt="vote up" title="This was helpful (click again to undo)" />

[...]
        )

)

Ensuite, nous récupérons tous les attributs de la balise img avec une boucle :

$img = array();
foreach( $result as $img_tag)
{
    preg_match_all('/(alt|title|src)=("[^"]*")/i',$img_tag, $img[$img_tag]);
}

print_r($img);

Array
(
    [<img src="/Content/Img/stackoverflow-logo-250.png" width="250" height="70" alt="logo link to homepage" />] => Array
        (
            [0] => Array
                (
                    [0] => src="/Content/Img/stackoverflow-logo-250.png"
                    [1] => alt="logo link to homepage"
                )

            [1] => Array
                (
                    [0] => src
                    [1] => alt
                )

            [2] => Array
                (
                    [0] => "/Content/Img/stackoverflow-logo-250.png"
                    [1] => "logo link to homepage"
                )

        )

    [<img class="vote-up" src="/content/img/vote-arrow-up.png" alt="vote up" title="This was helpful (click again to undo)" />] => Array
        (
            [0] => Array
                (
                    [0] => src="/content/img/vote-arrow-up.png"
                    [1] => alt="vote up"
                    [2] => title="This was helpful (click again to undo)"
                )

            [1] => Array
                (
                    [0] => src
                    [1] => alt
                    [2] => title
                )

            [2] => Array
                (
                    [0] => "/content/img/vote-arrow-up.png"
                    [1] => "vote up"
                    [2] => "This was helpful (click again to undo)"
                )

        )

    [<img class="vote-down" src="/content/img/vote-arrow-down.png" alt="vote down" title="This was not helpful (click again to undo)" />] => Array
        (
            [0] => Array
                (
                    [0] => src="/content/img/vote-arrow-down.png"
                    [1] => alt="vote down"
                    [2] => title="This was not helpful (click again to undo)"
                )

            [1] => Array
                (
                    [0] => src
                    [1] => alt
                    [2] => title
                )

            [2] => Array
                (
                    [0] => "/content/img/vote-arrow-down.png"
                    [1] => "vote down"
                    [2] => "This was not helpful (click again to undo)"
                )

        )

    [<img src="http://www.gravatar.com/avatar/df299babc56f0a79678e567e87a09c31?s=32&d=identicon&r=PG" height=32 width=32 alt="gravatar image" />] => Array
        (
            [0] => Array
                (
                    [0] => src="http://www.gravatar.com/avatar/df299babc56f0a79678e567e87a09c31?s=32&d=identicon&r=PG"
                    [1] => alt="gravatar image"
                )

            [1] => Array
                (
                    [0] => src
                    [1] => alt
                )

            [2] => Array
                (
                    [0] => "http://www.gravatar.com/avatar/df299babc56f0a79678e567e87a09c31?s=32&d=identicon&r=PG"
                    [1] => "gravatar image"
                )

        )

   [..]
        )

)

Les regexps sont gourmands en ressources CPU, vous pouvez donc mettre cette page en cache. Si vous n'avez pas de système de cache, vous pouvez modifier le vôtre en utilisant ob_start et le chargement/la sauvegarde à partir d'un fichier texte.

Comment ce truc fonctionne-t-il ?

Tout d'abord, nous utilisons preg_ match_ all une fonction qui récupère toutes les chaînes de caractères correspondant au motif et les renvoie dans son troisième paramètre.

Les regexps :

<img[^>]+>

Nous l'appliquons sur toutes les pages web html. Il peut être lu comme suit chaque chaîne qui commence par " <img ", contient un caractère non ">" et se termine par un >. .

(alt|title|src)=("[^"]*")

Nous l'appliquons successivement sur chaque balise img. Il peut être lu comme suit chaque chaîne de caractères commençant par "alt", "title" ou "src", puis un "=", puis un " ". ', un tas de choses qui ne sont pas ' " ' et se termine par un ' " '. Isolez les sous-chaînes entre () .

Enfin, chaque fois que vous voulez traiter des regexps, il est pratique d'avoir de bons outils pour les tester rapidement. Regardez ceci Testeur de regexp en ligne .

EDIT : réponse au premier commentaire.

Il est vrai que je n'ai pas pensé aux (rares, je l'espère) personnes qui utilisent des guillemets simples.

Si vous utilisez uniquement ', remplacez simplement tous les " par '.

Si vous mélangez les deux. Vous devriez d'abord vous gifler :-), puis essayer d'utiliser ("|') à la place de " et [^ø] pour remplacer [^"].

0 votes

Le seul problème, ce sont les guillemets simples : <img src='picture.jpg'/> ne fonctionnera pas, l'expression rationnelle s'attend toujours à ".

0 votes

Tre mon ami. J'ai ajouté une note à ce sujet. Merci.

1 votes

Je ne recommanderais PAS de faire défiler les pages (ok, faites défiler pour vérifier) : bien que le code semble simple et est donc tentant pour les gens à utiliser, DOMDocument a tellement d'overhead quand vous voulez juste avoir les attributs d'une balise...

67voto

Stefan Gehrig Points 47227

Pour donner un petit exemple de l'utilisation de la fonctionnalité XML de PHP pour cette tâche :

$doc=new DOMDocument();
$doc->loadHTML("<html><body>Test<br><img src=\"myimage.jpg\" title=\"title\" alt=\"alt\"></body></html>");
$xml=simplexml_import_dom($doc); // just to make xpath more simple
$images=$xml->xpath('//img');
foreach ($images as $img) {
    echo $img['src'] . ' ' . $img['alt'] . ' ' . $img['title'];
}

J'ai utilisé le DOMDocument::loadHTML() car cette méthode peut gérer la syntaxe HTML et ne force pas le document d'entrée à être XHTML. Strictement parlant, la conversion en SimpleXMLElement n'est pas nécessaire - elle rend simplement l'utilisation de xpath et des résultats de xpath plus simple.

1 votes

Cette approche est certainement très simple, mais quelqu'un pourrait vouloir utiliser le signe @ lors de l'appel de la méthode loadHTML (@$doc->loadHTML) car cela empêcherait l'apparition d'avertissements.

1 votes

Appelez cette fonction à l'avance pour gérer les erreurs avec élégance : libxml_use_internal_errors( true ); . Vous pouvez également boucler sur ces erreurs XML avec libxml_get_errors()

13voto

yann.kmm Points 751

Utilisez xpath.

Pour php, vous pouvez utiliser simplexml o domxml

voir également ceci question

9voto

DreamWerx Points 1857

Si c'est du XHTML, comme votre exemple, vous n'avez besoin que de simpleXML.

<?php
$input = '<img src="/image/fluffybunny.jpg" title="Harvey the bunny" alt="a cute little fluffy bunny"/>';
$sx = simplexml_load_string($input);
var_dump($sx);
?>

Sortie :

object(SimpleXMLElement)#1 (1) {
  ["@attributes"]=>
  array(3) {
    ["src"]=>
    string(22) "/image/fluffybunny.jpg"
    ["title"]=>
    string(16) "Harvey the bunny"
    ["alt"]=>
    string(26) "a cute little fluffy bunny"
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X