ようこそゲストさん

Magical Diary, beta version

[Perl] ニコニコ動画をWeb::Scraperでスクレイプ

2007/10/06 21:41 HIRATA Yasuyuki

ニコニコ動画のタグごとにRSSを作るため、最初は以下のように正規表現でゴリゴリと処理していたが、イマイチ綺麗じゃない。

while($html =~ m{<p><a\s+href="watch/(\w+)">\s*
                 <img\s+.*?src="(.*?)".*?>.*?
                 <strong>((?:\d+分)?\s*\d+秒)</strong>.*?
                 再生:<strong>([\d,]+)</strong>.*?
                 コメント:<strong>([\d,]+)</strong>.*?
                 <a\s+class="video".*?>([^<>]*)</a></p>.*?
                 <p.*?>([^<>]*?)</p>.*?
                 <p.*?><strong>([^<>]*?)</strong></p>
                 }gsx) {
    ...
}

今回は Web::Scraper というモジュールを使ってみた。これは、CSSセレクタやXpathで対象を指定すると、解析した結果を返してくれる。HTMLをパースして情報を取得するときに便利だ。

どのブロックからデータを取得するのかを大まかに指定してしまって、その中で細かい情報を取得するという段階を踏むと、スクレーピングしやすいとあったので、

  1. "thumb_frm" を class 属性として持つ div 一式を取得
  2. これらの div について、細かく Xpath 指定で要素を抽出

という手順で処理することにした:

my $scraper = scraper {
  process('//div[@class="thumb_frm"]',
          'videos[]' => scraper {
            process('/div/div/div/p/a/img',
                    img_url => '@src',
                    img_width => '@width',
                    img_height =>  '@height');
            process('/div/div/p[2]/strong',
                    length_str => 'TEXT');
            process('/div/div/p[2]/strong[2]',
                    num_played_str => 'TEXT');
            process('/div/div/p[2]/strong[3]',
                    num_comments_str => 'TEXT');
            process('/div/div[2]/p/a[@class="video"]',
                    title => 'TEXT',
                    url => '@href');
            process('/div/div[2]/p[2]',
                    desc => 'TEXT');
            process('/div/div[2]/div/p/strong',
                    comment => 'TEXT');
          });
};

作った結果: ニコニコ動画 俺様用RSS

ニコニコ動画アクセス関係は WWW::NicoVideo として分離させているけど、需要あるかな?

ニコニコ動画Perlインターフェイス (WWW::NicoVideo) を公開しました。


#  非公開コメント   

  • TB-URL(確認後に公開)  http://diary.asuka.net/032/tb/
© 2007 HIRATA Yasuyuki <yasu@asuka.net>, all rights reserved