R. Ayanokouzi et al.

[perl] Web::Scraper モジュールでリンク抽出の雛形

webページの内容を抽出するモジュールであるWeb::Scraper、これを使うとリンク抽出も出来る。

重要な示唆はpodに書かれている以下の一文。XPath表現とか、html、cssセレクタを使えると書いてある。

The scraper and process blocks provide a method to define what segments of a document to extract. It understands HTML and CSS Selectors as well as XPath expressions.

基本のコードひな形

Web::Scraper に渡すのは HTTP::Request にした方がいい。なぜなら、失敗の原因を 1.リクエストに対するレスポンス、2. スクレイピングなのかを切り分けるため。


#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use LWP::UserAgent;
use URI;
use HTTP::Request;
use Web::Scraper;

my $ua = new LWP::UserAgent();
$ua->agent( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36' );
$ua->max_size(1000000);

my $uri = URI->new("http://example.com/");

my $request  = HTTP::Request->new( GET => $uri );
$request->referer("http://example.com/");

my $scraper = scraper {
        process 'a', 'link[]' => '@href';
};

my ($response, $result) = err_handring(
    $ua
    , $request
    , $scraper
    , 10
)
print Dumper $result;
exit;

sub err_handring {
    my $ua = shift;
    my $request     = shift;
    my $scraper = shift;
    my $retry   = shift;

    my $response;
    my $result = {};
    while ( defined $@ && $retry-- > 0 ) {
        $response = $ua->request($request);
        # print Dumper $response;
        $result = eval { $scraper->scrape($response) };
        if ( !$@ ) {
            last;
        }
        else {
            warn $@;
        }
    }
    return ($response, $result);
}
__end__;

aタグのhref属性値

cssセレクタでaタグを抽出している。


my $scraper = scraper {
        process 'a', 'link[]' => '@href';
};

xpathでaタグを抽出する場合は以下。


my $scraper = scraper {
        process '//a', 'link[]' => '@href';
};

aタグのhref属性値が"http:"から始まるもの

cssセレクタとxpathの区別はprocess文が受け持っていて、以下の基準でなされる。

if the first argument begins with "//" or "id(" it's treated as an xpath expression and otherwise css selector.

正規表現を使ってxpath指定することも出来るようだ。たとえば以下の例はhref属性値がhttp:から始まるaタグを抽出している。xpathって正規表現使えたのかな?


my $scraper = scraper {
        process '//a[@href=~/^http:/]', 'link[]' => '@href';
};

aタグのhref属性値が"http:"から始まるもの

さらに、属性セレクタの条件を組み合わせることも出来る。以下の例はclass属性値にgbが含まれて、かつ、href属性値が/から始まるaタグを抽出している。


my $scraper = scraper {
        process '//a[@class=~/gb/][@href=~/^\//]', 'link[]' => '@href';
};

aタグの親要素のタグがdivかつクラスが"main-contents"であるもの


my $scraper = scraper {
        process '//div[@class="main-contents"]/a', 'link[]'   => '@href';
};

抽出内容の後処理の一例

podには書かれていないが、抽出した内容の後処理が出来る。以下の例は、aタグのhref属性値を抽出して、これに含まれる/を削除している。抽出後の$resultをごにょごにょするのと同じこと。


my $scraper = scraper {
        process '//a', 'link[]' => ['@href', sub {s/\///g}];
};

リファレンス

  1. web::scraperで正規表現を使って必要なリンクだけを取得する方法 - 日曜プログラマのそゞろ事
  2. web::scraper - search.cpan.org
  3. gentleちゃれんじ tips -関数を利用したxpath式-
  4. latest topics > css3セレクタとxpathでの表現の対応表 - outsider reflex
  5. actionscript入門wiki@rsakane - 属性セレクタ
  6. 属性セレクタ 正規表現 - google 検索
  7. xpath 正規表現 - google 検索
  8. xpath リンク - google 検索
  9. css セレクタ 正規表現 - google 検索
  10. use web::scraper リンク - google 検索
  11. xpath 正規表現 href - google 検索
  12. Web::Scraper - Google 検索

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2009-08-03T10:39:45+09:00
  2. Modified: 2009-08-03T10:39:45+09:00
  3. Generated: 2021-03-31T07:51:29+09:00