日本語ページをXPATHでスクレイピング

PHPXPATHを使ったスクレイピングをするには、基本的にはDOMDocumentとDOMXPathを使えばいいのだが、DOMDocumentにutf-8をISO-8859-1と誤認識してしまうバグがあるようだ。

ISO-8859-1の対応範囲内の言語のサイトならUTF-8をISO-8859-1に変換してからDOMDocumentに渡すというワークアラウンドがあるが(参考 http://www.php.net/manual/ja/class.domdocument.php#97051)、日本語の場合はそうもいかない。

で、このバグ、charsetより前に日本語があると発生するらしい(参考 http://ongmap.com/blog/?p=361)。

同じサイトでもページによって化けたり化けなかったりするなぁと思ったら、titleが英語のページと、日本語を含むページの違いだったのね。

charsetをheadの先頭に書くワークアラウンド

というわけで、charsetを書く位置を変更すればOK。http://d.hatena.ne.jp/rti7743/20090902/1251843968←このへんを参考に、以下のようにすれば無事文字化けせずにスクレイピングできた。

  $html = @file_get_contents($url);
  // charsetをheadの先頭に
  $html = preg_replace('/<meta[^>]*?charset[^>]*?>/uis', '', $html);
  $html = preg_replace('/<head[^>]*?>/uis', '<meta http-equiv="content-type" content="text/html; charset=utf-8">', $html);

  $dom = @DOMDocument::loadHTML($html);
  $xpath = new DOMXPath($dom);
  echo $xpath->query( "★xpathで指定")->item(0)->nodeValue;

スクレイピングは自己責任で(ry