RSSアンテナ作りました

http://panathenaia.halfmoon.jp/birdeyes/

やっぱり何番煎じかわからないのですが……。

愛用させていただいていたI knowが終了してしまって困ったことは、「複数のRSSをまとめた結果をRSSとして再出力できるWeb上のRSSリーダーがない」ということでした。(ダッシュボード上のRSSリーダーで更新チェックしてます)

で、Yahoo Pipesの存在を教えていただいて、しばらくそれを使っていました。こいつはGUIプログラミングでRSSを加工できるかなり楽しいツールなのですが、ふつーのRSSリーダーのようにサイトをひとつ追加しようと思えば、Fetch Feedを配置してUnionにつないで……と、まあ、めんどいわけです。そのせいですっかり購読しているサイトが少なくなってしまいました。

次に、無いなら自分で設置しよう、ということでCGIアンテナを探したわけです。その中ではRNAが私の要件を満たしてるっぽいです。

一応I knowでできてRNAでできないことはありまして、RNAはサイトごとに、最新記事だけを表示するか、各記事をばらして表示するかの設定ができません。各サイトの最新記事だけをまとめたRSS、各サイトの各記事を全部含めたRSSは作れます。その設定を混ぜることができません。I knowではできたんですよね。
例えば個人のブログサイトなんかは、更新されていることがわかれば充分ですので最新記事だけでよくて、むしろ過去の記事は混ざってほしくないわけです。
逆に、ニュースサイトなんかは、タイトルを見て開くかどうかを決めますので、全タイトル出てきて欲しくて、ブログとは逆に出元のニュースサイトがどこかは意識しないわけで、バラバラに時系列順に並んで欲しいわけです。

というわけでその機能付きの俺アンテナです。

あとI knowでできたことと言えば、RSSを公開していないサイトもdiff取ってRSSに載せてくれたのですが、はてなアンテナRSSを取り込めば実現できますので実装していません。負荷ははてなに負わせる作戦。

あとインポート/エクスポート形式は、ふつーOPMLと思うのですが、たまたまI knowのデータをLIRSでしか保存してなかったのでLIRSのみ対応してます。

実装の話

実装は……ほとんどwgetとlibxml2に丸投げのグルーコード全開です……。他にはgzip、libyamlなんかも使ってます。
ソースも置いてますが、私以外コンパイルできないだろうって点は自信がありますので、FreeBSDOSX用のバイナリが欲しい人がもしいれば用意できますです。

cronとか走らせる権限がありませんので、更新チェックはリクエストがある度に4件ずつ行ってます。どうせRSSリーダー(ダッシュボードウィジェッドの方)が30分に1回とかポーリングしてますのでこれで充分。俺アンテナを置く欠点として、相手サイトに負荷をかけてしまう(はてなアンテナ等の共用アンテナならユーザーが何人いても1リクエストで全員が幸せになれる)というのがあるのですが、これなら私のPCが動いてない時はリクエストも起きないってことになりますし……。

あ、あとwgetには-N付けてますので、負荷は最小限のはずです……はず……。


libxml2への愚痴
XMLは本当に使えるライブラリがありませんね……。何言ってんだオマエって言われそうです。
実際、XMLを前から順次パースするストリームパーサのライブラリを探しまくったのですが、libxml2しか無いのはどういうことでしょうか?
大抵、DOMかSAXです。DOMは、DOMを解釈してアプリケーションのデータに落とすのも、ストリームパーサの取ってきたイベントの列を解釈してアプリケーションのデータに落とすのも労力として変わりませんので、一旦DOMを作るだけメモリの無駄です。
SAXは、あちこちで言われてるように、使い辛いことこの上ないです。……何を考えてこんなものが生まれたんだか。SAXパーサライブラリの代表と思われるexpatはSAXの悪構造の中で頑張ってるのはわかりますが、それでもSAXは使いたくないです。あとAdaでXMLといったらXMLAdaですが、こいつもSAXです。
というわけでlibxml2しか選択肢が無いのですが、そのlibxml2は、循環参照と機能レイヤーの混同が酷いライブラリです。
しかも命名がバラバラで、各関数の動作はぱっと見でわからず、ソースコードは後から機能足しっぱなしで整理してないだろこれ……というのが読み取れて。そしてお目当てのreader(ストリームパーサ)は、DOMを作るパーサの上に作られているため、色々酷いです。XMLの全情報(特に先頭の<!だか<?だか書く部分)を内部では解釈してるくせにアプリケーションコードから取れないとか、どういうパーサライブラリですか……。
この手の依存関係はスキャナ←ストリームパーサ←DOMパーサの順になるべきってことに異論を唱える人はいないと思います。libyamlの爪の垢を煎じて飲むべきです。ああlibyamlのなんと美しいことか。
というわけで自分で作りたい病に侵されてる私はXMLパーサから作りたくなったのですが、よく考えてみると私はXMLが好きでもなんでもありませんでしたので、libxml2を使ってしまいました。
ただ労力的には、libxml2の動作を調べてる時間でもっとまともなXMLパーサを作れただろうなあ……orz
というわけで今までlibxml2を使ったことがなくて、これからlibxml2を使おうとされている方は、よろしければlibxml2を調べる時間を使って是非まともなXMLのストリームパーサを作ってくださいませ。