[SBM] はてブ・del.icio.usの被ブックマーク件数を表示してみた
<<
作成日時 : 2006/05/09 09:30
>>
トラックバック 1 / コメント 0
はてなブックマークとdel.icio.us にブックマークされている件数を、そのページ自身に表示するようにしてみた。
ページ表示のたびに件数取得しにいくと大変なことになるので、1日何回かだけ cron の定期実行で
主要ページの登録件数をまとめて取得させてもらって、JSON 形式でサーバに置いておきます。
表示するのは静的 HTML のページなので、Ajax でダウンロードしたJSONファイルから検索します。
仕組みとしては、以下のようなフローです。
負荷を抑えつつ、静的HTMLページに動的に値を埋め込んでいるのがポイント。
(事前処理) サイトのRSS ⇒ 被ブックマーク件数の照会 ⇒ JSON作成
(ページ表示時) JSONをAjaxでダウンロード ⇒ 被ブックマーク件数を表示
右上の『100 users』が、はてブの被ブックマーク件数で、
『20 people』が、del.icio.us の被ブックマーク件数です。
はてなブックマークは件数取得APIが公開されているのでやりやすいですが、
del.icio.us はページごとに原始的な方法で問い合わせるしかないので、
あまり頻繁に問い合わせると、スグにIPブロックされてしまいますね。。。賢い。
del.icio.us は、RSS 経由でブックマーク内容(コメント)を取得することもできますが、
それだと 20件までしか取れないのかな? 合計件数の数字が欲しいんだけど。
以下は、被ブックマーク件数を取得して JSON 形式に変換するスクリプト。
#!/usr/bin/perl
# ----------------------------------------------------------------
# sbm2json.pl ----
# Copyright 2004-2006 Kawasaki Yusuke <u-suke [at] kawa.net>
# ----------------------------------------------------------------
use strict;
use XML::FeedPP;
use Digest::MD5;
use LWP::UserAgent;
use WebService::Hatena::BookmarkCount;
use JSON::Syck;
# ----------------------------------------------------------------
&sbm_to_json( @ARGV );
# ----------------------------------------------------------------
sub sbm_to_json {
my $links = [];
my $opts = { map {$_=>1} grep { /^-/ } @_ };
my $files = [ grep { ! /^-/ } @_ ];
foreach my $rss ( @$files ) {
warn "[rss] $rss\n";
my $feed = XML::FeedPP->new( $rss );
push( @$links, $feed->link() ); # feed itself
my $items = [ $feed->get_item() ];
push( @$links, map {$_->link()} @$items ); # entries
}
my $uniq = { map {$_=>1} @$links };
$links = [ sort keys %$uniq ];
my $out;
$out = &check_hatena( $links ) if $opts->{'-h'};
$out = &check_delicious( $links ) if $opts->{'-d'};
return unless ref $out;
return unless scalar %$out;
my $json = JSON::Syck::Dump( $out ) or return;
print $json;
}
# ------------------------------------------------------------------------
sub check_hatena {
my $links = shift or return;
my $data = {};
while( scalar @$links ) {
my @slice = splice( @$links, 0, 10 );
my $res = WebService::Hatena::BookmarkCount->getCount( @slice ) or next;
foreach my $url ( keys %$res ) {
$data->{$url} = $res->{$url};
}
}
return unless scalar keys %$data;
my $out = {};
foreach my $url ( sort keys %$data ) {
my $count = $data->{$url} or next;
warn "[hatena] $url $count\n";
$out->{$url} = {
hatena => $count,
};
}
$out;
}
# ------------------------------------------------------------------------
sub check_delicious {
my $links = shift;
my $out = {};
foreach my $url ( @$links ) {
my( $count, $md5 ) = &count_delicious( $url );
next unless $count;
$out->{$url} = {
delicious => $count,
md5 => $md5,
};
}
$out;
}
# ------------------------------------------------------------------------
sub count_delicious {
my $url = shift;
my $md5 = Digest::MD5::md5_hex( $url );
my $get = "http://del.icio.us/url/".$md5;
my $ua = LWP::UserAgent->new();
my $AGENT = 'Mozilla/4.0 (compatible; delicious2json.pl)';
$ua->agent( $AGENT );
my $res = $ua->get( $get ) or return;
my $html = $res->content() or return;
my $count = ( $html =~ m#<h4[^>]*>[^<>]*this url has been saved by\D+(\d+)#s )[0] or return;
warn "[delicious] $url $count\n";
sleep 3;
wantarray ? ( $count, $md5 ) : $count;
}
# ------------------------------------------------------------------------
第1引数は -d (del.icio.us用)または -h(はてな用)のいずれか。
第2引数以降に、ブックマーク件数をチェックしたいページの URL が入っている
RDF/RSS/Atom ファイルのファイル名またはフィードの URL を指定する。
つまり、RSS に掲載されているページのブックマーク件数を取得する。
bash$ ./sbm2json.pl -d index.rdf > sbm-delicious.json
bash$ ./sbm2json.pl -h index.rdf > sbm-hatena.json
のように実行して JSON ファイルを生成します。
JSON ファイルからページ内に件数を表示するJavaScriptは省略。
あとでまとめたいね。
|