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;
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とか、自在に操れるようにしとかないとなぁ。
