はてなブックマークでタグを付けていないエントリーに仮にタグ付けするスクリプト

はてブからタグ付けしていないエントリーを探し出して仮にタグ付けするスクリプトを書いみた。本当は、はてブ側でタグ付けしていないエントリーを表示する機能があると嬉しいのですけど、その手の要望は、
はてなアイデア - タグの付いていないものを一括で表示する 未分類タグが欲しいです
こんな具合に旧はてブ時代から塩漬けになっており、また、リニューアルで検索性が高まったことでこの先も望み薄っぽいので、自分で何とかしてみようと。

#!/usr/bin/perl
use strict;
use warnings;
use XML::Atom::Client;

#はてなアカウントのIDとパスワード
my $username = '****';
my $password = '****';

#付けるタグ
my $tag = "[*]";

my $url = 'http://b.hatena.ne.jp/dump';
#エクスポート機能からの一括取得に失敗する場合は、
#ユーザーのフィードを利用する。キャッシュが効いているので要注意。
#my $url = "http://b.hatena.ne.jp/$username/atomfeed";

my $sleepTime = 1;

#ブクマのコメントを編集
sub updateSummary{
    my ($api, $url, $summary) = @_;

    my $entry = XML::Atom::Entry->new;
    $entry->add(undef,'summary',$summary,{type => 'text/plain'});

    my $res = $api->updateEntry($url,$entry) or die $api->errstr;
    return $res;
}

#フィードからタグ付けしていないブクマのEditURIとsummary、フィードの続きのurlを取得
sub getNotTaggedEntries{
    my ($url,$api) = @_;
    my $dc = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/');
    my @notTaggedEntries;
    my $nextUrl;
    my $feed;

    if(ref($api) eq 'XML::Atom::Client'){
        $feed = $api->getFeed($url);
    }else{
        $feed = XML::Atom::Feed->new($url);
    }

    foreach my $link ($feed->link){
        if($link->rel eq 'next'){
            $nextUrl =  $link->href;
        }
    }

    foreach my $entry ($feed->entries){
        my $tags = $entry->getlist($dc,'subject');
        if(!$tags){
            foreach my $entryLink ($entry->link){
                if($entryLink->rel eq 'service.edit'){
                    push(@notTaggedEntries,{
                            editUrl => $entryLink->href,
                            summary => $entry->summary
                        });
                }
            }
        }
    }

    return {entries => \@notTaggedEntries, nextUrl => $nextUrl};
}

my $api = XML::Atom::Client->new;
$api->username($username);
$api->password($password);

do{
    print "feed: $url\n";
    my $res = &getNotTaggedEntries($url,$api);
    $url = $res->{nextUrl};

    foreach my $entry (@{$res->{entries}}){
        print "\t$entry->{editUrl}\n";
        &updateSummary($api, $entry->{editUrl}, $tag . $entry->{summary});
        sleep $sleepTime;
    }

}while($url);

エクスポート機能から自分のブックマークをAtom形式で一括取得してタグを付けていないエントリーを探し出し、はてブAtomAPIを使って仮のタグを付けていきます。エクスポート機能のアドレスは以下。要認証。

my $url = 'http://b.hatena.ne.jp/dump';

で、このエクスポート機能なんですが、応答が無かったり違う形式が返って来たりとおかしい時があるので、そういう時はユーザーごとに用意されている /atomfeed の方を使ってもよし。こっちは認証無しで取れる。

my $url = "http://b.hatena.ne.jp/$username/atomfeed";

ただこっちは20件ずつしか取得できないのでブクマが多いと時間がかかるし、キャッシュが効くようになっているみたいで、一度タグ付けをした後に時間を置かずにもう一度実行してしまうと、実際にはタグが付いているのにキャッシュによってタグが無いという情報が取得されてしまい、結果的にタグが二重に付いてしまうので注意。