私のウェブサイトにあるすべての画像がタイトルと代替表現でリストされているページを作成したいと思います。
すべてのHTMLファイルを見つけてロードするための小さなプログラムをすでに作成しましたが、このHTMLからsrc
、title
、およびalt
を抽出する方法にこだわっています。
<img src="/image/fluffybunny.jpg" title="Harvey the bunny" alt="a cute little fluffy bunny" />
正規表現を使用してこれを行う必要があると思いますが、タグの順序は異なる可能性があり、それらすべてを必要とするため、これをエレガントな方法で解析する方法がわかりません(ハード文字で行うことができます) charの方法ですが、それは苦痛です)。
正規表現を使用してこの種の問題を解決するのは 悪い考え であり、保守不能で信頼性の低いコードになる可能性があります。 HTMLパーサー を使用する方が適切です。
その場合、プロセスを2つの部分に分割することをお勧めします。
あなたのドキュメントは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"
)
)
[..]
)
)
正規表現はCPUを集中的に使用するため、このページをキャッシュすることをお勧めします。キャッシュシステムがない場合は、 ob_start を使用してテキストファイルからロード/保存することにより、独自に調整できます。
最初に、 preg_ match_ all を使用します。これは、パターンに一致するすべての文字列を取得し、3番目のパラメーターに出力する関数です。
正規表現:
<img[^>]+>
すべてのhtml Webページに適用します。 「<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');
}
タスクにPHPのXML機能を使用する簡単な例を示します。
$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は配列の配列を返すため
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を使用してそれを行いました。
私の場合、Wordpressから取得した<img>
タグを1つだけ含む文字列があり(他のマークアップはありません)、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);
タイトルまたはaltを取得するパターンでは、単に$pattern = '/title="([^"]*)"/';
を使用してタイトルを取得するか、$pattern = '/title="([^"]*)"/';
を使用してaltを取得できます。悲しいことに、私の正規表現は、1つのパスで3つ(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パーサーの使用は不要なオーバーヘッドであると訴える多くのコメントを読みました。まあ、それは単なる正規表現の呼び出しよりも高価かもしれませんが、OPはimgタグの属性の順序を制御できないと述べています。この事実は、不必要な正規表現パターンの畳み込みにつながります。さらに、domパーサーを使用すると、読みやすさ、保守容易性、dom-awareness(regexはdom-awareではありません)の追加の利点が得られます。
私は正規表現が大好きで、多くの正規表現の質問に答えますが、有効なHTMLを扱う場合、パーサーを正規表現する正当な理由はほとんどありません。
以下のデモでは、引用符が混在する(および引用符がまったくない)任意の順序でimgタグ属性をDOMDocumentが簡単かつクリーンに処理する方法を参照してください。また、ターゲット属性のないタグはまったく破壊的ではないことに注意してください。空の文字列が値として提供されます。
コード:( デモ )
$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 =
---
プロのコードでこの手法を使用すると、クリーンなスクリプト、競合する問題の減少、および他の場所での作業を希望する同僚の数が少なくなります。