feedgeneratorを使って PythonでRSSを出力する

Python

このブログの RSSフィードを出力するコードを feedgeneratorで書いたのでその時のこと

Pythonで RSSを出力するためのモジュールはいくつかあるが、比較検討した結果 Django由来と言われる feedgenerator を採用してみることにする。

フィードの構築

entriesは出力したいエントリのリスト。

title = "My Blog"
link = "http://www.example.com/blog/"
feed_url = "http://www.example.com/blog/index.xml"
description = "私のブログです"

# フィードを生成
feed = feedgenerator.Rss201rev2Feed(title=title,link=link,feed_url=feed_url,description=description,language="ja")

# 生成したフィードに各エントリを追加
for entry in entries:
    title = entry["title"]
    link = entry["link"]
    description = entry["description"] if "description" in entry else None
    pubdate = entry["pubdate"] # datetimeオブジェクト。型が違う場合は要変換
    feed.add_item(title=title,link=link, description=description,pubdate=pubdate,unique_id=link)

unique_idは feedgenerator的にはオプションなのだが、付けないと W3Cの Feed Validation Serviceに叱られたので付けることにした。(unique_idには記事の URLをそのまま使うのが簡単)

フィードをXMLで出力する

フィードを XMLの string表現に変換するには writeString()を呼び出してやる。下記は Flaskで HTTPレスポンスとしてフィードを返す例。

response = flask.make_response(feed.writeString("utf-8"))
response.headers["Content-Type"] = "application/xml"
return response

pubdate属性に使用する datetimeオブジェクトの作り方

エントリの公開日時である pubdate属性だが、これには datetimeオブジェクトを渡すことになっている(適当に日付っぽい文字列を渡しても勝手に変換してはくれずエラーになる)。但し、datetimeオブジェクトを生成する際にタイムゾーンが指定されていないと pubdateは UTC扱いになってしまう。

全世界に向けて英語で書いているサイトであればそれでもいいかもしれないが、日本語で書かれた日本ローカル向けのサイトであれば公開日時のタイムゾーンは JSTにしておきたいところだ。

Pythonではタイムゾーンが未指定な日付時刻オブジェクトを "naive", タイムゾーンの指定されているものを "aware" と呼んでいるらしい。feedgeneratorは pubdateが naiveであれば UTC、awareであればそのタイムゾーンを出力する実装になっている。

datetimeオブジェクトの生成時にはタイムゾーンオブジェクトを渡すことが出来るようになっているのだが、Pythonの標準ライブラリにはタイムゾーンオブジェクトを生成する明快な手段がないので、pytzモジュールを使って JSTを表現するタイムゾーンオブジェクトを生成する。feedgeneratorは pytzを使用しているので、feedgeneratorがインストールされている環境なら pytzも使えるはずである。

timezone = pytz.timezone("Asia/Tokyo")
pubdate = datetime.datetime(year,month,day,hour,minute,second,ms,timezone)

datetimeオブジェクトは immutableなので、awareな日付時刻オブジェクトが欲しければ生成時にタイムゾーンを指定してやる必要がある(既に生成されている datetimeオブジェクトのタイムゾーン部だけを後から上書きするというようなことは出来ない)。

もしもデータベースなどのバックエンドから既に生成済みのdatetimeオブジェクトを得ており、かつそれが naive なものであったとしたならそれを awareに変換するためdatetimeオブジェクトを生成しなおす処理を自分で書いてやらなくてはならない。

公開日時を文字列で保持している場合

日付時刻文字列からdatetimeオブジェクトを得る方法として strptime 関数を使う方法があるが、残念なことに datetime.strptime() はタイムゾーンのパースに対応していない。

参考: datetime - Python strptime() and timezones? - Stack Overflow

どうしても文字列からタイムゾーン込みで datetimeをパースしたければ、標準ライブラリは諦めて python-dateutil を使う。

同じカテゴリの記事

Pythonで Scalaの findのように条件にマッチする最初の要素をリストから取得する 2014年1月18日
JSON APIを Pythonから呼び出して結果を表示する 2013年10月25日
Eclipse 3.6(Helios)に Pythonプラグイン PyDevを導入する 2010年7月31日

お勧めカテゴリ

英語でアニメ観ようず
なじみ深い日本製アニメの英語版DVDで、字幕と音声から英語を学びましょうという趣旨のシリーズ記事です。
ScalaのようでJavaだけど少しScalaなJSON API
Scalaと Spring Frameworkを使って REST的なJSON APIを実装してみましょう。
ドクジリアン柔術少女 すから☆ぱいそん
代表 嶋田大貴のブログです。写真は神仏に見せ金をはたらく罰当たりの図