PHPでphpQueryを使ってWebスクレイピングしてみる

Webスクレイピングだなんて、あんまり大きい声じゃ言えない。
結局のところ、他所様のコンテンツを勝手に拝借してゴニョゴニョするわけで、良いことではないわ。

だが、人間生きていれば、Webスクレイピングをしなければいけない場面くらいある。

そう、今回はそういう場面なのだ。

Webスクレイピングとは?

プログラムで、WebページのHTMLを取得し、解析して、必要なデータだけを抽出することを指す用語。
ウェブスクレイピング(Wikipedia)

例えば、Amazonなどの通信販売系のWebサイトにスクレイピングをかけると、少年漫画の新刊情報だけ抽出できたりするのだ。

だが、プログラムが自動的に、必要なデータだけを抽出するということは、広告やら何やら余計な情報が表示されない。という意味になる。

Webサイトを開いている個人はともかく、営利目的である企業のWebサイトやサービスでは、そんなことをされると、広告収入が減ったり、プログラムで大量に連続的にアクセスされることで、Webサーバーに負荷がかかったりと、あんまり良いことはない。

明確に規約で禁止されていることもある。もしWebスクレイピングに手を出すなら、充分に気を付けなくてはいけない。

ISBNコードから書籍情報を検索したい

友人の蔵書管理システムのデータ復旧を手伝っている内に、どうしてもISBNコードから書籍情報を検索する必要が出てきた。

一応、書籍データベースが利用できないかと思って調べてみたのだが、書籍データベースというものは有料で高価な物ばかりで、個人的に利用するには年収が 500,000 USDくらいないときつい。

一件ずつ手動でAmazonで検索すれば良いのだろうけど、4005件もデータがあるので、手動でやっていた日には検索が完了する頃には、人類が火星に移住してしまう。

そういうわけで、Webスクレイピングをするのだ。目指すはISBNコードから書籍情報を検索して、CSVの一覧にすること。(自動で、お手軽に!)

まずはWebページをダウンロードしてみよう

Webスクレイピングの手順は以下の様になる。

  1. URLを特定する。
  2. 特定できたURLからHTMLを取得する。
  3. HTMLを解析して必要なデータを抽出する。

とまぁ、このような手順である。

URLを特定するのと、HTMLを取得する部分は、PHPなので適当に書けるだろう。

// ISBNコードが掲載されているテキストファイルを読み込む
$isbn_file = file("isbn.txt");
// 1行ずつループを回す
foreach($isbn_file as $isbn) {
    // urlを特定
    $url = sprintf("http://example.com/isbn/%s/", $isbn);
    // HTMLをダウンロード
    $html = get_webpage($url);
    var_dump($html);
    // サーバー側にDDos攻撃だと思われないように、充分なスリープを取る
    sleep(10);
}

※ Webスクレイピングの対象になるWebサイトは、動的にページを生成することが多く、ほとんどの場合、リダイレクトへの対処が必要になるのだが、上記コードはリダイレクトへの対処をしていない。リダイレクトが発生するWebページを上記コードでダウンロードしようとしても、うまくいかないので注意。(この件については、別記事として書くことにする。)

※ リダイレクトへの対応が面倒な場合は、PEARHTTP_Clientなどを使うと簡単に実装できるかも。

phpQueryを使ってHTMLを解析するのだ!

あ、やっとタイトルに出てきたphpQueryが出てきた。
はい。

phpQueryとはjQueryというJavaScriptと同一の感覚でDOM操作が行えるPHP用のライブラリです。jQueryでのDOM操作に慣れていれば、簡単に扱えます。

大体、PHPを触るような人なら、jQueryくらい使えるので、phpQueryは非常に便利なライブラリですね! PHP使ってるけどjQuery使えないという人は、まぁ覚えてください。

phpQueryのプロジェクトページ
https://code.google.com/p/phpquery/

phpQueryのダウンロードページ
https://code.google.com/p/phpquery/downloads/list

phpQueryをダウンロードする際は、onefile とついたファイルをダウンロードすると良い。一個のファイルに、phpQueryの実装がまとめられていて、requireやincludeする際に面倒が無くて良い。

では、早速使ってみよう。以下の様なHTMLをダウンロードしてきたとする。

...
<div class="book">
	Authors: 藤崎 聖人<br>
	Publisher: 小学館<br>
	Pages: 135<br>
	Published: 2006-04-18<br>
	Language: Japanese<br>
	Category: コミック, コミック・ラノベ・bl, <br>
	Binding: コミック<br>
	List Price: 4.10 JPY<br>
</div>
...

上記は、実際にHTMLから抜き出したい箇所である。このデータを抽出したいのだ。
phpQueryでの書き方はこう。

        $doc = phpQuery::newDocument($html);
        $book = $doc['.book'];
        echo $book;

なお、bookというクラスは、HTML中に一回しか出てこないものとする。
複数回、出てくる場合は、$bookという変数の中に複数要素が入る。

ちなみに

Webスクレイピングしようとしていたページは、詳細ページでテキストファイルがダウンロードできる。
URL中のISBNコードを書きかえるだけで、対象のテキストファイルがダウンロードできたので、Webスクレイピングは実は全く必要なかったのだ。

やっぱりWebスクレイピングだなんて、やらないほうがいい。迷惑だからな。皆もやるんじゃないぞ。