Cómo extraer img src, title y alt de html usando php?


Me gustaría crear una página donde todas las imágenes que residen en mi sitio web se enumeran con el título y la representación alternativa.

Ya me escribí un pequeño programa para encontrar y cargar todos los archivos HTML, pero ahora estoy atascado en cómo extraer src, title y alt de este HTML:

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

Supongo que esto debería hacerse con algunas expresiones regulares, pero como el orden de las etiquetas puede variar, y necesito todas, realmente no sé cómo analizar esto de una manera elegante (podría hacerlo el duro char por char manera, pero eso es doloroso).

Author: Andy Lester, 2008-09-26

21 answers

EDITAR: ahora que sé mejor

Usar regexp para resolver este tipo de problemas es una mala idea y probablemente conducirá a un código inalcanzable y poco fiable. Es mejor usar un analizador HTML .

Solución Con regexp

En ese caso es mejor dividir el proceso en dos partes :

  • obtener toda la etiqueta img
  • extraer sus metadatos

Asumiré que su documento no es estricto con xHTML, por lo que no puede usar un analizador XML. Por ejemplo, con código fuente de esta página 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)" />

[...]
        )

)

Luego obtenemos todos los atributos de la etiqueta img con un bucle:

$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"
                )

        )

   [..]
        )

)

Las expresiones regulares son intensivas en CPU, por lo que es posible que desee almacenar en caché esta página. Si no tiene un sistema de caché, puede modificar el suyo utilizando ob_start y cargando / guardando desde un archivo de texto.

¿Cómo funciona esto ?

Primero, usamos preg_ match_ all , una función que obtiene cada cadena que coincide con el patrón y lo genera en su tercera parámetro.

Las expresiones regulares:

<img[^>]+>

Lo aplicamos en todas las páginas web html. Se puede leer como cada cadena que comienza con "<img", contiene caracteres no ">" y termina con un >.

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

Lo aplicamos sucesivamente en cada etiqueta img. Se puede leer como cada cadena que comienza con "alt", "title" o "src", luego un "=", luego un '" ', un montón de cosas que no son '"'y termina con un '" '. Aísla las sub-cadenas entre () .

Finalmente, cada vez si desea lidiar con las expresiones regulares, es útil tener buenas herramientas para probarlas rápidamente. Compruebe este probador de expresiones regulares en línea.

EDITAR : respuesta al primer comentario.

Es cierto que no pensé en las (esperemos que pocas) personas que usan comillas simples.

Bueno, si solo usas ', simplemente reemplaza todo el " por '.

Si mezcla ambos. Primero debes abofetearte: -), luego intenta usar ( " | ') en su lugar o " y [^ø] para reemplazar [^"].

 184
Author: e-satis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Author: karim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-18 02:32:24

Solo para dar un pequeño ejemplo de uso de la funcionalidad XML de PHP para la tarea:

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

Usé el método DOMDocument::loadHTML() porque este método puede hacer frente a la sintaxis HTML y no obliga al documento de entrada a ser XHTML. Estrictamente hablando, la conversión a SimpleXMLElement no es necesaria, solo hace que el uso de xpath y los resultados de xpath sean más simples.

 64
Author: Stefan Gehrig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 10:40:36

Use xpath.

Para php puedes usar simplexml o domxml

Ver también esta pregunta

 13
Author: yann.kmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:03:05

Si es XHTML, su ejemplo es, solo necesita 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);
?>

Salida:

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
Author: DreamWerx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 10:30:44

El script debe ser editado así

foreach( $result[0] as $img_tag)

Porque preg_match_all devuelve matriz de matrices

 5
Author: Bakudan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-18 02:32:50

CON respecto a esta solución:

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

¿Cómo se obtiene la etiqueta y el atributo de varios archivos/URL?

Hacer esto no funcionó para mí:

    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
Author: user1312079,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-17 07:02:18

Puede usar simplehtmldom. La mayoría de los selectores jQuery son compatibles con simplehtmldom. A continuación se da un ejemplo

// 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
Author: Nauphal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-27 07:24:20

Aquí está Una función PHP que cojeé de toda la información anterior para un propósito similar, a saber, ajustar el ancho de la etiqueta de imagen y las propiedades de longitud sobre la marcha ... un poco torpe, tal vez, pero parece funcionar de manera confiable:

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
Author: John Daliani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-09 07:57:35

Usé preg_match para hacerlo.

En mi caso, tenía una cadena que contenía exactamente una etiqueta <img> (y ningún otro marcado) que obtuve de Wordpress y estaba tratando de obtener el atributo src para poder ejecutarlo a través de 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);

En el patrón para tomar el título o el alt, simplemente puedes usar $pattern = '/title="([^"]*)"/'; para tomar el título o $pattern = '/title="([^"]*)"/'; para agarrar la alt. Lamentablemente, mi regex no es lo suficientemente bueno para agarrar los tres (alt/title/src) con una sola pasada.

 1
Author: Jazzerus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-28 16:59:34

También puede probar SimpleXML si se garantiza que el HTML sea XHTML - analizará el marcado por usted y podrá acceder a los atributos solo por su nombre. (También hay bibliotecas DOM si es solo HTML y no puede depender de la sintaxis XML.)

 0
Author: Borek Bernard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 08:35:35

Puede escribir una expresión regular para obtener todas las etiquetas img (<img[^>]*>), y luego usar simple explode: $res = explode("\"", $tags), la salida será algo como esto:

$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 elimina la etiqueta <img antes de la explosión, obtendrá una matriz en forma de

property=
value

Así que el orden de las propiedades es irrelevante, solo usa lo que te guste.

 0
Author: Biri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 08:49:26

Aquí está LA solución, en PHP:

Simplemente descargue QueryPath, y luego haga lo siguiente:

$doc= qp($myHtmlDoc);

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

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

}

Eso es todo, ¡ya está !

 0
Author: Xavier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-13 13:52:25

El siguiente código funcionó para mí en wordpress...

Extrae todas las fuentes de imagen del código

$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";
        }
    }
}

Salud!

 0
Author: foxybagga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Author: phpdev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-05 15:26:41

Si desea utilizar regEx por qué no tan fácil como esto:

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

Esto devolverá algo como:

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
Author: Nico Knoll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-17 20:08:41

Existe mi solución para recuperar solo imágenes del contenido de cualquier publicación en wordpress o contenido 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
Author: Jainty Sarraff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-09 07:56:48
"]+>]+>/)?>"


esto extraerá la etiqueta de anclaje anidada con la etiqueta de imagen

 -1
Author: Muhammad Irfan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-29 06:31:55

Para un elemento puede usar esta solución minificada usando DOMDocument. Maneja las comillas ' y " y también valida el html. La mejor práctica es utilizar bibliotecas existentes en lugar de su propia solución utilizando expresiones regulares.

$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
Author: Wizzard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-31 10:30:38

Qué tal usar una expresión regular para encontrar las etiquetas img (algo así como "<img[^>]*>"), y luego, para cada etiqueta img, podría usar otra expresión regular para encontrar cada atributo.

Tal vez algo como " ([a-zA-Z]+)=\"([^"]*)\"" para encontrar los atributos, aunque es posible que desee permitir que las comillas no estén allí si se trata de sopa de etiquetas... Si usted fue con eso, usted podría obtener el nombre del parámetro y el valor de los grupos dentro de cada partido.

 -2
Author: MB.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-26 08:47:22

Tal vez esto le dará las respuestas correctas :

<img.*?(?:(?:\s+(src)="([^"]+)")|(?:\s+(alt)="([^"]+)")|(?:\s+(title)="([^"]+)")|(?:\s+[^\s]+))+.*/> 
 -2
Author: Levi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-09 13:05:33