OAuth認証でGoogle Calendar APIに接続する(python編)

2016.12.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ベルリンの半瀬です。

はじめに

いつもながら初心者向けです。Google Calendar API を初めて触ったので、備忘メモでまとめます。
基本的な OAuth認証でのアクセス方法を確認しました。
Google Calendar API
Google Calendar API リファレンス

やってみました

リファレンスを読んでpythonサンプルの動作確認をしてみます。
Google Calendar API Python Quickstart
必要なものは、

  • Python 2.6以上
  • pip
  • Webブラウザ
  • Googleアカウント(Googleカレンダーが有効なもの)

です。

Step1: Turn on the Google Calendar API

  • ココからGoogle Calendar APIアプリケーションの登録をします。
    20161204-01
  • 「認証情報に進む」をクリック、
    20161204-02
  • 「プロジェクトへの認証情報への追加」画面になるので、一度「キャンセル」をします。
    20161204-03
  • 「API Manager」ダッシュボードが表示され、有効なAPIが確認できます。使用しないAPIは無効化しておいても良さそうです。
    20161204-04
  • 「認証情報」の「OAth同意画面」で「ユーザーに表示するサービス名」を設定します。この設定がないとOAuth認証ができません。
    20161204-05-2
  • 「認証情報」から「認証情報を作成」→「OAuthクライアントID」を選択します。
    20161204-06
  • 「クライアントIDの作成」画面でアプリケーションの種類「その他」を選択し、名前を入力。
    20161204-07
  • クライアントIDが発行されます。
    20161204-08-2
    20161204-09-2
  • クレデンシャルを取得します。「test-hanse」をクリック→ 「JSONをダウンロード」をクリックすると、json形式でダウンロードができます。
    20161204-10-2
    ダウンロードした「client_secret_NNNNNNNNNN-XXXXXX.apps.googleusercontent.com」の中身

    {
      "installed": {
        "client_id": "NNNNNNN-XXXXXXX.apps.googleusercontent.com",
        "project_id": "triple-student-151509",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://accounts.google.com/o/oauth2/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": "{シークレット情報}",
        "redirect_uris": [
          "urn:ietf:wg:oauth:2.0:oob",
          "http://localhost"
        ]
      }
    }
  • クレデンシャルをローカルに落としたら、サンプルコードに使用するために、「client_secret.json」にリネームしておきます。

Step 2: Install the Google Client Library

  • python用のGoogle APIクライアントをインストールします。
    pip install --upgrade google-api-python-client

Step 3: Set up the sample

  • ここまで準備できたら以下のサンプルコードを配置します。
    quickstart.py

    from __future__ import print_function
    import httplib2
    import os
    
    from apiclient import discovery
    from oauth2client import client
    from oauth2client import tools
    from oauth2client.file import Storage
    
    import datetime
    
    try:
        import argparse
        flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
    except ImportError:
        flags = None
    
    # If modifying these scopes, delete your previously saved credentials
    # at ~/.credentials/calendar-python-quickstart.json
    SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
    CLIENT_SECRET_FILE = 'client_secret.json'
    APPLICATION_NAME = 'Google Calendar API Python Quickstart'
    
    
    def get_credentials():
        """Gets valid user credentials from storage.
    
        If nothing has been stored, or if the stored credentials are invalid,
        the OAuth2 flow is completed to obtain the new credentials.
    
        Returns:
            Credentials, the obtained credential.
        """
        home_dir = os.path.expanduser('~')
        credential_dir = os.path.join(home_dir, '.credentials')
        if not os.path.exists(credential_dir):
            os.makedirs(credential_dir)
        credential_path = os.path.join(credential_dir,
                                       'calendar-python-quickstart.json')
    
        store = Storage(credential_path)
        credentials = store.get()
        if not credentials or credentials.invalid:
            flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
            flow.user_agent = APPLICATION_NAME
            if flags:
                credentials = tools.run_flow(flow, store, flags)
            else: # Needed only for compatibility with Python 2.6
                credentials = tools.run(flow, store)
            print('Storing credentials to ' + credential_path)
        return credentials
    
    def main():
        """Shows basic usage of the Google Calendar API.
    
        Creates a Google Calendar API service object and outputs a list of the next
        10 events on the user's calendar.
        """
        credentials = get_credentials()
        http = credentials.authorize(httplib2.Http())
        service = discovery.build('calendar', 'v3', http=http)
    
        now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
        print('Getting the upcoming 10 events')
        eventsResult = service.events().list(
            calendarId='primary', timeMin=now, maxResults=10, singleEvents=True,
            orderBy='startTime').execute()
        events = eventsResult.get('items', [])
    
        if not events:
            print('No upcoming events found.')
        for event in events:
            start = event['start'].get('dateTime', event['start'].get('date'))
            print(start, event['summary'])
    
    
    if __name__ == '__main__':
        main()
  • サンプルコードとクレデンシャルのjsonファイルを同じディレクトリに配置。
    前項でクレデンシャルファイルは「client_secret.json」にリネームしています。

    % ls -l 
    total 16
    -rw-r--r--@ 1 kohei-hanse  test   434 12  4 10:37 client_secret.json
    -rw-r--r--  1 kohei-hanse  test  2629 12  4 10:48 quickstart.py
    drwxr-xr-x  7 kohei-hanse  test   238 12  4 10:39 venv
  • quickstart.pyを実行すると、以下の出力がされます。同時に、開いているブラウザでアクセス要求画面が表示されます。このとき、自分の操作したいアカウントであるかどうかを確認してください。Chromeなどで複数アカウントを開いている場合は、直近に操作していたブラウザのアカウントにアクセスされるようです。
    % python quickstart.py 
    XXXX/lib/python2.7/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access XXXXX/.credentials/calendar-python-quickstart.json: No such file or directory
      warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
    
    Your browser has been opened to visit:
    
        https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=NNNNNNNN-XXXXXX.apps.googleusercontent.com&access_type=offline
    
    If your browser is on a different machine then exit and re-run this
    application with the command-line parameter
    
      --noauth_local_webserver
  • アクセス要求画面
    20161204-11
  • 「許可」をすると、このアカウントへのOAuth認証によるアクセスが可能となります。
    {先ほどの出力の続き}
      --noauth_local_webserver
    
    Authentication successful.

Step 4: Run the sample

  • 認証が通りましたので、再度実行してみます。
    ちなみに処理は「ローカル時間の現時刻から直近のイベントを最大10件まで表示させる」というものです。

    % python quickstart.py
    Getting the upcoming 10 events
    2016-12-04T15:00:00+01:00 test
    2016-12-04T16:00:00+01:00 test2
    2016-12-05T12:00:00+01:00 test3

    うまく動作しました(^_^

おわり

以上、Google Calendar APIのOAuth認証による接続でした。
ふと思い立ったことがあるので、それを次回以降で確認していければと思います。
下記もご参考になれば幸いです。
Developers.IO | [iOS][Objective-C] Google Calendar API で予定を書き込んでみる

それでは〜