PHP Simple HTML DOM Parserは非公式のライブラリであり、ダウンロードしたライブラリをインクルードして使用します。
DOMDocumentは、PHPのDOM拡張モジュールのクラスです。
bool DOMDocument::loadHTML ( string $source )PHP: DOMDocument::loadHTML - Manual
文字列$sourceに含まれるHTMLをパースします。
bool DOMDocument::loadHTMLFile ( string $filename )PHP: DOMDocument::loadHTMLFile - Manual
ファイル$filenameから読み込んだHTMLドキュメントをパースします。
loadHTML()で誤ってHTMLファイルを読み込もうとすると、引数の「ファイル名」をHTMLコードとしてパースします。そのときには警告も表示されないため注意が必要です。なおXMLファイルから読み込むメソッドはload()であるため、これと誤解しないようにします。
HTMLファイルを読み込み、DOMXPathでimg要素を取得するには、
$dom = new DOMDocument(); @$dom->loadHTMLFile( $filename ); $xpath = new DOMXpath( $dom ); $elem = $xpath->query( '//img' );
とします。同様の処理をSimpleXMLでもできます。
$dom = new DOMDocument(); @$dom->loadHTMLFile( $filename ); $xml = simplexml_import_dom( $dom ); $elem = $xml->xpath( '//img' );
HTMLコードに非標準のタグが、XMLの規約に反する形式で含まれているとき、DOMXpathとSimpleXMLでは異なる結果を返します。
たとえばwbr要素について考えてみます。
$str = '<div>A<wbr>B</div>'; $dom = new DOMDocument(); @$dom->loadHTML( $str );
DOMXpathの場合、
$xml = new DOMXpath( $dom ); $result = $xml->query( '/*' ); print_r( $result->item( 0 ) ); // DOMElement Object // ( // [tagName] => html // [schemaTypeInfo] => // [nodeName] => html // [nodeValue] => AB // [nodeType] => 1 // ... 省略 // [localName] => html // [baseURI] => // [textContent] => AB // )
SimpleXMLの場合、
$xml = simplexml_import_dom( $dom ); $result = $xml->xpath( '/*' ); print_r( $result[ 0 ] ); // SimpleXMLElement Object // ( // [body] => SimpleXMLElement Object // ( // [div] => A // ) // )
このとき<wbr>
ではなく、<wbr />
のようにXMLの規約に従う形式ならば相違は生じません。
loadHTMLFile()によるHTMLファイルの読み込み時に、input conversion failed due to input errorと警告されることがあります。これは、
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
による文字セットの指定と、実際の文字セットが異なっている状態で発生します。このときにはファイルから文字列として読み込み、文字エンコーディングを変換してからloadHTML()で処理します。
ファイル関数を使用してファイルから文字列として読み込み、それを文字列の関数を使用して解析します。
たとえばtitleタグの要素を取得するならば、次のようにします。
function GetTitleTag( $url )
{
$result = null;
$filePointer = fopen( $url, 'r' );
if( $filePointer )
{
while( !feof( $filePointer ) )
{
// ファイルポインタから1行取得する
$text = fgets( $filePointer );
if( strpos( $text, '<title' ) !== FALSE )
{
$pattern = '/<title.*?>(.*?)<\/title>/i';
if( preg_match( $pattern, $text, $matches ) )
{
$to_encoding = 'UTF-8';
$from_encoding = 'EUC-JP, UTF-8, JIS, SJIS, ASCII';
$result = mb_convert_encoding( $matches[ 1 ], $to_encoding, $from_encoding );
}
break;
}
}
fclose( $filePointer );
}
return $result;
}
このコードには、次の問題点があります。