Comment extraire img src, title et alt de html en utilisant php?

je voudrais créer une page où toutes les images qui résident sur mon site sont énumérées avec le titre et la représentation alternative.

j'ai déjà écrit un petit programme pour trouver et charger tous les fichiers HTML, mais maintenant je suis coincé à la façon d'extraire src , title et 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 certain regex, mais puisque l'ordre des étiquettes peut varier, et j'ai besoin de tous les, je Je ne sais pas vraiment comment analyser cela d'une manière élégante (je pourrais le faire le char dur par char way, mais c'est douloureux).

133
demandé sur Andy Lester 2008-09-26 12:33:05

21 réponses

EDIT : maintenant que je connais mieux

en utilisant regexp pour résoudre ce genre de problème est une mauvaise idée et sera probablement conduire dans le code Impossible à maintenir et non fiable. Mieux utiliser un HTML parser .

Solution Avec regexp

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

  • obtenir toutes les balise img
  • extraire leurs métadonnées

je suppose que votre doc n'est pas XHTML strict Donc vous ne pouvez pas utiliser un analyseur XML. E. G. Avec cette page Web code source:

/* 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)" />

[...]
        )

)

nous obtenons alors 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"
                )

        )

   [..]
        )

)

Regexps sont intensif CPU donc vous pouvez vouloir 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 en chargeant / sauvegardant à partir d'un fichier texte.

Comment ça marche ?

tout d'abord , nous utilisons preg_ match_ all , une fonction qui obtient chaque chaîne correspondant au motif et l'afficher dans son troisième paramètre.

Les expressions régulières :

<img[^>]+>

nous l'appliquons sur toutes les pages Web html. Il peut être lu comme chaque chaîne qui commence par " <img ", contient non " > " char et se termine par un > .

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

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

enfin, chaque fois que vous voulez traiter avec regexps, il est pratique d'avoir de bons outils pour les tester rapidement. Vérifier ce en ligne regexp tester .

EDIT : réponse au premier commentaire.

il est vrai que je n'ai pas pensé aux (Si tout va bien peu) personnes utilisant des citations simples.

bien, si vous utilisez seulement', remplacez tout le 'par'.

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

184
répondu e-satis 2017-05-23 12:03:05
$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');
}
234
répondu karim 2010-12-18 02:32:24

juste pour donner un petit exemple d'utilisation de la fonctionnalité XML de PHP pour la 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é la méthode DOMDocument::loadHTML() parce que cette méthode peut traiter avec 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 - cela rend juste l'utilisation de xpath et les résultats de xpath plus simple.

64
répondu Stefan Gehrig 2008-09-26 10:40:36

utilisez xpath.

pour php vous pouvez utiliser simplexml ou domxml

Voir Aussi ce question

13
répondu yann.kmm 2017-05-23 12:03:05

si C'est XHTML, votre exemple est, 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"
  }
}
8
répondu DreamWerx 2008-09-26 10:30:44

le script doit être édité comme ceci

foreach( $result[0] as $img_tag)

parce que preg_match_all renvoie un tableau de tableaux

5
répondu Bakudan 2010-12-18 02:32:50

RE cette solution:

    $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');
    }

Comment obtenir la balise et l'attribut à partir de plusieurs fichiers/urls?

faire cela n'a pas fonctionné pour moi:

    foreach (glob("path/to/files/*.html") as $html) {

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

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

      foreach ($tags as $tag) {
         echo $tag->getAttribute('src');
      } 
    } 
5
répondu user1312079 2012-08-17 07:02:18

Vous pouvez utiliser simplehtmldom . La plupart des sélecteurs jQuery sont supportés dans simplehtmldom. Un exemple est donné ci-dessous

// Create DOM from URL or file
$html = file_get_html('http://www.google.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>'; 
5
répondu Nauphal 2014-01-27 07:24:20

Voici une fonction PHP que j'ai cliqué ensemble à partir de toutes les informations ci-dessus pour un but similaire, à savoir le réglage de la largeur de l'étiquette d'image et des propriétés de longueur à la volée ... un peu maladroit, peut-être, mais semble fonctionner de manière fiable:

function ReSizeImagesInHTML($HTMLContent,$MaximumWidth,$MaximumHeight) {

// find image tags
preg_match_all('/<img[^>]+>/i',$HTMLContent, $rawimagearray,PREG_SET_ORDER); 

// put image tags in a simpler array
$imagearray = array();
for ($i = 0; $i < count($rawimagearray); $i++) {
    array_push($imagearray, $rawimagearray[$i][0]);
}

// put image attributes in another array
$imageinfo = array();
foreach($imagearray as $img_tag) {

    preg_match_all('/(src|width|height)=("[^"]*")/i',$img_tag, $imageinfo[$img_tag]);
}

// combine everything into one array
$AllImageInfo = array();
foreach($imagearray as $img_tag) {

    $ImageSource = str_replace('"', '', $imageinfo[$img_tag][2][0]);
    $OrignialWidth = str_replace('"', '', $imageinfo[$img_tag][2][1]);
    $OrignialHeight = str_replace('"', '', $imageinfo[$img_tag][2][2]);

    $NewWidth = $OrignialWidth; 
    $NewHeight = $OrignialHeight;
    $AdjustDimensions = "F";

    if($OrignialWidth > $MaximumWidth) { 
        $diff = $OrignialWidth-$MaximumHeight; 
        $percnt_reduced = (($diff/$OrignialWidth)*100); 
        $NewHeight = floor($OrignialHeight-(($percnt_reduced*$OrignialHeight)/100)); 
        $NewWidth = floor($OrignialWidth-$diff); 
        $AdjustDimensions = "T";
    }

    if($OrignialHeight > $MaximumHeight) { 
        $diff = $OrignialHeight-$MaximumWidth; 
        $percnt_reduced = (($diff/$OrignialHeight)*100); 
        $NewWidth = floor($OrignialWidth-(($percnt_reduced*$OrignialWidth)/100)); 
        $NewHeight= floor($OrignialHeight-$diff); 
        $AdjustDimensions = "T";
    } 

    $thisImageInfo = array('OriginalImageTag' => $img_tag , 'ImageSource' => $ImageSource , 'OrignialWidth' => $OrignialWidth , 'OrignialHeight' => $OrignialHeight , 'NewWidth' => $NewWidth , 'NewHeight' => $NewHeight, 'AdjustDimensions' => $AdjustDimensions);
    array_push($AllImageInfo, $thisImageInfo);
}

// build array of before and after tags
$ImageBeforeAndAfter = array();
for ($i = 0; $i < count($AllImageInfo); $i++) {

    if($AllImageInfo[$i]['AdjustDimensions'] == "T") {
        $NewImageTag = str_ireplace('width="' . $AllImageInfo[$i]['OrignialWidth'] . '"', 'width="' . $AllImageInfo[$i]['NewWidth'] . '"', $AllImageInfo[$i]['OriginalImageTag']);
        $NewImageTag = str_ireplace('height="' . $AllImageInfo[$i]['OrignialHeight'] . '"', 'height="' . $AllImageInfo[$i]['NewHeight'] . '"', $NewImageTag);

        $thisImageBeforeAndAfter = array('OriginalImageTag' => $AllImageInfo[$i]['OriginalImageTag'] , 'NewImageTag' => $NewImageTag);
        array_push($ImageBeforeAndAfter, $thisImageBeforeAndAfter);
    }
}

// execute search and replace
for ($i = 0; $i < count($ImageBeforeAndAfter); $i++) {
    $HTMLContent = str_ireplace($ImageBeforeAndAfter[$i]['OriginalImageTag'],$ImageBeforeAndAfter[$i]['NewImageTag'], $HTMLContent);
}

return $HTMLContent;

}
2
répondu John Daliani 2011-11-09 07:57:35

j'ai utilisé preg_match pour le faire.

dans mon cas, j'ai eu une chaîne contenant exactement une étiquette <img> (et aucun autre markup) que J'ai eu de Wordpress et j'ai essayé d'obtenir l'attribut src pour que je puisse l'exécuter à travers timthumb.

// get the featured image
$image = get_the_post_thumbnail($photos[$i]->ID);

// get the src for that image
$pattern = '/src="([^"]*)"/';
preg_match($pattern, $image, $matches);
$src = $matches[1];
unset($matches);

Dans le modèle pour saisir le titre ou la touche alt, vous pouvez simplement utiliser $pattern = '/title="([^"]*)"/'; pour saisir le titre ou $pattern = '/title="([^"]*)"/'; pour saisir la touche alt. Malheureusement, mon regex n'est pas assez bon pour saisir tout trois (alt/title/src) avec une passe.

1
répondu Jazzerus 2010-09-28 16:59:34

vous pouvez également essayer SimpleXML si le HTML est garanti D'être XHTML - il analysera le markup pour vous et vous serez en mesure d'accéder aux attributs juste par leur nom. (Il y a aussi des bibliothèques DOM si C'est juste HTML et que vous ne pouvez pas dépendre de la syntaxe XML.)

0
répondu Borek Bernard 2008-09-26 08:35:35

vous pouvez écrire un regexp pour obtenir toutes les étiquettes img ( <img[^>]*> ), puis utiliser simple explode: $res = explode("\"", $tags) , la sortie sera quelque chose comme ceci:

$res[0] = "<img src=";
$res[1] = "/image/fluffybunny.jpg";
$res[2] = "title=";
$res[3] = "Harvey the bunny";
$res[4] = "alt=";
$res[5] = "a cute little fluffy bunny";
$res[6] = "/>";

si vous supprimez la balise <img avant l'explosion, alors vous obtiendrez un tableau sous la forme de

property=
value

donc l'ordre des propriétés n'est pas pertinent, vous n'utilisez que ce que vous voulez.

0
répondu Biri 2008-09-26 08:49:26

Voici la solution, en PHP:

il suffit de télécharger QueryPath, puis faire comme suit:

$doc= qp($myHtmlDoc);

foreach($doc->xpath('//img') as $img) {

   $src= $img->attr('src');
   $title= $img->attr('title');
   $alt= $img->attr('alt');

}

C'est ça, c'est fini !

0
répondu Xavier 2010-11-13 13:52:25

le code ci-dessous a fonctionné pour moi dans wordpress...

il extrait toutes les sources d'image du code

$search = "any html code with image tags";

preg_match_all( '/src="([^"]*)"/', $search, $matches);

if ( isset( $matches ) )
{
    foreach ($matches as $match) 
    {
        if(strpos($match[0], "src")!==false)
        {
            $res = explode("\"", $match[0]);
            $image = parse_url($res[1], PHP_URL_PATH);
            $xml .= " <image:image>\n";
            $xml .= " <image:loc>".home_url().$image."</image:loc>\n";
            $xml .= " <image:caption>".htmlentities($title)."</image:caption>\n";
            $xml .= " <image:license>".home_url()."</image:license>\n";
            $xml .= " </image:image>\n";
        }
    }
}

santé!

0
répondu foxybagga 2011-02-24 08:38:24
$content =  "<img src='http://google.com/2af5e6ae749d523216f296193ab0b146.jpg' width='40' height='40'>";
$image   =  preg_match_all('~<img rel="imgbot" remote="(.*?)" width="(.*?)" height="(.*?)" linktext="(.*?)" linkhref="(.*?)" src="(.*?)" />~is', $content, $matches);
0
répondu phpdev 2012-10-05 15:26:41

si vous voulez utiliser regEx pourquoi pas aussi facile que ceci:

preg_match_all('% (.*)=\"(.*)\"%Uis', $code, $matches, PREG_SET_ORDER);

ceci retournera quelque chose comme:

array(2) {
    [0]=>
    array(3) {
        [0]=>
        string(10) " src="abc""
        [1]=>
        string(3) "src"
        [2]=>
        string(3) "abc"
    }
    [1]=>
    array(3) {
        [0]=>
        string(10) " bla="123""
        [1]=>
        string(3) "bla"
        [2]=>
        string(3) "123"
    }
}
0
répondu Nico Knoll 2015-02-17 20:08:41

il y a ma solution pour retrouver uniquement des images à partir du contenu de n'importe quel poste wordpress ou html.

$content = get_the_content();
$count = substr_count($content, '<img');
$start = 0;
for ($i=0;$i<$count;$i++) {
  if ($i == 0){
    $imgBeg = strpos($content, '<img', $start);
    $post = substr($content, $imgBeg);
  } else {
    $imgBeg = strpos($post, '<img', $start);
    $post = substr($post, $imgBeg-2);
  }
  $imgEnd = strpos($post, '>');
  $postOutput = substr($post, 0, $imgEnd+1);
  $postOutput = preg_replace('/width="([0-9]*)" height="([0-9]*)"/', '',$postOutput);
  $image[$i] = $postOutput;
  $start= $imgEnd + 1;
} 
print_r($image);

`

0
répondu Jainty Sarraff 2016-02-09 07:56:48
"]+>]+>/)?>"



ceci extraira l'étiquette d'ancrage imbriquée avec l'étiquette d'image

-1
répondu Muhammad Irfan 2010-04-29 06:31:55

pour un élément, vous pouvez utiliser cette solution miniaturisée en utilisant DOMDocument. Gère les guillemets ' et ' et valide également le html. La meilleure pratique consiste à utiliser des bibliothèques existantes plutôt que votre propre solution en utilisant des expressions régulières.

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

$doc = new DOMDocument();
@$doc->loadHTML($html);
$attributeValue = @$doc->documentElement->firstChild->firstChild->attributes->getNamedItem($attribute)->value;

echo $attributeValue;
-1
répondu Wizzard 2017-03-31 10:30:38

Que Diriez-vous d'utiliser une expression régulière pour trouver les étiquettes img (quelque chose comme "<img[^>]*>" ), et puis, pour chaque étiquette img, vous pourriez utiliser une autre expression régulière pour trouver chaque attribut.

peut-être quelque chose comme " ([a-zA-Z]+)=\"([^"]*)\"" pour trouver les attributs, bien que vous pourriez vouloir permettre aux citations n'étant pas là si vous avez affaire à la soupe d'étiquette... Si vous allez avec cela, vous pouvez obtenir le nom du paramètre et la valeur des groupes dans chaque match.

-2
répondu MB. 2008-09-26 08:47:22

Peut-être que cela vous donnera les bonnes réponses :

<img.*?(?:(?:\s+(src)="([^"]+)")|(?:\s+(alt)="([^"]+)")|(?:\s+(title)="([^"]+)")|(?:\s+[^\s]+))+.*/> 
-2
répondu Levi 2011-03-09 13:05:33