Billboardのランキングをperlで取得する
とりあえず書いてみた
Billboardのアルバムランキングを取得するモジュールを書いてみた.
どうせならと思い,threadを使ってみた.
かなり簡単だった.
それよりも,Web::Scraperって本当に便利だな.
package Music::Billboard; use strict; use threads; use threads::shared; use Carp; use Web::Scraper; use URI; use YAML::Syck; sub go { my @albums = ( threads->new(\&_albums_parsePage,'Albums','1-10'), threads->new(\&_albums_parsePage,'Albums','11-50'), threads->new(\&_albums_parsePage,'Albums','51-100'), ); foreach(@albums){ $_->join; } } sub _albums_parsePage { my ($genre,$scope) = @_; my $uri = new URI( qq{http://www.billboard.com/bbcom/charts/chart_display.jsp?f=The+Billboard+200&pageNumber=Top+${scope}&g=${genre}} ); my $page_scraper = scraper { process 'table.cbbTable_rowOn, table.cbbTable_rowOff, table.c50Table_row1, table.cbbTable_row1', 'songs[]' => scraper { process '.c50Table_text1, .cbbTable_text1',rank => 'TEXT'; process '.c50Table_text2, .cbbTable_text2',lastWk => 'TEXT'; process '.c50Table_text3, .cbbTable_text3',artist => 'TEXT'; process '.c50Table_text4, .cbbTable_text4',albumName => 'TEXT'; result 'rank','lastWk','artist','albumName'; }; result 'songs'; }; $page_scraper->user_agent->agent("Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"); my $data = $page_scraper->scrape( $uri ); print Dump $data; } 1;
追記:threads::sharedで苦戦
threads::sharedでhashを共有したら,なぜかうまくいかない.
ドキュメントを読み漁っているが,解決法が分からない..
my %hash :shared; ... sub thread_task {# threadで動かすサブルーチン $hash{test} = &share({}); $hash{test}->{a} = 1; }
これじゃ,やり方がまずいのかな
と思って,配列で試してみた.
my @array :shared; ... sub thread_task {# threadで動かすサブルーチン foreach(0..10){ push @array,$_; } }
これだとうまくいく.
リファレンスの扱いがだめなのかな.
まだ理解できない.
追記2:shared_clone()を使ってみた
ここを参考に,shared_clone()を使ってみた.
結果,arrayではうまくいくが,hashではうまくいかない.
とりあえずモジュールの中身を覗いてみた(参照)
# Used by shared_clone() to recursively clone # a complex data structure or object $make_shared = sub { my ($item, $cloned) = @_; ... # Make copies of array, hash and scalar refs and refs of refs my $copy; my $ref_type = reftype($item); ... # Copy a hash ref elsif ($ref_type eq 'HASH') { # Make empty shared hash ref $copy = &share({}); # Add to clone checking hash $cloned->{$addr} = $copy; # Recursively copy and add contents foreach my $key (keys(%{$item})) { $copy->{$key} = $make_shared->($item->{$key}, $cloned); } }
&share({});で初期化して,中身をディープコピーって,普通のことしかやってないよな.
やっぱやり方はあってるはず...
解決..
なんかしょうもないことをやっていた.
use YAML::Syck; ... my %hash :shared; ... print Dump %hash;
こうやって確認していたけど,print Dumpじゃ,hashのリファレンスは展開されないのか.
初めに確認すべきだった.