追記
コメント欄で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