Python Google Notebook API
Python Google Notebook API を使ってみた。
Poly9 blog Blog Archive (unofficial) Python Google Notebook API
http://blog.poly9.com/?p=19
上記のサイトにあるpythonのライブラリを使ってこねこねしようと思いきや、これがすんなりとは動かず。。
色々調べてみた結果、どうやらこのライブラリが作成された後にGoogle Notebookの方でAjaxリクエスト関連のプロトコルバージョンが上がっていて動かないっぽいことが発覚(もちろんGoogleはまったく悪くない)。
どうやらhttp://www.google.com/notebook/read系のURLが全滅っぽいので調べてみると、それらのURLは以下のようなレスポンス>を返しているらしい。
#実際にはインデントされてません
[ B( 'BDQRhIgoQmaK7gOkh', 'bar hoge note', 1159662160953, 1159662151077, 1159676252709, '', 0, 0, '', 0, '', [ S( 'SDQRhIgoQmqK7gOkh', '', 0, [ N( 'NDQ02IgoQo9vUgOkh', 'foo ', 'myname@gmail.com', [], 'null', 1159662557859, 1159662557871, 0 ), N( 'NDT7kIgoQ55DVgOkh', 'bar ', 'myname@gmail.com', [], 'null', 1159662566711, 1159662566720, 0 ), N( 'NDRQYIwoQobnVgOkh', 'buzz ', 'myname@gmail.com', [], 'null', 1159662569889, 1159662569893, 0 ) ] ) ] ) ]
python API側ではこの出力を受けて、以下の定義を使用してそのままevalしてます。
class NotebookObj: """ A minimalistic notebook container. """ def __init__(self, *args): self.key = args[0] self.name = args[1] self.entries = args[7] class NotebookEntry: """ A minimalistic notebook entry container """ def __init__(self, *args): self.key = args[0] self.content = args[1] # This is a wrapper function # that we use to get the notebook entries def extractEntries(*args): return args[3] # Some obfuscation bindings. May not work in the future N = NotebookEntry S = extractEntries B = NotebookObj
で、フォーマットが変わると例外がraiseされて終了って感じです。使えませんでした、終了というのもあれなので、とりあえず標準入力から読んで、それをGoogle Notebook に新規エントリーとして追加するデモを作ってみました。
まずはオリジナルのライブラリに今回必要な箇所だけ修正が入れたパッチを作成しました。以下の箇所が「部分的に」修正されています(中途半端!(--;;)
- プロトコルバージョンが古くて情報が取得出来ていない
- raiseしている例外が定義されていない
デモスクリプトを実行するために、上記のパッチを以下の手順であてます(python2.4以上が必要)。
$ wget http://www.poly9.com/developers/gnotebook/google_notebook_api.pys -O google_notebook_api.py $ wget http://scalar.jp/sandbox/python/gnote/gnote.patch $ patch < gnote.patch
で、実際のソースはこんな感じです。
#!/usr/bin/env python import sys, getpass, urllib from google_notebook_api import * # read text from stdin # - add pre tag for formatting(there may be a better way...) contents = "" for line in sys.stdin: contents = contents + line contents = "<pre>%s</pre>" % contents # code to avoid EOFError # http://www.velocityreviews.com/forums/t356411-mysterious-eoferror.html sys.stdin = open('/dev/tty') username = raw_input('username: ') passwd = getpass.getpass('passwd: ') try: g = GNotebook(username, passwd) except: print >> sys.stderr, "login failure." sys.exit(1) # select notebook print "-- your note books --"; i = 0 notebooklist = g.listNotebooks() for notebook in notebooklist: print " [%d] %s" % (i, notebook) i += 1 target_index = raw_input('which notebook?: ') print "target_index=[%s]" % target_index try: target = notebooklist[int(target_index)] except Exception, e: print "args=[%s]" % e.args print >> sys.stderr, "no such notebook." sys.exit(1) entry_title = raw_input('title: ') # post try: g.addNote(target, entry_title, urllib.quote(contents), ""); print "OK" except Exception, e: print "args=[%s]" % e.args print >> sys.stderr, "post data failed." sys.exit(1) sys.exit(0)
このスクリプトは、標準入力から文字列を受けて、ユーザ名とパスワード、保存先のnotebookの入力を対話的に受け取ってそれを新規エントリとして保存します。短いスクリプトでいけてないところもあるのですが、以下のような感じで一応動作します。
$ perl -v | python gnote.py username: bonarster passwd: -- your note books -- [0] ClearSilver [1] bar hoge note [2] My Notebook [3] mysandbox [4] my note book which notebook?: 3 target_index=[3] title: perl -v OK
すると、
できた!なんかちょっと嬉しい!
これPerlとかでもっと気合い入れてあたらしいバージョンのものを書きたいのですが、python初体験で苦戦中。。修行せねば。