Web::Scraperで正規表現を使って必要なリンクだけを取得する方法

わかってしまえば単純なことでした。

1
process 'a[href=~/\.jpe?g$/]', 'urls[]' => '@href';

XPathでも同じようにできます。

1
process '//a[@href =~ /\.jpe?g$/]', 'urls[]' => '@href';

Web::Scraperにはフィルタの概念があって、取得してからごにょごにょできるので、そっちのほうばかり調べていました。 例えば以下のようなHTMLの場合、そのまま取得すると、前後に改行が入ってしまいます。

1
2
3
<title>
タイトルなのだ
</title>

で、それを取得する時に、前後の改行を削除してやることができます。

1
process 'title', 'title' => ['TEXT', sub { s/^\s+//o; s/\s+$//o; } ];

こういう機能をフィルタと呼んでいます。 その機能を先に知ったので、取得したあとに拡張子を調べてマッチした場合だけ追加する、という方法を探していたのですが、考えてみれば、取得してからきれいにするよりも、最初からきれいに取るほうがいいですね。

以上を踏まえて書き直したのが以下のコード。 ついでだったので、Acme::PerlTidyを使って、自動的にコードの整形をしてもらいました。 実行時には不要なので、削除して使ってもまったく問題ありません。 CPAN:☼ 林永忠 ☼ / Acme-PerlTidy - search.cpan.org

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
use Acme::PerlTidy;
use strict;
use warnings;
use Web::Scraper;
use URI ();
use LWP::Simple qw(mirror);
use File::Basename qw(basename);
my $uri     = URI->new("http://weblog.nqou.net");
my $scraper = scraper {
    process 'a[href=~/\.jpe?g$/]', 'urls[]' => '@href';
    result 'urls';
};
my $result = $scraper->scrape($uri);
foreach my $link (@{$result}) {
    my $filename = basename($link);
    mirror($link, './images/' . $filename);
    sleep 1;
}
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy