work.log

元エンジニアの備忘録的ブログ

PerlのHTML::TreeBuilderとWeb::Scraperは使い分けが良さそうだ

投稿:2013-12-05 17:48  更新:

Perl で Web ページをスクレイピングするメモ書きです。

昨日 Web::Scraper を試してみて「Web::Scraper は最高だ!」と書いたのですが、肝心な事を確認するのを忘れていました。

スクレイピング処理を書くなら簡単に越したことがないとは考えているのですが、利用頻度が高い処理の場合はなるべく早いに越したことがないのも事実。

ということで、Web::Scraper と HTML::TreeBuilder で同じ処理を行うスクリプトを書いて簡単に処理速度を計測してみました。

Web::Scraper でタイトルを抜き出す処理

まずは Web::Scraper から。

#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use Web::Scraper;

    my $url     = 'https://worklog.be/';
    my $ua      = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)';
    my $timeout = '10';

    my $lwp = LWP::UserAgent->new( agent => $ua, timeout => $timeout );
    my $res = $lwp->get( $url );

    if ( $res->is_success ) {

        my $scraper = scraper {
               process '#content h1', 'title[]' => 'TEXT';
           };

        my $data = $scraper->scrape($res);

    }
exit;

これを 5 回ほど実行してみます。

# time perl scraper.pl

0.616u 0.037s 0:01.02 62.7%     10+7914k 0+0io 0pf+0w
0.517u 0.063s 0:00.91 62.6%     10+7167k 0+0io 0pf+0w
0.686u 0.015s 0:01.03 66.9%     10+7674k 0+0io 0pf+0w
0.667u 0.007s 0:01.02 64.7%     10+7674k 0+0io 0pf+0w
0.806u 0.069s 0:01.22 70.4%     10+7724k 0+0io 0pf+0w

平均 1.04 秒って所ですね。

HTML::TreeBuilder でタイトルを抜き出す処理

続いて、HTML::TreeBuilder です。

#!/usr/bin/perl

use strict;
use warnings;
use LWP::UserAgent;
use HTML::TreeBuilder;

    my $url     = 'https://worklog.be/';
    my $ua      = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)';
    my $timeout = '10';

    my $lwp = LWP::UserAgent->new( agent => $ua, timeout => $timeout );
    my $res = $lwp->get( $url );

    if ( $res->is_success ) {

        my $data = {};
        my $tree = HTML::TreeBuilder->new;
        $tree->parse( $res->content );
        $tree->eof();

        foreach ( $tree->look_down('id', 'content')->find('h1') ) {
            push(@{$data->{title}}, $_->as_text);
        }

        $tree = $tree->delete;

    }
exit;

先ほどと同様に実行してみます。

# time perl treebuilder.pl

0.269u 0.055s 0:00.67 46.2%     10+5202k 0+0io 0pf+0w
0.299u 0.043s 0:00.69 47.8%     11+6023k 0+0io 0pf+0w
0.312u 0.045s 0:00.70 50.0%     10+5300k 0+0io 0pf+0w
0.314u 0.037s 0:00.69 49.2%     11+5512k 0+0io 0pf+0w
0.330u 0.022s 0:00.68 51.4%     10+5215k 0+0io 0pf+0w

平均 0.68 秒と Web::Scraper より 1.5 倍ほど早いですね。

Web::Scraper は使いやすいように中で色々使ってるのでその差ですかね (適当)。

実用スクリプトでも差を見てみる

ついでなので普段稼働させている処理も Web::Scraper と HTML::TreeBuilder で分けてみたので計測してみました。

こちらはソースはなしで結果だけ。

# time perl scraper.pl

0.900u 0.076s 0:01.99 48.7%     10+10402k 0+0io 0pf+0w
0.999u 0.053s 0:02.14 48.5%     10+10862k 0+0io 0pf+0w
0.909u 0.068s 0:02.10 45.7%     10+10696k 0+0io 0pf+0w
0.887u 0.073s 0:01.98 47.9%     11+11010k 0+0io 0pf+0w
0.714u 0.067s 0:01.86 41.3%     10+9906k 0+0io 0pf+0w

# time perl treebuilder.pl

0.496u 0.053s 0:01.61 33.5%     10+7619k 0+0io 0pf+0w
0.457u 0.071s 0:01.65 31.5%     11+8005k 0+0io 0pf+0w
0.477u 0.098s 0:01.67 33.5%     10+7588k 0+0io 0pf+0w
0.483u 0.039s 0:01.58 32.2%     10+7414k 0+0io 0pf+0w
0.607u 0.074s 0:01.73 38.7%     10+7477k 0+0io 0pf+0w

Web::Scraper が平均 2.01 秒。HTML::TreeBuilder が平均 1.64 秒で 1.2 倍ほど HTML::TreeBuilder の方が早く処理できたようです。

Web::Scraper のコードがスッキリする恩恵も捨てがたいけど、高頻度で利用する物であればやっぱり HTML::TreeBuilder かなーという感じです。

何となくですが物によって使い分けるのが良さそうな感じ。