追記
コメント欄でotsuneさんにご指摘頂きました。scraperのprocess部、LWPの初期化をループ内で行わないようにしました。
やっぱり書いた記事にはてなスターが付くと嬉しいものですよね。出先でちょっとした間にはてなスターが付いているのを見て、ニタニタしたい人もいるかと思います。
でもはてなスターにはモバイルページがありません。しかもスターレポートページを閲覧するにはログインが必要になります。さて今日はモバイル端末から閲覧出来るエゴツール「モバイルはてなスターページ」を作って見たいと思います。
まずスターレポートページを見る為に、WWW::Mechanizeを使ってログインします。ログインページは
http://www.hatena.ne.jp/login?location=http://s.hatena.ne.jp/
となります。セキュリティを考慮されたいならばhttpsにされるのが良いかと思います。以下WWW::Mechanizeでログインする処理になります。
my $username = 'xxxxxxxx'; my $password = 'xxxxxxxx'; my $mech = WWW::Mechanize->new(timeout => 10, agent=>'StarScraper'); $mech->get('http://www.hatena.ne.jp/login?location=http://s.hatena.ne.jp/'); $mech->add_header('Accept-Encoding', 'identity'); my $res = $mech->submit_form( form_number => 1, fields => { name => $username, password => $password, } );
ログイン後の処理はWeb::Scraperでのスクレイピングになります。レシピは以下の通り
my $star_list = scraper { process 'span.entry-title', 'stars[]' => scraper { process 'a', title => 'TEXT', link => '@href'; }; result 'stars'; };
そして上記mechをWeb::Scraperのuaに設定し、スクレイピングを実行します。
$star_list->user_agent( $mech ); my $u = "http://s.hatena.ne.jp/$username/report"; my $stars = $star_list->scrape( URI->new($u) );
さて、これだけではスターが付けられたURLの一覧しか取得出来ません。そこで、はてなスターAPIを使ってスターのエントリを取得します。はてなスターAPIのエントリ取得URLは以下の通り。
http://s.hatena.ne.jp/entries.json?uri=[URL]
このAPIに上記でスクレイピングしたURLを渡します。
my $ua = LWP::UserAgent->new; for my $star (@$stars) { my $uri = 'http://s.hatena.ne.jp/entries.json?uri=' . URI::Escape::uri_escape($star->{link}); my $req = HTTP::Request->new(GET => $uri); my $res = $ua->request($req); $res->is_success or return 0; my $json = from_json( $res->content ); my @sts = @{$json->{entries}->[0]->{stars}}; }
ここで気をつける必要があるのですが、stsの要素はHASHの場合とスカラの場合があり、HASHにはスター情報が、スカラには"☆35☆"といった省略する数値が入っています。これに気をつけて以下の様に処理します。
for my $st (@sts) {
if (ref $st eq 'HASH') {
print '<img src="http://s.hatena.ne.jp/images/star.gif" title="' . $st->{name} . '" />'
} else {
printf '<font color="#f4b128">%d</font>', $st;
}
}
全体のコードは以下の様になります。
#!/usr/bin/perl use warnings; use strict; use URI; use Web::Scraper; use HTML::Entities; use WWW::Mechanize; use JSON; my $username = 'xxxxxxxx'; my $password = 'xxxxxxxx'; my $mech = WWW::Mechanize->new(timeout => 10, agent=>'StarScraper'); $mech->get('http://www.hatena.ne.jp/login?location=http://s.hatena.ne.jp/'); $mech->add_header('Accept-Encoding', 'identity'); my $res = $mech->submit_form( form_number => 1, fields => { name => $username, password => $password, } ); my $star_list = scraper { process 'span.entry-title', 'stars[]' => scraper { process 'a', title => 'TEXT', link => '@href'; }; result 'stars'; }; $star_list->user_agent( $mech ); print "Content-Type: text/html; charset=utf-8\n\n"; my $u = "http://s.hatena.ne.jp/$username/report"; my $stars = $star_list->scrape( URI->new($u) ); my $ua = LWP::UserAgent->new; for my $star (@$stars) { printf "<a href=\"%s\">%s</a><br />‬\n", $star->{link}, encode_entities($star->{title}); my $uri = 'http://s.hatena.ne.jp/entries.json?uri=' . URI::Escape::uri_escape($star->{link}); my $req = HTTP::Request->new(GET => $uri); my $res = $ua->request($req); $res->is_success or return 0; my $json = from_json( $res->content ); my @sts = @{$json->{entries}->[0]->{stars}}; for my $st (@sts) { if (ref $st eq 'HASH') { print '<img src="http://s.hatena.ne.jp/images/star.gif" title="' . $st->{name} . '" />' } else { printf '<font color="#f4b128">%d</font>', $st; } } print "<br />\n"; }
携帯片手にニタニタしてみてはどうでしょうか。



process 'a', title => 'TEXT';
process 'a', link => '@href';
は
process 'a', title => 'TEXT' , link => '@href';
でok
あとforループの中で
my $ua = LWP::UserAgent->new;
でコンストラクタ走らせるとおもくね?
>otsuneさん
ありがとうございます。修正しました。
trackback送ってるはずなのに反映されてないのは気のせいですかね?
私も「はてなスター」チェックにチャレンジしてみましたー(^o^)/
http://d.hatena.ne.jp/sasezaki/20080719#p1