Fork me on GitHub

2008/10/27

はてな
以前、「はてなブックマークをPlaggerで同期する際の注意点」という記事で書いたXML::Feed::Atomが複数のsubjectを返せない件で、送ったパッチが取り込まれました。厳密にはちょっと変えられてますが。
はてなブックマークのRSSフィードにはblockquote引用文が含まれており、Atomを使った方が良いという記事でしたが難点としてPlaggerで使用しているXML::Feed::Atomには複数のsubjectつまりタグを返せる仕組みがなかった為、別のソーシャルブックマークへポストした際にタグが削られてしまう事になっていました。
簡単な例で言うと
use strict;
use warnings;
use XML::Feed;
my $feed = XML::Feed->parse(URI->new('http://b.hatena.ne.jp/mattn/atomfeed'))
    or die XML::Feed->errstr;
for my $entry ($feed->entries) {
  print $entry->link."\n";
  print "[$_]" for $entry->category;
  print $entry->summary->{body};
  print "\n";
}
というコードに対して、以前までのXML::Feed::Atomだと
http://b.hatena.ne.jp/mattn/20081024#bookmark-10541285
[coderepos]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10541123
[coderepos]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10538485
[wsgi]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10534904
[googleappengine]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10531400
[]てかRSS意識しすぎw そんなに気になるか。
http://b.hatena.ne.jp/mattn/20081024#bookmark-7152814
[webfont]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10530774
[vimperator]Include this patch f*ck でok
http://b.hatena.ne.jp/mattn/20081023#bookmark-10527748
[perl]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10529111
[chrome]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10522215
[catalyst]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10520297
[dojo]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10516769
[igoogle]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10513534
[ruby]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512893
[merb]merbでscaffold
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512804
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512802
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-9671938
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512759
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-9696628
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512388
[perl]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10498444
[lighttpd]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10504059
[]prototype.jsかぁ…。
http://b.hatena.ne.jp/mattn/20081022#bookmark-10502783
[]
http://b.hatena.ne.jp/mattn/20081021#bookmark-10489204
[vimperator]rcが先す
http://b.hatena.ne.jp/mattn/20081021#bookmark-10488856
[softbank]
http://b.hatena.ne.jp/mattn/20081021#bookmark-10484808
[blosxom]
http://b.hatena.ne.jp/mattn/20081021#bookmark-10488095
[]
http://b.hatena.ne.jp/mattn/20081020#bookmark-7686515
[テスト]TeSt
http://b.hatena.ne.jp/mattn/20081019#bookmark-10465795
[]
http://b.hatena.ne.jp/mattn/20081019#bookmark-10460236
[perl]
こんな形にタグが1つ以上出力されず、しかも空の配列として得られたりしていましたが、XML::Feed 0.22以降だと
http://b.hatena.ne.jp/mattn/20081024#bookmark-10541285
[coderepos][oops]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10541123
[coderepos]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10538485
[wsgi]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10534904
[googleappengine][appengine]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10531400
てかRSS意識しすぎw そんなに気になるか。
http://b.hatena.ne.jp/mattn/20081024#bookmark-7152814
[webfont]
http://b.hatena.ne.jp/mattn/20081024#bookmark-10530774
[vimperator]Include this patch f*ck でok
http://b.hatena.ne.jp/mattn/20081023#bookmark-10527748
[perl]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10529111
[chrome]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10522215
[catalyst]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10520297
[dojo]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10516769
[igoogle][google]
http://b.hatena.ne.jp/mattn/20081023#bookmark-10513534
[ruby][rails]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512893
[merb]merbでscaffold
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512804
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512802
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-9671938
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512759
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-9696628
[merb]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10512388
[perl][twitter][wassr]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10498444
[lighttpd]
http://b.hatena.ne.jp/mattn/20081022#bookmark-10504059
prototype.jsかぁ…。
http://b.hatena.ne.jp/mattn/20081022#bookmark-10502783

http://b.hatena.ne.jp/mattn/20081021#bookmark-10489204
[vimperator]rcが先す
http://b.hatena.ne.jp/mattn/20081021#bookmark-10488856
[softbank]
http://b.hatena.ne.jp/mattn/20081021#bookmark-10484808
[blosxom]
http://b.hatena.ne.jp/mattn/20081021#bookmark-10488095

http://b.hatena.ne.jp/mattn/20081020#bookmark-7686515
[テスト]TeSt
http://b.hatena.ne.jp/mattn/20081019#bookmark-10465795

http://b.hatena.ne.jp/mattn/20081019#bookmark-10460236
[perl]
こんな感じの出力になります。 今回の修正により手放しで、はてなブックマークAtomフィードをdelicios等にポスト出来る様になります。

めでたしめでたし
Posted at 09:46 in ソフトウェア::lang::perl | WriteBacks (0)
Tagged as: atom, perl, xml
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip | add to buzzurl add to buzzurl | add to fc2bookmark add to fc2bookmark | add to Yahoo Bookmark add to Yahoo Bookmark | add to Pookmark add to Pookmark

2007/10/21

はてな
私は、Plaggerを使用して、はてなブックマークを別のソーシャルブックマークに同期していますが、その際ブックマークタグがどのように扱われるかについて以下説明します。
はてなブックマークのフィードは
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>
      &lt;blockquote cite="http://coderepos.org/share/changeset/552" title="Changeset 552 - CodeRepos::Share - Trac"&gt;
        
        &lt;cite&gt;&lt;a href="http://coderepos.org/share/changeset/552"&gt;Changeset 552 - CodeRepos::Share - Trac&lt;/a&gt; &lt;a href="http://b.hatena.ne.jp/entry/http://coderepos.org/share/changeset/552"&gt;&lt;img src="http://b.hatena.ne.jp/images/entry.gif" title="このエントリーを含むブックマーク" alt="このエントリーを含むブックマーク" border="0"&gt;&lt;/a&gt;&lt;/cite&gt;
      &lt;/blockquote&gt;
      &lt;p&gt;笑わせて頂きました&lt;/p&gt;
    </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
※2
Nifty Clip RSS1.0 タグ毎にdc:subject
※3
Blue Dot RSS2.0 単一のdc:subjectをカンマでセパレート
Digg RSS2.0 出力されない
※1 このフィードはちょっと頂けない
※2 入力UIは単一行だがダブルクオート記述出来る
※3 入力UIはjavascriptで追加形式(POSTは1個もしくは配列)
各サービス毎にdc:subjectの扱われ方はまちまちです。
これらの仕様を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を使うってのもアリですね。
Posted at 01:43 in ソフトウェア::lang::perl | WriteBacks (0)
Tagged as: atom, perl, plagger, rss
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip | add to buzzurl add to buzzurl | add to fc2bookmark add to fc2bookmark | add to Yahoo Bookmark add to Yahoo Bookmark | add to Pookmark add to Pookmark