Google のサービスと連携するには Google Data API を使う。Googleが公式にサポートしているので、とても安心して使える。RSS リーダーとしてよく使われている Google Reader 用のAPI も。。。は、まだ公式には無い。
まぁ、色々な人が解析しており、GoogleReaderAPIのページが、詳細にまとまっている。
なので、Google 提供の python ライブラリで、Google Reader API を叩いてみた
ただ、サンプルを書いたあとで、pyrfeed内にGoogleReader 用のライブラリが含まれていたのに気付いたので、そっちを使うのがいいのかも。
インストール
MacPorts を使っているので、さくっとインストール。
% sudo port install py27-gdata
そうでないならば、gdata-python-clientから最新版をインストールする。
Google Reader 用の下準備と認証
gdata-python-client には、Reader サービスの固有の API は無いので、ベースのモノを適当に設定する必要がある。
import gdata.service
config = { 'Email': 'foobar@gmail.com', 'Passwd': 'password' }
# Google Reader サービス設定
service = gdata.service.GDataService(account_type='GOOGLE',
service='reader',
server='www.google.com',
source='MyReaderHoge')
# Google アカウント設定とログイン
service.ClientLogin(config['Email'],config['Passwd'])
# 認証トークン(SIDの値)
print service.GetClientLoginToken()
# 書き込み用のトークンの取得
token = service.Get('/reader/api/0/token',converter=lambda x:x)
print "token:", token
'api/0'
以下のレスポンスが AtomPub 形式では無く、小細工が必要である。gdata-python-clientには、ちょうど隙間が開いてるようである。。。
未読件数を取得
'api/0/unread-count'
を JSON 形式で取得する
query = gdata.service.Query(feed='/reader/api/0/unread-count',
params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
unreadcounts = feed['unreadcounts']
# 全体の未読数を一番前に移動しとく
for i, item in enumerate(unreadcounts):
if re.match(r'^user/\d+/state/com.google/reading-list$',item['id']):
unreadcounts.pop(i)
unreadcounts.insert(0,item)
break
# 全体の未読数
print int(unreadcounts[0]['count'] if len(unreadcounts) > 0 else 0)
#=> 1
# 未読があるラベルとその未読数
for item in unreadcounts:
if not re.match(r'^user/\d+/label',item['id']): continue
print "count:%(count)s id: %(id)s" % item
#=> count:1 id: user/16814486509924941024/label/android
すべてのラベルを取得
query = gdata.service.Query(feed='/reader/api/0/tag/list',
params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
tags = feed['tags']
for item in tags:
tag = re.sub(r'^user/\d+/',r'',item['id'])
print "tag: %s" % tag
#=> tag: state/com.google/starred
#=> tag: state/com.google/broadcast
#=> tag: label/android
#=> tag: label/misc
#=> tag: label/neta
#=> tag: state/com.blogger/blogger-following
ラベルを指定して取得
android 関連の記事を 5 件見てみるかいな。。。
query = gdata.service.Query(feed='/reader/atom/user/-/label/android',
params={'n': str(5)})
feed = service.Get(query.ToUri())
for entry in feed.entry:
print "===="
dom = xml.dom.minidom.parseString(entry.ToString())
print dom.toprettyxml(indent=" ")
print "===="
print "href: %s" % entry.GetHtmlLink().href
print "title: %s" % entry.title.text
# print "%s" % entry.summary.text
未読を既読に変更
先の記事は、読んだから既読にする。
# token, feed は、上に記載の書き込み用トークンと直前で取得した記事リスト
for entry in feed.entry:
i = entry.id.text
s = entry.source.extension_attributes['{http://www.google.com/schemas/reader/atom/}stream-id']
ret = service.Post(urllib.urlencode({'i':i,
'a':'user/-/state/com.google/read',
's':s,
'T':token,
}),
'/reader/api/0/edit-tag',
converter=lambda x:x,
extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print i,ret
何でも無いが、この部分には半日悩んでしまった。
何気ない POST パラメータを送信する POST 処理なのだが、gdata.service.Post
は aplication/atom+xml
形式のデータ送信を想定するため、明示的に Content-Type
を指定する必要がある!気づくまで、「400 Bad Request
」+「X-Reader-Google-Bad-Token: true
」に悩まされてしまった。
新しいフィードを登録
sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
'ac': 'subscribe',
'T':token,
}),
'/reader/api/0/subscription/edit',
converter=lambda x:x,
extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'subscribe',ret
購読しているフィードを解除
sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
'ac': 'unsubscribe',
'T':token,
}),
'/reader/api/0/subscription/edit',
converter=lambda x:x,
extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'unsubscribe',ret
0 件のコメント:
コメントを投稿