Hatena::ブログ(Diary)

cool2ikou このページをアンテナに追加 RSSフィード

2009-01-14

CustomFeed::Script for AmazonMP3 ranking

CustomFeed::Script for MixiNewsがうまくいったので、ついでにAmazon.com MP3 Downloads Bestsellers: The most popular items in MP3 Songs. Updated hourly.のランキング100をRSSにするスクリプトを作りました。

今まではDapper: The Data Mapperを使ってスクレイピングRSSにしていたのですが、amazonMP3だけうまく動作しなくなったのでPlaggerを使ってRSS生成するようにしました。

吐き出されたRSSを読み込んでYouTubeAPIに検索かけることでCDTube - カウントダウンチューブの洋楽版ができあがる。

amazonmp3ranking.pl

フィードタイトルに曲名、本文にアーティスト名

#!/usr/bin/perl

use strict;
use Web::Scraper;
use URI;
use utf8;

my $uri = URI->new('http://www.amazon.com/gp/bestsellers/dmusic/digital-music-track/ref=pd_ts_dmusic_nav');

my $scraper = scraper {
	process '//div[2]//div//td[3]', 'lists[]' => scraper { 
		process '//strong/a',
			 'artist' => 'TEXT';
		process '//a[last()-1]',
			 'title' => 'TEXT';
		}
};

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

my $feed = {
	title => 'amazonmp3',
	link => $uri->as_string,
	type => 'amazon',
};

for my $entry (@{ $res->{lists} }){
	push @{$feed->{entries}},{
		title => $entry->{title},
		body  => $entry->{artist},
};
}

use YAML;
binmode STDOUT, ":utf8";
print Dump $feed;

応用記事

  1. P::P::Filter::YouTubeFromTitle (Yusukebe::Tech)
  2. PerlでYouTubeのGData検索をする (Yusukebe::Tech)

YouTubeGdataサブルーチン

一応動いていますので使えるかも

sub search_youtube{
        my ($self,$context,$query) = @_;
        my $url = "http://gdata.youtube.com/feeds/api/videos?vq=" .
           URI::Escape::uri_escape_utf8($query);
        my $feed = XML::Atom::Feed->new(URI->new($url));

           $query = encode('UTF-8', $query) unless $context->conf->{no_decode_utf8};
#   $query =~s/([^\w\/\.\?:=&#])/sprintf("%%%02X", unpack("C", $1))/eg;
           $query =~ tr/\'/+/;
           $query =~ tr/ /+/;
           $context->log( info => 'Getting YouTube search results for ' . $query );

        my @entries = $feed->entries;
	die "" unless $entries[0];
        my $video_id;
        foreach my $link ( $entries[0]->link ) {
            my $href = $link->href;
            if($href =~ m!www.youtube.com/watch\?v=(.*)$!){
                $video_id = $1;
                $context->log(info => "$video_id get!");
                 }
              }
        return $video_id;
}

Web::Scraper,PlaggerでMixiニュースをGmailへ送信 CustomFeed::Script for MixiNews

web::scraperでmixi news一覧を抜き出すで実行したかったPlaggerを使ってのGmail送信。

試行錯誤の末なんとかうまくいきました。

前回のエラーの原因がわからず。

Plagger::Plugin::CustomFeed::Script [error] Error happend while executing '/usr/local/share/perl/5.10.0/Plagger/assets/plugins/CustomFeed-Script/mixinews_check.pl': -1

CustomFeed/Script.pmを見てみるも

>|my $output = qx($script) の部分でエラー処理されているようで 文字列エラー?未だに正確な原因はわかりません。 ただ、管理者権限(root)でスクリプトを作成していたので、 ファイルのアクセス権を変えることで認識し動作しました。 半ば諦めていたのですが動いてよかったです。 CustomFeed::Script for MixiNewsでミクシーニュース一覧を取り出しRSS生成。 吐き出されたRSSを別で読み込んでGmailへ送信といった2手間かかるといったフロー。 スクリプトyaml載せておきます。 今度はwww::Mechanizeのfollow_linkへリンクを渡し、 個々の記事を拾ってくるようにしようと考えています。 mixi_news_check.pl
#!/usr/bin/perl 
use strict;
use warnings;
use URI;
use YAML;
use WWW::Mechanize;
use Web::Scraper;
use utf8;

my $uri = URI->new( 'http://mixi.jp/' );
my $username = 'yourname@example.com';
my $password = "password";
my $mech = new WWW::Mechanize;

   $mech->get($uri);
   $mech->submit_form(
                 fields => {
                    email     => $username,
                    password => $password,
                 }
   );

   $mech->get('http://news.mixi.jp/list_news.pl');

my $base_uri = 'http://news.mixi.jp/list_news.pl';

my $s = scraper {
              process '//title' , 'title' => 'TEXT',
              process '//table[@class="newsTable"]/tr/td',
                      'entries[]' => scraper {
                                   process 'a',
                                   title => 'TEXT', 
                                   link => sub { URI->new_abs($_->attr('href'), $base_uri)->as_string };
                                   };
			result 'entries';
             };
my $src = $s->scrape($mech->content, $mech->uri);

my $feed = {
        title => 'mixi NEWS',
        link  => $uri->as_string,
        type => 'mixinews',
};

for my $entry (@{ $src }) {
    push @{$feed->{entries}}, {
        title   => $entry->{title},
        link    => $entry->{link},
        summary => $entry->{link},
        body    => $entry->{title}." ".$entry->{link},
    };
}


binmode STDOUT, ":utf8";
print Dump$feed;
mixiNEWScheck.yaml
global:
  plugin_path:
    - /usr/local/share/perl/5.10.0/Plagger/Plugin


  assets_path:
    - /usr/local/share/perl/5.10.0/Plagger/assets

  timezone: Asia/Tokyo


  log:
    level: error

plugins:
  - module: Subscription::Config
    config:
      feed:
        - script:///path/to/mixiNEWScheck.pl

  - module: CustomFeed::Script

  - module: Publish::Feed
    config:
      dir: /home/user/
      filename: mixiNEWS.rss
      format: RSS
参考記事
  1. Config::PitとWeb::ScraperとPlaggerで24時間365日のゲーム監視体制
今度はConfig::Pitを実装してみます。
  1. Big Sky :: はてなニュースのRSSを出力するCustomFeedScript
助かりました。
  1. さくら水産の日替わり定食献立表を取得する - noboruhiの日記 - Plaggerグループ
  2. use WWW::Mechanize; - 今日のCPANモジュール
  3. use Web::Scraper; - 今日のCPANモジュール
  4. 配列のリファレンス, 配列への変換, 要素の参照 - Perl入門〜サンプルコードによるPerl入門〜
リファレンスについてちょっと理解できてきました。 >追記: Plagger CustomFeed::Script mixiニュースのRSSを生成 にて、本文抜き出しRSS生成スクリプをを公開。