perl と CrenaHtml2jpg を使って大量のサイトを自動キャプチャする方法

大量のサイトのキャプチャ画像を取得したい!そんな要件のお仕事もたまにあるでしょう。
実際、そんな要件に答えるために随分昔に作ったツールがありましたが、最近また利用する機会があったのでブログのエントリとして記載しておこうと思いました。

過去イロイロと検証した結果ですが、Windows + IE + CrenaHtml2jpg によるキャプチャ画像が一番いけてる画像が取得できる結論に達しました。CrenaHtml2jpg とは http://dip.picolix.jp/disp5.html で公開されているサイトキャプチャツールで非常に良くできたツールです。一般的な使われ方としての GUI 提供板貝に、サーバ向け?としてコマンドラインから内部的に IE を起動して描画してキャプチャ画像を出力する機能を有しています。動作中はもちろんパソコンが重くなるし、コピペが若干動作が怪しくなったりしますが良くできてると思います。巷の情報では hatena のサイトサムネイル画像の生成のバックエンドの仕組みにも使われているそうです。

というわけで URL が記述されたファイルから CrenaHtml2jpg 経由でキャプチャ画像を出力する perl スクリプトを書きました。

- スポンサーリンク -

CrenaHtml2jpg と perl スクリプトの準備

  1. CrenaHtml2jpg 最新版をダウンロードして、圧縮ファイルを展開する。展開したフォルダ名を CrenaHtml2jpg に変更する。
  2. キャプチャスクリプト screen_captcha.pl をダウンロードして、screen_captcha.pl というファイル名で保存する。
  3. 1. 2. を同じフォルダ配下に設置する。※下記画像のように。

    img001.jpg

使い方

  1. URL が記述されたテキストファイルを用意する。

    img002.jpg

  2. コマンドプロンプトを開いて screen_captcha.pl のフォルダへ移動する。
  3. 下記の通りコマンドを実行する。
    perl  screen_captcha.pl  URLテキストファイル名 横幅px数 wait値

横幅px数、wait値は省略可能です。
横幅px 数はスクリーンショットを取得するサイトの横幅に合わせて調整します。デフォルトは 1000px です。
wait 値は web アクセス後、何秒後にキャプチャーするかを指定します。動画などプラグイン系を含むページの場合は 3-5 秒程度を指定した方が良いのですが、その分実行速度が落ちます。

スクリプトを実行すると下記のような実行結果が出力されると共に、imgs というフォルダが自動生成され、そのフォルダ配下にキャプチャ画像が保存されます。キャプチャに成功した場合には、SUCCESS 表示、失敗した場合には FAILED とエラー理由が表示されます。

img003.jpg

キャプチャ画像のファイル名は、MD5 で URL をハッシュ化した値をファイル名にもちいており、実行と共にファイル出力される md5_url01.txt に、URL とキャプチャ画像ファイル名の対応が記載されています。このファイルを元に DB 管理したり excel 管理してください。

img004.jpg

ちなみにソースコードは下記のような感じになってます。一応事前に html に内容を取得して flash などの有無を調べて描画 wait 値などを調整したりしてます。

use strict;
use Digest::MD5 qw(md5 md5_hex md5_base64);
use LWP::Simple;

# URL リストを読み込む & img フォルダ配下へフォルダ作成
my $width = $ARGV[1] || 1000;
my $wait  = $ARGV[2] || 2;
my $savepath = "./imgs";
mkdir $savepath unless -e $savepath;
my @urls;
open my $fh, '<', $ARGV[0] || die 'perl screen_captcha.pl url一覧ファイル名 横幅px数 wait秒数で実行して下さい\n';
while (<$fh>) {
    chomp;
    my $uri    = $_;
    my $digest = md5_hex($_);
    push @urls, { url => $_, file => "$savepath/$digest\.jpg" };
}
close $fh;

# 対応表ファイルを書き出す
open my $ofh, '>', "md5_$ARGV[0]";
for ( sort @urls ) {
    print $ofh qq{$_->{file},$_->{url}\n};
}
close $ofh;

# ウェブショットを作成
my $idx  = 1;
my $size = "$width\x1";
for my $url (@urls) {
    my $begin = time;
    eval {
        # shockwave / flash の有無を判定
        my $content = get( $url->{url} );
        if ( $content =~ m!http://download.macromedia.com/pub/shockwave!msx ) {
            if ( $content =~ m!Shockwave\s*Player!msxi ) {
                $wait = 10;
                print "$idx [shockwave],$url->{url},shockwaveが含まれています。正常に画像出力されていないかも\n";
            }
            else {
                $wait = 5;
                print "$idx [flash],$url->{url}\n";
            }
        }
        else {
            print "$idx [normal],$url->{url}\n";
        }
        my $cmd = "CrenaHtml2jpg\\CrenaHtml2jpg.exe -o\"$url->{file}\" -fjpeg -q50 -p -w$size -s$size -t25 -l$wait -u\"$url->{url}\"";
        `$cmd`;
        $idx++;
    };
    my $end            = time;
    my $processingtime = $end - $begin;
    print $@ ? "->FAILED : $@\n" : "->SUCCESS : $processingtime sec : $url->{file}\n";
}

過去の経験上で、core2 以降の一般的な CPU で実行して、おおよそ 24 時間で 10000 スクリーンショットくらいが取得可能です。

- スポンサーリンク -

関連する記事&スポンサーリンク