سؤال

أرغب في إنشاء صفحة يتم فيها إدراج جميع الصور الموجودة على موقع الويب الخاص بي مع العنوان والتمثيل البديل.

لقد كتبت لي بالفعل برنامجًا صغيرًا للعثور على جميع ملفات HTML وتحميلها، لكنني الآن عالق في كيفية استخراجها src, title و alt من HTML هذا:

<img src="/image/fluffybunny.jpg" عنوان="Harvey the bunny" بديل="a cute little fluffy bunny" />

أعتقد أنه يجب أن يتم ذلك باستخدام بعض التعابير العادية، ولكن نظرًا لأن ترتيب العلامات قد يختلف، وأحتاج إليها جميعًا، لا أعرف حقًا كيفية تحليل هذا بطريقة أنيقة (يمكنني القيام بذلك باستخدام الحرف الصعب طريقة شار، ولكن هذا مؤلم).

هل كانت مفيدة؟

المحلول

يحرر :الآن بعد أن أعرف أفضل

استخدام regexp لحل هذا النوع من المشاكل هو فكرة سيئة ومن المحتمل أن يؤدي ذلك إلى تعليمات برمجية لا يمكن صيانتها وغير موثوقة.من الأفضل استخدام محلل HTML.

الحل مع regexp

في هذه الحالة من الأفضل تقسيم العملية إلى قسمين:

  • الحصول على كل علامة img
  • استخراج البيانات الوصفية الخاصة بهم

سأفترض أن المستند الخاص بك ليس صارمًا xHTML لذا لا يمكنك استخدام محلل XML.على سبيل المثال.باستخدام كود مصدر صفحة الويب هذا:

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

[...]
        )

)

ثم نحصل على جميع سمات علامة img باستخدام حلقة:

$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 مكثفة لوحدة المعالجة المركزية (CPU)، لذا قد ترغب في تخزين هذه الصفحة مؤقتًا.إذا لم يكن لديك نظام ذاكرة تخزين مؤقت، فيمكنك تعديل نظامك الخاص باستخدام ob_start والتحميل/الحفظ من ملف نصي.

كيف تعمل هذه الأشياء؟

أولا نستخدم preg_match_all, ، دالة تحصل على كل سلسلة مطابقة للنمط وتخرجها في المعلمة الثالثة الخاصة بها.

التعبيرات العادية :

<img[^>]+>

نحن نطبقه على جميع صفحات الويب بتنسيق html.يمكن قراءتها على أنها كل سلسلة تبدأ بـ "<img"، يحتوي على حرف غير ">" وينتهي بـ >.

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

ونطبقه تباعًا على كل علامة img.يمكن قراءتها على أنها كل سلسلة تبدأ بـ "alt" أو "title" أو "src"، ثم "="، ثم ' " '، وهي مجموعة من العناصر التي ليست ' " ' وتنتهي بـ ' " '.عزل السلاسل الفرعية بين ().

أخيرًا، في كل مرة تريد فيها التعامل مع التعبيرات العادية، من المفيد أن يكون لديك أدوات جيدة لاختبارها بسرعة.افحص هذا اختبار التعبير العادي عبر الإنترنت.

يحرر :الرد على التعليق الأول.

صحيح أنني لم أفكر في الأشخاص (آمل أن يكونوا قليلين) الذين يستخدمون علامات الاقتباس المفردة.

حسنًا، إذا كنت تستخدم "" فقط، فما عليك سوى استبدال كل "بواسطة".

إذا قمت بخلط كليهما.عليك أولاً أن تصفع نفسك :-)، ثم حاول استخدام ("|') بدلاً من ذلك أو " و [^ø] لاستبدال [^"].

نصائح أخرى

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

فقط لإعطاء مثال صغير لاستخدام وظيفة XML الخاصة بـ PHP للمهمة:

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

لقد استخدمت DOMDocument::loadHTML() لأن هذه الطريقة يمكنها التعامل مع بناء جملة HTML ولا تجبر مستند الإدخال على أن يكون XHTML.بالمعنى الدقيق للكلمة التحويل إلى أ SimpleXMLElement ليس ضروريًا - فهو يجعل استخدام xpath ونتائج xpath أكثر بساطة.

إذا كان XHTML، فمثالك هو أنك تحتاج فقط إلى 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);
?>

انتاج:

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

يجب تحرير البرنامج النصي مثل هذا

foreach( $result[0] as $img_tag)

لأن preg_match_all يُرجع مجموعة من المصفوفات

يمكنك استخدام com.simplehtmldom.معظم محددات jQuery مدعومة بلغة Simplehtmldom.وفيما يلي مثال على ذلك

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

لقد استخدمت preg_match للقيام بذلك.

في حالتي، كان لدي سلسلة تحتوي على واحدة بالضبط <img> العلامة (وليس أي علامة أخرى) التي حصلت عليها من Wordpress وكنت أحاول الحصول على src السمة حتى أتمكن من تشغيلها من خلال 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);

في نمط الحصول على العنوان أو البديل، يمكنك ببساطة استخدامه $pattern = '/title="([^"]*)"/'; للحصول على اللقب أو $pattern = '/title="([^"]*)"/'; للاستيلاء على البديل.للأسف، التعبير العادي الخاص بي ليس جيدًا بما يكفي للاستيلاء على الثلاثة (alt/title/src) بتمريرة واحدة.

إليك وظيفة PHP قمت بجمعها معًا من جميع المعلومات المذكورة أعلاه لغرض مماثل، وهو ضبط خصائص عرض علامة الصورة وطولها بسرعة ...ربما تكون قديمة بعض الشيء، ولكن يبدو أنها تعمل بشكل يمكن الاعتماد عليه:

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;

}

إليك الحل بلغة PHP:

فقط قم بتحميل QueryPath، ثم قم بما يلي:

$doc= qp($myHtmlDoc);

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

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

}

هذا كل شيء، لقد انتهيت!

لقد قرأت العديد من التعليقات على هذه الصفحة التي تشكو من أن استخدام محلل dom هو عبء غير ضروري.حسنًا، قد يكون الأمر أكثر تكلفة من مجرد استدعاء regex، لكن OP ذكر أنه لا يوجد تحكم في ترتيب السمات في علامات img.تؤدي هذه الحقيقة إلى الإلتواء غير الضروري لنمط regex.علاوة على ذلك، يوفر استخدام محلل dom فوائد إضافية تتمثل في سهولة القراءة وقابلية الصيانة والوعي بـ dom (التعبير العادي ليس على دراية بـ dom).

أنا أحب التعبير العادي وأجيب على الكثير من أسئلة التعبير العادي، ولكن عند التعامل مع HTML صالح، نادرًا ما يكون هناك سبب وجيه لاستخدام التعبير العادي بدلاً من المحلل اللغوي.

في العرض التوضيحي أدناه، انظر كيف يتعامل DOMDocument بسهولة ووضوح مع سمات علامة img بأي ترتيب مع مزيج من الاقتباس (وعدم الاقتباس على الإطلاق).لاحظ أيضًا أن العلامات التي لا تحتوي على سمة مستهدفة ليست مزعجة على الإطلاق - يتم توفير سلسلة فارغة كقيمة.

شفرة:(تجريبي)

$test = <<<HTML
<img src="/image/fluffybunny.jpg" title="Harvey the bunny" alt="a cute little fluffy bunny" />
<img src='/image/pricklycactus.jpg' title='Roger the cactus' alt='a big green prickly cactus' />
<p>This is irrelevant text.</p>
<img alt="an annoying white cockatoo" title="Polly the cockatoo" src="/image/noisycockatoo.jpg">
<img title=something src=somethingelse>
HTML;

libxml_use_internal_errors(true);  // silences/forgives complaints from the parser (remove to see what is generated)
$dom = new DOMDocument();
$dom->loadHTML($test);
foreach ($dom->getElementsByTagName('img') as $i => $img) {
    echo "IMG#{$i}:\n";
    echo "\tsrc = " , $img->getAttribute('src') , "\n";
    echo "\ttitle = " , $img->getAttribute('title') , "\n";
    echo "\talt = " , $img->getAttribute('alt') , "\n";
    echo "---\n";
}

انتاج:

IMG#0:
    src = /image/fluffybunny.jpg
    title = Harvey the bunny
    alt = a cute little fluffy bunny
---
IMG#1:
    src = /image/pricklycactus.jpg
    title = Roger the cactus
    alt = a big green prickly cactus
---
IMG#2:
    src = /image/noisycockatoo.jpg
    title = Polly the cockatoo
    alt = an annoying white cockatoo
---
IMG#3:
    src = somethingelse
    title = something
    alt = 
---

إن استخدام هذه التقنية في التعليمات البرمجية الاحترافية سيترك لك نصًا نظيفًا، وعددًا أقل من العقبات التي يجب مواجهتها، وعددًا أقل من الزملاء الذين يرغبون في العمل في مكان آخر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top