bonar note

京都のエンジニア bonar の技術的なことや技術的でない日常のブログです。

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


すると、


http://static.flickr.com/68/257913452_778100ba07.jpg


できた!なんかちょっと嬉しい!


これPerlとかでもっと気合い入れてあたらしいバージョンのものを書きたいのですが、python初体験で苦戦中。。修行せねば。