¿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 título y representación alternativa.

Ya me escribí un pequeño progtwig para buscar 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 dado que el orden de las tags puede variar, y las necesito todas, realmente no sé cómo analizarlas de una manera elegante (podría hacerlo el tema difícil por char, pero eso es doloroso).

EDITAR: ahora que sé mejor

Usar la expresión regular para resolver este tipo de problema es una mala idea y es probable que conduzca a un código inmanejable y poco confiable. 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 en xHTML, por lo que no puede usar un analizador XML. EG con este código fuente de la 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('/]+>/i',$html, $result); print_r($result); Array ( [0] => Array ( [0] => logo link to homepage [1] => vote up [2] => vote down [3] => gravatar image [4] => vote up [...] ) ) 

Luego obtenemos todos los atributos de 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 ( [logo link to homepage] => Array ( [0] => Array ( [0] => src="https://stackoverflow.com/Content/Img/stackoverflow-logo-250.png" [1] => alt="logo link to homepage" ) [1] => Array ( [0] => src [1] => alt ) [2] => Array ( [0] => "https://stackoverflow.com/Content/Img/stackoverflow-logo-250.png" [1] => "logo link to homepage" ) ) [vote up] => Array ( [0] => Array ( [0] => src="https://stackoverflow.com/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] => "https://stackoverflow.com/content/img/vote-arrow-up.png" [1] => "vote up" [2] => "This was helpful (click again to undo)" ) ) [vote down] => Array ( [0] => Array ( [0] => src="https://stackoverflow.com/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] => "https://stackoverflow.com/content/img/vote-arrow-down.png" [1] => "vote down" [2] => "This was not helpful (click again to undo)" ) ) [gravatar image] => Array ( [0] => Array ( [0] => src="http://img.rephp.com/php/df299babc56f0a79678e567e87a09c31.jpeg" [1] => alt="gravatar image" ) [1] => Array ( [0] => src [1] => alt ) [2] => Array ( [0] => "http://img.rephp.com/php/df299babc56f0a79678e567e87a09c31.jpeg" [1] => "gravatar image" ) ) [..] ) ) 

Las expresiones regulares requieren una gran cantidad de 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 coloca en su tercer parámetro.

Las expresiones regulares:

 ]+> 

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

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

Lo aplicamos sucesivamente en cada etiqueta img. Se puede leer como cada cadena que comience por "alt", "title" o "src", luego como "=", luego como '' '', como un montón de cosas que no son '' '' y termina con '' '' ''. . Aislar las subcadenas entre () .

Finalmente, cada vez que desee tratar con expresiones regulares, es útil tener buenas herramientas para probarlas rápidamente. Verifique este probador de expresiones regulares en línea .

EDIT: respuesta al primer comentario.

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

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

Si mezclas ambos Primero debe abofetearlo a usted mismo :-), luego intente usar ("| ') en su lugar o" y [^ ø] para reemplazar [^ "].

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

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

 $doc=new DOMDocument(); $doc->loadHTML("Test
\"alt\"/"); $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']; }

Utilicé el DOMDocument::loadHTML() porque este método puede manejar la syntax HTML y no obliga a que el documento de entrada sea XHTML. Estrictamente hablando, la conversión a SimpleXMLElement no es necesaria, simplemente hace que usar xpath y los resultados de xpath sean más simples.

Use xpath.

Para php puedes usar simplexml o domxml

ver también esta pregunta

Si es XHTML, su ejemplo es que solo necesita XML simple.

 '; $sx = simplexml_load_string($input); var_dump($sx); ?> 

Salida:

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

El script debe editarse así

foreach( $result[0] as $img_tag)

porque preg_match_all devuelve una matriz de matrices

RE 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 múltiples 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'); } } 

Puedes usar simplehtmldom . La mayoría de los selectores jQuery son compatibles en simplehtmldom. Un ejemplo se da a continuación

 // 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 . '
'; // Find all links foreach($html->find('a') as $element) echo $element->href . '
';

Aquí hay una función de PHP Cojeé juntos de toda la información anterior para un propósito similar, es decir, ajustar el ancho y las propiedades de la etiqueta de la imagen 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('/]+>/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; } 

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

Puede escribir una expresión regular para obtener todas las tags img ( ]*> ), y luego usar simple explotar: $res = explode("\"", $tags) , el resultado será algo como esto:

 $res[0] = " 

Si elimina la etiqueta antes de la explosión, obtendrá una matriz en forma de

 property= value 

por lo que el orden de las propiedades es irrelevante, solo utiliza lo que le gustará.

Usé preg_match para hacerlo.

En mi caso, tenía una cadena que contenía exactamente una etiqueta (y ninguna otra marca) 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 obtener el título o alt, simplemente puede usar $pattern = '/title="([^"]*)"/'; para tomar el título o $pattern = '/title="([^"]*)"/'; agarrar el alt. Tristemente, mi expresión regular no es lo suficientemente buena para agarrar los tres (alt / title / src) con un pase.

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, ¡listo!

el siguiente código funcionó para mí en wordpress …

extrae todas las fonts 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 .= " \n"; $xml .= " ".home_url().$image."\n"; $xml .= " ".htmlentities($title)."\n"; $xml .= " ".home_url()."\n"; $xml .= " \n"; } } } 

¡aclamaciones!

 $content = ""; $image = preg_match_all('~~is', $content, $matches); 

Si desea usar regEx, ¿por qué no tan fácil como esto?

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

Esto devolverá algo así 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" } } 

Existe mi solución para recuperar solo imágenes del contenido de cualquier publicación en contenido wordpress o html. `

 $content = get_the_content(); $count = substr_count($content, ''); $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); 

`

  "] +>] +> /)?>" 

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

para un elemento, puede usar esta solución minimizada usando DOMDocument. Maneja las comillas ‘y’ y también valida el html. La mejor práctica es usar bibliotecas existentes en lugar de su propia solución usando expresiones regulares.

 $html = 'a cute little fluffy bunny'; $attribute = 'src'; $doc = new DOMDocument(); @$doc->loadHTML($html); $attributeValue = @$doc->documentElement->firstChild->firstChild->attributes->getNamedItem($attribute)->value; echo $attributeValue; 

¿Qué le parece usar una expresión regular para encontrar las tags img (algo así como "]*>" ), y luego, para cada etiqueta img, puede usar otra expresión regular para buscar 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 una etiqueta sopa … Si fuera así, podría obtener el nombre del parámetro y el valor de los grupos dentro de cada coincidencia.

Tal vez esto te dará las respuestas correctas: