アド企画 制作部
アド企画 制作部
 

PHPで(外部の)HTMLを取得して、色々な値を取得する

PHPで(外部の)HTMLを取得して、色々な値を取得する

PHPで(外部の)HTMLを取得して、色々な値を取得するアプリ開発案件の作業中です。

HTMLを取得して、対象を絞り込んで値を取得して・・・という作業。
HTMLのパースについては、色々なやり方があるみたいで、正解を探した結果、今回のようになりました。

※ simple_html_domというライブラリもあるが、今回はそれを使わない方向で。
simple_html_dom

パースするHTMLの準備

$url = 'http://..../xxxx.html'; // 対象のURL又は対象ファイルのパス
$html = get_file_contents($url); // HTMLを取得

パースするHTMLの準備:文字化け対策

取得したHTMLをパースしていく際に、HTMLに「<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />」と文字コード指定の記述があれば、正常に文字コードを変換して使える。
なんと、HTML5で記述された「 <meta charset="UTF-8" />」では、文字コードを判別できないという。

HTML5を指定した場合に備えて、次の処理をしなければ、文字化けしてしまう事がある。

1) 仕様するHTMLの文字コードが予めわかっている場合はHTMLエンコードする

$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');

2) HTML5で記述された文字コード指定部分のmetaタグを、正規表現で追記する。

$html = preg_replace('/<\s*meta\s+charset\s*=\s*["\'](.+)["\']\s*\/?\s*>/i', '<meta charset="${1}"><meta http-equiv="Content-Type" content="text/html; charset=${1}">', $html);

DOMDocumentオブジェクトの作成

$dom = new DOMDocument();
@$dom->loadHTML($html);
//loadHTMLは、HTMLとして正しくない箇所が一か所でもあるとWarningを発生するため、「@」をつけて無視させます。

次の様にして値を取得できた

//例 ) <title>タグの値を取得する場合
$title = $dom->getElementsByTagName('title')->item(0)->nodeValue;

//例 ) id='idname'のタグの値を取得する場合
$val = $dom->getElementById('idname')->nodeValue;

DOMについて
DOMDocumentについて

DOMXPathを使う場合

jQueryのセレクタと同じように使えたらいいなぁ・・・と思うがそうもいかないみたい。
XPathを使って、各値を取得しました。

XPath は、XML 文書の特定の部分を指し示す構文を規定します。XPath を利用すれば、XML 文書中に HTML 文書のようにアンカーなどが埋め込まれていなくとも、文書中の任意の位置を指し示すことができます。
http://www.techscore.com/tech/XML/XPath/XPath1/xpath01.htmlより
$xpath  = new DOMXPath($dom);

//id="tags"の子にあたるliタグの値を取得
$tags = array();
foreach($xpath->query('/*[@id="tags"]/li') as $node){
	// DOMXPath::queryの場合、$nodeはDOMElement
	$tags[] = $node->nodeValue;
}
print_r($tags);

DOMXPathについて
DOMXpath::queryについて
DOMElementについて

SimpleXMLElementでXPath式を使う場合

DOMXPathではなく、SimpleXMLElementを使ってもXPath式で値を取得できます。

$xml = simplexml_import_dom($dom); // SimpleXMLElementが返る
$tags = array();
foreach($xml->xpath('/*[@id="tags"]/li') as $node){
	// SimpleXMLElement::xpathの場合、$nodeはSimpleXMLElement 
	$tags[] = $node->__toString();
}
print_r($tags);

SimpleXMLElementについて
基本的な SimpleXML の使用法

今回は画像のURL(imgタグのsrc属性)も取得したかったので、こんな感じで取得しました。

$x = $xml->xpath('//div[@id="TargetId"]/img[@src]');
$x =(array)$x[0]["src"];
echo $x;

$images = array();
foreach($xml->xpath('//img[@class="TargetClass"]') as $node){
	$images[] =(array)$node[0]["src"];
}
print_r($images);

DOMDocumentとかXPathとか初めてさわるので、やり方がブサイクかもしれませんが、とりあえず目的は達成できました。
たぶん、もっとスマートでクールなやり方があることでしょう。

XPathとか、自在に操れるようにしとかないとなぁ。