読者です 読者をやめる 読者になる 読者になる

Web::Queryで最初の要素を取りたい!

例えば、このようなリストがあるとします。

<ul class="video">
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>C</li>
</ul>

このリストから、最初の要素<li>A</li>だけを取りたい時にはどうすればいいでしょうか。
Web::Scraperではこんな感じです。

use Web::Scraper;

my $scraper = scraper {
    process 'ul.video li', 'title' => 'TEXT';
};

my $res = $scraper->scrape(URI->new('http://example.com'));
print $res->{title}, "\n";

Web::Scraperはscrape()のときにURIオブジェクトを渡さないといけないとか、いろいろ面倒くさいです。でも、キライじゃないです。
Web::Queryでは、なかなかうまくいきません。で、試行錯誤の末、うまく動いたのがこんな感じです。

use Web::Query;

my $elem = wq('http://ch.nicovideo.jp/channel/ch60001')
    ->find('ul.g-video-mini .g-video-right');

$elem->{trees} = [$elem->{trees}[0]];

$elem->each(sub {
    my $i = shift;
    print $_->text, "\n";
});

ダメだー X(
Web::Scraperを使わないと、いい感じに書けないみたいですね。


でも、Web::Queryはeach()で$_が使えるのがすげー!と思い、気になったのでコードを見てみたら

sub each {
    my ($self, $code) = @_;
    my $i = 0;
    for my $tree (@{$self->{trees}}) {
        local $_ = wq($tree);
        $code->($i++, $_);
    }
    return $self;
}

すげー!
Web::Queryはwq()になんでも渡せる(URIオブジェクト、URL文字列、生HTML、...)ので素敵だし、find()を重ねて、Web::Scraperでは出来ないようなこともできるので、使って損はないと思います。