XML::Atomで任意のはてなユーザの はてなブックマークをコンソールにリストアップするテスト

この前は、はてなブックマークにエントリーをpostするテストをしたので、今回は任意の はてなユーザはてなブックマークAtom feedを取ってきてリストアップするPerlスクリプトを書いてみました。単にリストアップするだけなので、全然面白くありませんね(汗。

$ emacs listup.pl
#!/usr/bin/perl
use strict;
use warnings;
use XML::Atom::Entry;
use XML::Atom::Client;

my $feed_url = shift or die "usage: $0 <atomfeed url> [limit]";
my $limit    = shift || 10;

our $dc = XML::Atom::Namespace->new(
    dc => 'http://purl.org/dc/elements/1.1/'
);

my $client = XML::Atom::Client->new;
$client->{ua}->proxy(['http', 'ftp'],
    'http://my.proxy'
);

my $bm_count = 1;
for (;;) {
    &print_progress($feed_url);
    
    my $feed    = $client->getFeed($feed_url) or warn $client->errstr;
    my $entries = $feed->entries;
    my @links   = $feed->link;
    
    foreach my $entry ($feed->entries) {
        &print_entry($entry, $bm_count);
        exit if (++$bm_count > $limit);
    }
    
    $feed_url = '';
    foreach my $link(@links) {
        $feed_url = $link->href if ($link->rel eq 'next');
    }
    last if ($feed_url eq '');
}

sub print_progress {
    my $feed_url = shift;

    my $bar = "-" x 70 . "\n";
    print $bar;
    print $feed_url, " を取得中...\n";
    print $bar;
}

sub print_entry {
    my ($entry, $entry_number) = @_;

    my $title   = $entry->title;
    my $url     = $entry->link->href;
    my $summary = $entry->summary;
    my @tags    = $entry->getlist($dc, 'subject');
    my $issued  = $entry->issued;

    print "# $entry_number\n";
    print "Title:   $title\n";
    print "URL:     $url\n";
    print "Summary: $summary\n";
    print "Tag:     ";
    foreach my $tag (@tags) {
        print "[$tag]";
    }
    print "\n";
    print "Issued:  $issued\n\n";
}

このコードを実行すると以下のようになります。試しにid:naoyaさんの はてなブックマークの直近100件をリストアップしてみます。

[ysano@fedora perl]$ perl listup.pl http://b.hatena.ne.jp/naoya/atomfeed 100
----------------------------------------------------------------------
http://b.hatena.ne.jp/naoya/atomfeed を取得中...
----------------------------------------------------------------------
# 1
Title:   MODULE.JP - 再帰的な木を描く"JavaScript"のソースコード
URL:     http://module.jp/blog/js_tree.html
Summary:  カッとなってこんな Hack してしまうあたり、さすがマジシャン...
Tag:     [javascript]
Issued:  2005-11-01T03:48:30+09:00

# 2
Title:   mysql:12312
URL:     http://www.mysql.gr.jp/mysqlml/mysql/msg/12312
Summary:  innodb_thread_concurrency のデフォルトの値が異なるらしい。この条件を同一にしてベンチするべしと。
Tag:     [mysql]
Issued:  2005-11-01T03:09:15+09:00

[...]
----------------------------------------------------------------------
http://b.hatena.ne.jp/naoya/atomfeed?of=20 を取得中...
----------------------------------------------------------------------
# 21
Title:   グーグルの歴史|ユースケース  〜Web2.0勉強ブログ〜
URL:     http://ameblo.jp/tabunsoturon/entry-10005607852.html
Summary:  こうやってまとめて見るとまた違って面白い。
Tag:     [google]
Issued:  2005-10-30T17:21:36+09:00

# 22
Title:   antipop2.0: Emacs 事始め
URL:     http://antipop.gs/mt/2005/10/29/233221
Summary:  C-g 連打しる
Tag:     [emacs]
Issued:  2005-10-30T07:07:12+09:00

[...]
# 100
Title:   TAG INDEX : HTMLタグの読み方アンケート結果
URL:     http://www.tagindex.com/statistics/tag_name/index.html
Summary:  タグの読み方。いろいろあるね。
Tag:     [html]
Issued:  2005-10-18T13:19:37+09:00

http://b.hatena.ne.jp/****/atomfeedでは直近20件分のデータしか取得できません。しかしそこはちょっと工夫をして、Atom feedにあるlink要素のrel属性が"next"であるlink要素のhref属性の値 (XPathで表現すると「/feed/link[./@rel="next"]/@href」 ?)を見て、次々とそれ以降のAtom feedをゲットするようにしました。これで任意のはてなユーザーはてなブックマークを、やろうと思えば、すべてゲットできます。夢が広がりますね。このコードを発展させれば面白いことができそうです。今からやろうとしていることは秘密です(笑。

追記 (11/02 06:15)

自分のはてなブックマークを漁っていたら、

というエントリーをブックマークしていたことが判明しました(汗。

ちょっと比較して、思ったことは以下の通りです。

  • XML::Atom::Clientの「getFeed()」は使わずにLWPで自前でAtom feedをゲット
  • 次のAtom feedを取得する前にsleepさせているので、はてなサーバに優しい
  • 次のAtom feedのURLを取得する所のコードの書き方が似ている(もっとエレガントな書き方がないものか?)
  • ファイルへの書き込みは、当然FileHandleモジュールを使用
  • 当たり前だけど、プライベートモードのAtom feedは取得できない(私のこのエントリーのタイトルで「任意のはてなユーザ...」と言っていますが、任意ではないですね...)

追記 (11/12 08:40)

このエントリーで紹介したコードの改善について、新たにエントリーを書きました。本当に些細なことですが。。。