たった10行のコードでひたすらアイドル水着画像をあつめる

こんにちは、飯塚です。
ウェブ上にはたくさんのデータがあふれています。その中から「自分の欲しいデータだけ」を「自動」でかき集めることができたら素敵じゃないですか? そこで今回は UT Startup Gym「ウェブから情報をあつめる」で取り上げた内容をもとに、たった10行(正確には 9 行)のコードでひたすら「アイドル水着画像」を集める方法を紹介します。言語は PHP です!

まずは結果から


はい、これが今日の目標です。

さっそくコード書く

mac ユーザはさっそくプリインストールされているターミナル.app を起動して、

$ emacs crawler.php

と入力して Enter(もちろん他のエディタでも OK)。頑張って下のコード(青色のコメント部分は写さなくていいです)を写経してください。

<?php
$url = "http://matome.naver.jp/odai/2135350364969742801"; // 画像を収集したい NAVER まとめページの URL
$res = file_get_contents($url); // URL からソースコード(文字列)を取得する
$dom = @DOMDocument::loadHTML($res); // 文字列から HTML を生成
$xml = simplexml_import_dom($dom); // さらにそこから SimpleXMLNode オブジェクトを取得
$imgs = $xml->xpath("//img[@class='MTMItemThumb']"); // XPath を用いて class="MTMItemThumb" の img 要素のみ取得
foreach ($imgs as $img) { // すべての画像について ...
    echo "<img src='".$img["src"]."'>\n"; // URL から img タグを出力
}

Windows ユーザは、各自 PHP を実行できる環境を整えてください。以前のエントリを参考に Ubuntu 入れちゃうのもアリです。
写経できたら、Ctrl+X を押して、Ctrl+S を押す(保存)。Ctrl+X を押して、Ctrl+C を押す(終了)。

画像の一覧を取得する

emacs が終了してシェル画面に戻ってきますので、次のコマンドを入力します。

$ php crawler.php

すると、画像の URL っぽいもの(正確に言うと img タグ)がたくさん表示されます!

これが実は、
http://matome.naver.jp/odai/2135350364969742801
に収められている画像の一覧なのです。

ブラウザに表示する

それでは、この画像群をブラウザで表示させます。もう一度ターミナルで、次のコマンドを入力します。

$ php crawler.php > photos.html
$ open photos.html

すると、既定設定のブラウザが起動して、画像の一覧が表示されます。

おおおおー!

もちろん、URL を変えればこんなかわいい猫画像も!

みんな大好きワンピースも!

こんなかんじで色々な画像が集められます。

リンクをたどって、すべてのページから画像を収集する

先ほどのコードでは、1ページ目の画像しか収集することができなかったので、今回は2ページ目以降も収集してみたいと思います。

<?php
$url = "http://matome.naver.jp/odai/2135350364969742801"; // NAVER まとめページ URL
$res = @file_get_contents($url);

while ($res) {
    $data = getData($res);
    foreach ($data["image"] as $image) {
        echo "<img src='".$image["src"]."'>\n";
    }
    if ($data["nextPage"]) { // 次のページがあるか?
        $res = @file_get_contents($url."?page=".$data["nextPage"]);  // URL の末尾に ?page= をつけると、ページを指定することができる。
        sleep(1); // サーバへの負荷を減らすため 1 秒間遅延処理
    } else {
        break; // 次のページがなければ終了
    }
}

function getData ($html) {
    $dom = @DOMDocument::loadHTML($html);
    $xml = simplexml_import_dom($dom);
    $result["image"] = $xml->xpath("//img[@class='MTMItemThumb']");
    $pager = $xml->xpath("//div[@class='MdPagination03']"); // ページ送り部分を取得
    $current_page = $pager[0]->strong; // 太字のページ番号の値
    $last_anchor = $pager[0]->a[count($pager[0]->a)-1]; // 太字でないページ番号の末尾の値
    if ($last_anchor + 1 != $current_page) { // 太字のページ番号が最後のページを指していなければ...
        $result["nextPage"] = $current_page + 1; // 次のページを設定する。
    } else {
        $result["nextPage"] = null; // 次のページは無い
    }
    return $result;
}

同じようにブラウザで表示すると・・・!

大漁!!

ポイント

  • URL の末尾に ?page= をつけると、ページを指定することができる。
  • 実在するページ数より大きい値を指定した場合でも 404 エラー (Not Found) とならず、最終ページを表示する。
  • そのため、?page= の指定を「404 エラーになるまでインクリメントする」戦略は使えない。
  • したがって、ページ送りで、太字で強調されているページ番号が、太字じゃないページ番号の末尾の次ならば、最終ページと判断する。

まとめ

というわけで、今回は NAVER まとめのアイドル水着画像を題材に、データを収集する方法を紹介しました。
もちろんこの技術を応用すれば、ウェブサイトの構築や研究にも役立てることができます。もっと詳しく勉強したい人は、ぜひ XPath、クローリング、スクレイピングなどのキーワードでググってみてください。さらに詳しく知りたい人のために、講義資料はSlideShareでも公開しています。本格的にウェブサービスの構築について学びたい方は UT Startup Gym でお待ちしております。
それではまた!

ちなみに