はてなブックマークのフィードは
RSS形式
http://b.hatena.ne.jp/[hatena account]/rss
もしくはAtomFeed形式
http://b.hatena.ne.jp/[hatena account]/atomfeed
というURLで提供され、データには以下の様な物が含まれています。
※以下の例はRSSの場合
<item rdf:about="http://coderepos.org/share/changeset/552">
<title>Changeset 552 - CodeRepos::Share - Trac</title>
<link>http://coderepos.org/share/changeset/552</link>
<description>笑わせて頂きました</description>
<content:encoded>
<blockquote cite="http://coderepos.org/share/changeset/552" title="Changeset 552 - CodeRepos::Share - Trac">
<cite><a href="http://coderepos.org/share/changeset/552">Changeset 552 - CodeRepos::Share - Trac</a> <a href="http://b.hatena.ne.jp/entry/http://coderepos.org/share/changeset/552"><img src="http://b.hatena.ne.jp/images/entry.gif" title="このエントリーを含むブックマーク" alt="このエントリーを含むブックマーク" border="0"></a></cite>
</blockquote>
<p>笑わせて頂きました</p>
</content:encoded>
<dc:date>2007-10-19T21:19:44+09:00</dc:date>
<dc:creator>mattn</dc:creator>
<dc:subject>coderepos</dc:subject>
<dc:subject>erogeek</dc:subject>
<taxo:topics>
<rdf:Bag>
<rdf:li resource="http://b.hatena.ne.jp/t/coderepos" />
<rdf:li resource="http://b.hatena.ne.jp/t/erogeek" />
</rdf:Bag>
</taxo:topics>
</item>
ブックマークした元リンクのtitle/linkに加え、ブックマークコメントが格納されたdescription、およびblockquote/citeタグを使用して引用元形式に表現されたcontent:encoded、さらにはブックマークタグを表現するdc:subjectが記述されています。Plaggerの場合、descriptionよりもcontant:encodedを優先しており、コメントとしては冗長な引用部分が転送されてしまいます。これについては先日書いた「Plaggerで、はてなブックマークをdel.icio.usにミラーする時に、descriptionフィールドを衛生的に修正するフィルタプラグイン書いた」にある様にdescriptionをcontent:encodedに上書きしてやる事で対応出来ます。
先日この記事を書いた際、otsuneさんから「この目的であれば、 b.hatena.ne.jp/[hatena user]/atomを Filter::AtomLinkRelated すればOk」というブックマークコメント頂きました。
昨日、頂いたアドバイスの通りAtomFeedで試して見た所、複数設定した筈のブックマークタグが一つだけしか適応されないという現象が発生しました。
IRC(#plagger-ja)でotsuneさん、国内滞在説のあるmiyagawaさんに相談しながら原因を当たった所、昨日の夜にXML::Feedでのdc:subjectの扱い方に問題があるのではないかという事が分かりました。
ここで見て頂きたいのはdc:subjectというノード。dc:subjectは私の記憶ではAtom0.3では厳密に個数は規定されておらず、複数記述する事も出来てしまっています。結果、規定されていないことで色んな実装が表れてしまっています。
はてなの様に複数のdc:subjectを使って表現する物もあれば、del.icio.usの様に一つのdc:subject内に空白(スペース)等でセパレートしてタグを記述している物もあります。
以下、私が簡単に調べた各サービスのフィード出力状況と、そのフィード内のdc:subjectの扱われ方です。
サービス フィード形式 dc:subjectの扱い はてなブックマーク RSS1.0
Atom0.3タグ毎にdc:subject del.icio.us RSS1.0 単一のdc:subjectを空白でセパレート Livedoor Clip RSS2.0 タグ毎にdc:subject Buzzurl RSS1.0 タグ毎にdc:subject Goo Bookmark RSS1.0 出力されない FC2 Bookmark RSS2.0
※1出力されない Pookmark Airlines RSS1.0 タグ毎にdc:subject
※2Nifty Clip RSS1.0 タグ毎にdc:subject
※3Blue Dot RSS2.0 単一のdc:subjectをカンマでセパレート Digg RSS2.0 出力されない
※1 このフィードはちょっと頂けない各サービス毎にdc:subjectの扱われ方はまちまちです。
※2 入力UIは単一行だがダブルクオート記述出来る
※3 入力UIはjavascriptで追加形式(POSTは1個もしくは配列)
これらの仕様をXML::Feedがどのように扱っているかが原因ではないかと思いました。
現状、XML-Feed-0.12のソースでは
lib/XML/Feed/Atom.pm(146):
sub category {
my $entry = shift;
my $ns = XML::Atom::Namespace->new(dc => 'http://purl.org/dc/elements/1.1/');
if (@_) {
$entry->{entry}->add_category({ term => $_[0] });
} else {
my $category = $entry->{entry}->category;
$category ? ($category->label || $category->term) : $entry->{entry}->get($ns, 'subject');
}
}
となっていますが、上記"get"ではXML::Atomの"get"が呼ばれ、ARRAYの先頭しか返りません。XML::Atomには"get"ではなく"getlist"も用意されており、こちらの方はARRAYを返してくれる仕様になっています。
(XML::Feed::RSSの方は元々categoryでARRAYを返す場合もある為、baseであるEntryは既にARRAYを返されても問題ない準備が出来ています)
dc:subjectが単一とは規定されていない事、XML::Atomで"getlist"が用意されている事を、XML::FeedのAUTHORであるBenjamin Trott氏にメールし、パッチも付けて送付しました。
どんな返事が返って来るか分かりませんが、これが正しい修正だとすればXML::Feedのアップグレードで直って来るかもしれません。
しばらくは、はてなブックマークからの同期はrssフィードを使いdescriptionからcontent:encodeを上書きするようなトリックを使うか、AtomFeedを使ってしかも上記の様な修正を入れて対応するかになります。
もしかしたら、Plagger側にcontent:encoded->summaryではなく、description->summaryとなるようなオプション入れても良いかも知れませんね。
それかtsupoさんのbookeyを使うってのもアリですね。