週末には少しPerlを。

Perlスクリプトの学習日記です。

いかにしてメイドさん画像をダウンロードするか~FC2編

Webサイトを巡回して画像ファイルを得る

Googleなどで「メイド 画像」を検索しているとfc2.comドメインのWebページが 少なからずヒットします。 そこでこれらのWebページを巡回してメイドさん画像をダウンロードする スクリプトを書いてみました。おおまかには

  1. Web検索APIを使って「メイド 画像 fc2.com」をキーワードに検索する。
  2. 検索にヒットした各Webサイトにアクセスし150Kbytes以上のJPG画像をダウンロードする。

という手順です。

マイクロソフトの検索エンジンの利用

検索エンジンにはこのブログエントリの 元ネタ でも利用されていた MicrosoftのBing Search API を利用しました。 利用にはWindows Azure Marketplaceでアカウントを作成し アカウントキーを得ることが必要ですが、登録さえすれば 月あたり5000トランザクションまで無料で利用できます。

1回のクエリにつき最大50件の結果が返りますので パラメータ「skip」を調整しながら問い合わせを繰り返します。 さしあたり問い合わせ回数の上限を100回と決めました。

use utf8;
use LWP::UserAgent;
use HTTP::Request;

# 略

my $url = URI->new('https://api.datamarket.azure.com/Bing/SearchWeb/Web');
my $authid = '';
my $authpass = 'My_API_Key';
my $query = 'メイド 画像 fc2.com';
my $ua = LWP::UserAgent->new( );

my $page_count = 0;
for (my $c = 0; $c < 100; $c++) {
    my $skip = $page_count * 50;

    $url->query_form(
        'Query' => qq{'$query'},
        '$top' => 50,           # max num of results
        '$skip' => $skip,       # offset
        '$format' => 'json',
        'Adult' => qq{'Off'},
        );

    my $req = HTTP::Request->new(GET => $url);
    $req->authorization_basic($authid, $authpass);

    my $res = $ua->request($req);

    if ($res->is_success) {

# 後述

    } else { # not success
        die $res->code;
    }
    $page_count++;
}

留意すべき点としてはクエリーを投げるときの「Adult」を「Off」指定している箇所です。 これは「Adultな結果をフィルタする機能をOffにする」という意味合いであって、 つまりAdultな結果を手に入れたいなら「Off」指定が必要です。

Parallel::ForkManagerによる並列処理

Web検索APIの結果が返ってきたらJSONモジュールでパースします。 「results」には最大50件の結果が格納されていますので、 それぞれの「Url」について 昨日のブログエントリ の要領で画像ファイルの検索・ダウンロードを試みます。

ここで高速化を期待してParallel::ForkManagerを 使って最大8プロセスでの並列処理をさせました。

use JSON;
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new(8);

# 途中略

for (my $c = 0; $c < 100; $c++) {

# 途中略

    if ($res->is_success) {
        my $j = decode_json $res->content;

        my $results = $j->{d}{results};
        if ($results) {
            my @targets = @$results;
            if (scalar(@targets) == 0) {
                last;
            }
            foreach my $target (@targets) {
                my $pid = $pm->start and next;
                &get_document($target->{'Url'});
                $pm->finish;
            }
        }
    }

# 途中略

} # for $c

コード中のサブルーチンget_documentの中身がほぼ 昨日のブログエントリ のものです。

成果

このスクリプトを実行することで約1400枚の画像をダウンロードできましたが 残念ながらメイドさんとはまったく無関係のものも多く混在してしまいました。 感覚的にはメイドさん画像が半数程度というところでしょうか。

とはいえ、それらの無関係な画像も含めて楽しめたので、 まずはこれで善しと考えたいと思います。