2012年4月3日

Google Plus API を使ってみる

Google Plus API を使ってみたのでちょっとメモしておきます。 プライベートなサークルのデータを引き抜けると嬉しいかなぁ、と思ったのに、 パブリックなデータにしかアクセスできないらしいので残念。(2012年4月2日現在)

  • Google+ API - Google+ Platform

    Note: The Google+ API currently provides read-only access to public data. All API calls require either an OAuth 2.0 token or an API key.

Activities list API は Buzz の API とほとんど一緒なので、 一回でも API を触ったことがあれば簡単です。

Python のライブラリを使うと OAuth 2.0 のフローは簡単に処理できますので、 サービスをディスカバリーしてからパラメータを与えて呼び出すだけです。

自分でコードを書いてみる場合

Google のサービスごとに認証して、それぞれにアプリケーションコードを書く、という流れは共通ですので、 認証部分を抽象クラスにまとめておきます。

class AbstractHandler(webapp.RequestHandler):
    """Base handler to utilize google api as service.
    Concrete class must define these two constant on their class.
    * SERVICE : google service name.
    * SCOPE   : authorization scope.
    * TPL     : template file path for static page.
    """

    def build_service(self):
        user = users.get_current_user()
        key = user.user_id() + '-' + self.SERVICE
        c = StorageByKeyName(Credentials, key, 'credentials').get()
        if c is None:
            url = self.request.relative_url('auth')
            url += '?service=' + self.SERVICE
            if hasattr(self, 'SCOPE'):
                url += '&scope=' + self.SCOPE
            self.redirect(url)
            return
        http = httplib2.Http()
        http = c.authorize(http)
        return build(self.SERVICE, 'v1', http=http)

    def send_static_page(self, js=None, css=None):
        params = {'javascripts': js, 'stylesheets': css}
        self.response.out.write(template.render(self.TPL, params))

    def send_data(self, data):
        self.response.headers['Content-Type'] = 'text/json'
        simplejson.dump(data, self.response.out)

アプリケーションごとのコードでは、サービスの定義ファイルから API リクエストを生成し、 アクティビティの一覧を取得します。 Google+ の場合は、認可のスコープが "plus.me" なのが個人的なつまずきポイント。 activities.list() を呼び出すときは userIdcollection が必須パラメータですが、 それぞれに特殊キーワードも用意されていますので、まずはそれを使っておきます。 なお、HTML のテンプレートなどは適当に用意しておきます。

class PlusHandler(AbstractHandler):
    """Sample handler to load user feed from Google Plus.
    """

    SERVICE = 'plus'
    SCOPE = 'plus.me'
    TPL = os.path.join(TEMPLATE_DIR, 'googleplus.html')

    def get(self):
        service = self.build_service()
        if service is None:
            return
        # load buzz activity asynchronously if user param is passed.
        uname = self.request.get('user')
        if not uname:
            self.send_static_page(js=['googleplus'])
            return
        activities = service.activities()
        user = users.get_current_user()
        try:
            activitylist = activities.list(userId='me',
                collection='public').execute()
            self.send_data(activitylist)
        except HttpError, e:
            logging.error("%s for %s" % (e, uname))
            self.error(500)

一応このコードで動きました。あとは JavaScript でデータを整形して表示させます。

これだとトークンのリフレッシュができませんし、 サービス側でアクセストークンを取り消した場合には動作できませんので、 実際のサービスには耐えられるものではありません。 ただ、これじゃダメ、ということが分かったので良しとします。

ライブラリを使う場合

google-api-python-client のサンプルがそのまんまです。 samples/appengine/main.py に Google+ を使ったサンプルが記述されています。

oauth2client.appengine.oauth2decorator_from_clientsecrets でデコレータを生成してから、 各APIエンドポイントに @decorator.oauth_aware@decorator.oauth_required を付けるみたいです。 トランスポートのレイヤーは http = decorator.http() として生成します。 これは httplib2 のオブジェクトを生成してくれるらしいです。 さすがにライブラリの作者が一緒なだけはあります。

個人的には Python のデコレータを関数から生成する点が難しいところですが、 ライブラリを使う側のユーザーコードはかなりシンプルになっていると思います。 パッと見で理解できるかは疑問が残りますが...


終わりに

Google Plus の API を使ってみました。 パブリックなポストしか取得できませんので面白みはありませんが、 ライブラリのサンプルや中身を見ることでプログラミング (Python) の勉強にはなりそうです。

Google AppEngine を使って Facebook などを Activitystreams に対応させるソフトウェアもあります。

Google+ Platform のドキュメントには "Try It!" というセクションがあるページも用意されており、 ここでレスポンスの JSON を確認できます。 画像 URL ひとつとっても、どのオブジェクトのどこに入っているかがイマイチ分かりにくいので、 こうしたツールを提供してくれているのは嬉しいですね。

コメントを投稿