読者です 読者をやめる 読者になる 読者になる

Common Lispで(簡易)RSS解析

前書き

ちょっとCommon LispRSSでも解析してみようかとRoswellスクリプト紹介記事, GitHub)を書きました。

コード

※2015/09/13追記:roswellでインストールできる複数環境(ccl, clisp, sbcl)で試した見たのですが、cclでしか動かないようです。SBCLは日本語の扱いに問題がある模様で、CLISPは(ql:quickload :dexador)で落ちているようです。前者はSBCLでの日本語の扱い全般に影響があるようなので、設定でどうにかなる問題であればちょっとどうにかしたいのですが…。 → 結局、SBCLに関しては環境変数のLANGがCになっていただけでした…。むしろ何食わぬ顔で動いていたClozure CLの方が不思議です…。

解説もどき

HTTPクライアントとしてはDexadorを、RSSXML)パーサとしてはcxml(本家紹介記事)を使いました。といっても、関数を1つずつ呼び出しただけの使い方ですが。

始める前は、またDOMツリー解析ライブラリの使い方覚えないといけないんだろう面倒だなと思っていたのですが、cxmlではcxml-xmls:make-xmls-builderを指定することで全てリストに変換してくれました。リストさえ得られてしまえばこっちのものだということで上のようなサンプルコードができ上がりました。cxmlでは解析対象としてファイル名かバイナリ・ストリームを求めていたため、dex:getにwant-streamオプションを指定してストリーム形式で結果を受け取りました(デフォルトは文字列)。

細かいところは良いと思いますが、main関数内の(find-headered-lists "item" xmls-list)が実際にRSSのアイテムリストを抽出しているところです。リストを再帰的に探索して任意の条件にあったリストを一覧化するfind-lists-recursively関数ですが、少し困ったのがdolistでループしている部分です。リストの中に(1 . 2) のようなnil終端でないものが含まれるため、そのまま回すとエラーになります。今回はnil終端でないリストからnil終端のリストを作って返すmake-nil-tail-list関数を作ったのですが、普通はどうするものなんでしょう…。

なお、結果をファイルに書き出しているのは、単にsshクライアント+screenな環境で日本語を流されると画面が崩れることが多いのでそれを嫌っただけです。

RSSの仕様を読んだわけでもないのできっと何か間違ってます。現状は2箇所ほどRSSを引っ張ってきて動いたのでまあ大丈夫かなという適当な感じです。

後書き

Roswellいいですね。実際に使ってみるまでは実行系を簡単に切り替えられるという部分に着目していただけでしたが。今回のようなサンプルコードを書くだけの用途でも、これが一個の完結したコードです、と気軽に公開できて素敵です。使ってみて始めて実は必要としていたことに気づく類のものですね。