抜け道探して遠まわり
きまぐれびゅーの各ページでFeed配信したいな
↓
でも、いちいちRSSとかAtomのXML構造考えてテンプレートとか作るのって、すごく面倒じゃない?
↓
きっと探せば、PythonのFeed作成用ライブラリとかあるさ。
↓
うーん、たとえばPyRSS2Genとか見つけたけど、UTF-8対応じゃないみたいだし……いまいち使い辛そう。
↓
やっぱ、地道にぽちぽちやるしかないのかなぁ……。
↓
まてよ、そういえば、Google App Engineが標準で採用しているdjangoって、いろんな機能ついてるんじゃないっけ?simplejsonとかもあったし……。
↓
お、C:\Program Files\Google\google_appengine\lib\django\django\utils に feedgenerator.py とかある、それっぽくない?
↓
検索してみたら……おおっ、どうやらそのものみたい→配信フィードフレームワーク ― Django v1.0 documentation
と、実際のコード組むより、探す方に圧倒的に時間を食ってしまいました。
そのFeed配信用のコードをさらしてみる
で紹介したFeed配信用のコードです。
# -*- coding: utf-8 -*- """ ■ Amazon カスタマーレビュー配信 Feed 作成 """ import sys,os,cgi,re,urllib,logging,cgi import datetime import wsgiref.handlers from django.utils import feedgenerator from google.appengine.ext import webapp from google.appengine.ext.webapp import template from awslib import AwsSearch SITE_BASE=u'http://honnomemo.appspot.com/amazonreview?asin=' CONTENT_TYPE_XML='text/xml' CONTENT_TYPE_XML_RSP=CONTENT_TYPE_XML+'; charset=utf-8' CONTENT_TYPE_HTML='text/plain' DEFAULT_CACHE_TIMEOUT=900 class showFeed(webapp.RequestHandler): def get(self): kind=self.request.get('kind','rss') if kind=='atom': fncfeed=feedgenerator.Atom1Feed elif kind=='rss': fncfeed=feedgenerator.Rss201rev2Feed else: self.error(400) return asin=urllib.unquote(re.compile(r'^.*/feed/(.*)/.*$').sub(r'\1',self.request.url)) awssrch=AwsSearch() info=awssrch.getSingleInfo(asin,getreviewlink=True,response=['Small','Reviews']) if not info or not info.get('Item') or str(info.Item[0].ASIN)!=asin: self.error(404) return item=info.Item[0] attrib=item.ItemAttributes crev=item.CustomerReviews sitelink=SITE_BASE+asin description=u'きまぐれびゅー:『'+attrib.Title+u'』のAmazonカスタマーレビュー' avestr=crev.get('AverageRating',None) if avestr: description+=u'(おすすめ度:星%s)' % (avestr) feed=fncfeed( title=attrib.Title , link=sitelink , description=description , language=u'ja' ) for review in crev.Review: reviewer=review.Reviewer author=reviewer.get('Nickname',None) cid=review.get('CustomerId',None) if not author: author=reviewer.get('Name',None) if not author: author=cid if cid else u'(非公開)' yyyy,mm,dd=review.Date.split('-') dobj=datetime.datetime(int(yyyy),int(mm),int(dd),0,0) dobj-=datetime.timedelta(hours=9) link=review.get('PermaLink',sitelink) description=u'<p><img src="http://g-ecx.images-amazon.com/images/G/09/x-locale/common/customer-reviews/stars-%s-0._V45731007_.gif" alt="星%sつ" border="0"/></p>' % (review.Rating,review.Rating) description+=review.Content feed.add_item( title=review.Summary , link=link , description=description , author_name=author if kind=='atom' else None , author_email=author if kind=='rss' else None # RSS 2.0 仕様では author 要素は e-mail アドレス , author_link=u'http://www.amazon.co.jp/gp/pdp/profile/'+cid+u'/ref=cm_cr_dp_pdp' if cid else '' , pubdate=dobj ) self.response.headers['Content-Type']=CONTENT_TYPE_XML_RSP self.response.out.write(feed.writeString('utf-8')) def main(): application = webapp.WSGIApplication([ ('/amazonreview/feed/.*', showFeed) ],debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main()
配信フィードフレームワーク ― Django v1.0 documentationの高水準フレームワークの方はなんだか難しくてよくわからなかったので(苦笑)、低水準フレームワークの基本機能のみ使ってます。
概要
Feed作成に関するところだけ抜粋すると。
from django.utils import feedgenerator
でfeedgeneratorをimport し、例えばRSS 2.0なら
feed=feedgenerator.Rss201rev2Feed( title=[サイトタイトル(必須)] , link=[サイトリンク(必須)] , description=[サイト概要(必須)] , language=[言語(u'ja'とか適当にセットしたけど、あってるのか?u'ja-jp'とか?) )
で大元を作り(Rss201rev2Feedの代わりに、RSS 0.91ならRssUserland091Feed、Atom 1.0ならAtom1Feedになる)
feed.add_item(
title=[アイテムのタイトル(必須)]
, link=[アイテムのリンク(必須)]
, description=[アイテムの概要(必須)]
, author_email=[アイテムの著者名(RSS 2.0の場合:仕様上はメールアドレスだが、そうでなくても受付はする)]
, author_name=[アイテムの著者名(Atomの場合)]
, author_link=[アイテムの著者のリンク]
, pubdate=[日付:Python datetime 型オブジェクト(datetime.datetime()とかdatetime.datetime.now()とかの戻り値)]
)
で、各アイテムを追加していく感じ(その他のオプションは上で紹介したサイトとかで随時調べてください)。
全て追加しおわったら、
result=feed.writeString('utf-8')
で文字列(上記例ではUTF-8としてencode済みの文字列)として取得できるので、後は適当に
self.response.headers['Content-Type']='text/xml; charset=utf-8' self.response.out.write(result)
のようにして出力してやればよいだけ、みたいです。かなりお手軽だと思いました。