Php kullanarak html img src, başlık ve alt ayıklamak nasıl?

15 Cevap php

Benim web sitesinde bulunan tüm görüntüler başlık ve alternatif gösterimi ile listelendiği bir sayfa oluşturmak istiyorum.

Zaten tüm HTML dosyaları bulmak ve yüklemek için bana biraz programı yazdı, ama şimdi ben bu HTML src, title ve alt ayıklamak için nasıl şaşırıp :

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

Bu bazı regex yapılmalıdır sanırım, ama etiketlerin sırası değişebilir beri, ve ben hepsini ihtiyacı, gerçekten (ben bunu sert karakterini yapabileceği tarafından zarif bir şekilde bu ayrıştırmak için nasıl bilmiyorum karakter yol, ama bu) acı.

15 Cevap

EDIT : now that I know better

Bu tür sorunları çözmek için regexpi kullanıyor a bad idea ve büyük olasılıkla unmaintainable ve güvenilmez kod yol açacaktır. Daha iyi bize bir HTML parser.

Solution With regexp

Bu durumda bu iki parçaya bölmek süreci daha iyidir:

  • Tüm img etiketi almak
  • onların meta ayıklamak

Ben bir XML ayrıştırıcı kullanamazsınız böylece doc sıkı xHTML değildir üstlenecek. ÖRN. Bu web sayfası kaynak kodu ile:

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

[...]
        )

)

Sonra hepimiz img bir döngü ile nitelikleri olsun:

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

        )

   [..]
        )

)

Regexplerin CPU yoğun yüzden bu sayfayı önbelleğe wan olabilir. Eğer önbellek sistemi varsa, ob_start ve yükleme / bir metin dosyasından kaydederek kullanarak kendi çimdik.

How does this stuff work ?

İlk olarak, desen eşleştirme her dize alır ve üçüncü parametre bunu çıkışına bir işlevi preg_ match_ all kullanın.

Regexp'nin:

<img[^>]+>

Biz tüm html web sayfası üzerinde uygulayın. Bu every string that start with "<img> "karakter", non içeriyor "ve a> ile biter olarak okunabilir.

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

Her img etiketinin üzerinde ardışık olarak uygulayın. Bu every string starting with "alt", "title" or "src", then a "=", then a ' " ', a bunch of stuff that are not ' " ' and ends with a ' " '. Isolate the sub-strings between () olarak okunabilir.

Son olarak, her şey size regexplerde ile uğraşmak istiyorum, kullanışlı hızlı bir şekilde test etmek için iyi araçlara sahip. Bu kontrol online regexp tester.

EDIT: ilk yorumuna cevap.

Ben tek tırnak kullanarak (umarım birkaç) insanlar hakkında düşünmüyordu doğrudur.

Peki, sadece kullanırsanız ', sadece tüm "ile değiştirin'.

Eğer her ikisi de katarsanız. "| Yerine ya da ('ve [^ ø] [" ^] yerine) "Birinci sonra kullanmayı deneyin, :-) kendinize tokat gerekir.

Sadece görev için PHP'nin XML işlevlerini kullanarak küçük bir örnek vereyim:

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

Ben bu yöntemi HTML sözdizimi ile başa çıkabilir ve XHTML olmak giriş belgesini zorlamaz çünkü DOMDocument::loadHTML() yöntemini kullandı. Harfiyen dönüşüm konuşan bir SimpleXMLElement gerekli değildir - sadece xpath ve xpath sonuçlarını daha basit kullanarak yapar.

XPath'i kullanabilirsiniz.

Php için, simplexml veya domxml kullanabilirsiniz

ayrıca bkz bu question

XHTML ise, sizin örnek sadece SimpleXML ihtiyacımız var.

<?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);
?>

Çıktı:

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

Script gibi düzenlenmesi gerekir

foreach( $result[0] as $img_tag)

çünkü diziler preg_match_all return array

Bu çözeltiye RE:

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

Nasıl birden fazla dosya / URL'ler gelen etiket ve nitelik alabilirim?

Bunu yapmak benim için işe yaramadı:

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

Bunu yapmak için preg_match kullanılır.

Benim durumumda, ben Wordpress var tam bir <img> etiketi (ve başka hiçbir biçimlendirme) içeren bir dize vardı ve ben bu yüzden çalıştırabilir src nitelik almaya çalışıyordu timthumb aracılığıyla.

// 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);

Başlık veya alt kapmak için desen, sadece $pattern = '/title="([^"]*)"/'; başlık kapmak için veya $pattern = '/title="([^"]*)"/'; alt kapmak için kullanabilirsiniz. Ne yazık ki, benim regex olsa tek pass ile üç (alt / başlık / src) kapmak için yeterince iyi değildir.

İşte çözüm PHP, bir:

Sadece QueryPath indirmek ve daha sonra aşağıdaki gibi yapın:

$doc= qp($myHtmlDoc);

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

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

}

İşte bu, bitirdiniz!

Burada yani anında görüntü etiketi genişlik ve uzunluk özelliklerini ayarlayarak, benzer bir amaç için yukarıdaki bilgilerin hepsi bir araya topallayarak bir PHP işlevi var ... biraz aksak, belki, ama güvenilir bir iş gibi görünüyor:

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;

}

HTML XHTML olmasını garanti durumunda da SimpleXML deneyebilirsiniz - Sizin için biçimlendirme ayrıştırmak ve sadece kendi adıyla özelliklerini erişmek mümkün olacak. (Bu sadece HTML ve XML sözdizimi bağlı değil eğer DOM kütüphaneler de vardır.)

Aşağıdaki kod wordpress benim için çalıştı ...

Bu kod tüm görüntü kaynaklarının ayıklar

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

şerefe!

Sen kullanabilirsiniz simplehtmldom. JQuery seçicileri çoğu simplehtmldom desteklenmektedir. Bir örnek aşağıda verilmiştir

// 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>'; 

Sen tüm img etiketlerini (<img[^>]*>), ve daha sonra kullanmak için bir regexpi yazabilirsiniz basit patlayabilir: $res = explode("\"", $tags), çıktı böyle bir şey olacak:

$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] = "/>";

Eğer patlayabilir önce <img etiketi silerseniz, o zaman formun bir dizi alacak

property=
value

böylece özelliklerin sırası alakasız, sadece sizin gibi ne kullanın.

Sonra (gibi bir şey "<img[^>]*>") img etiketleri bulmak için normal bir ifade kullanarak, ve yaklaşık her img etiketinin için, her öznitelik bulmak için başka bir normal ifadeyi kullanabilirsiniz nasıl.

Belki size etiket çorba ile uğraşıyoruz eğer tırnak orada olmadığı için izin vermek isteyebilirsiniz ama " ([a-zA-Z]+)=\"([^"]*)\"" O gitti ederseniz, parametre adını alabilir ..., özelliklerini bulmak gibi bir şey ve Her maç içinde gruplardan değer.

Belki bu size doğru cevaplar verecektir:

<img.*?(?:(?:\s+(src)="([^"]+)")|(?:\s+(alt)="([^"]+)")|(?:\s+(title)="([^"]+)")|(?:\s+[^\s]+))+.*/>