Python: Google Calendar のイベント情報を読み取るスクリプト
ライブラリのインストール
google-api-python-client を利用する。
google-api-python-client - Google APIs Client Library for Python - Google Project Hosting
$ sudo pip install google-api-python-client
認証用のファイルを準備
- まずは Google APIs Console で Calendar API を有効にする。
Google APIs Console - そして、Google のチュートリアルに従ってみる。
Installation - Google APIs Client Library for Python — Google Developers
このような画面操作でサンプルを手に入れることができる。それを参考にする。
認証は、client_secrets.json というJSON形式のファイルを使うのが推奨されているようだ。
このファイルも手打ちする必要はなく、ダウンロードボタン一発で入手できる。
Client Secrets - Google APIs Client Library for Python — Google Developers
サンプルをたたくと、初回に client_secrets.json を元にFlow オブジェクトが生成される。
このとき、どのAPIにどのレベルでアクセスするかを指定する。
今回はカレンダーの読み取りだけなので、'https://www.googleapis.com/auth/calendar.readonly' があれば十分。
その内容が Storage オブジェクトとなり、ファイルに保存される。
今回は read_calendar.dat というファイル名にした。
認証情報(credentials)が完成したら、httplib2、build() 関数を使って Calendar API v3 にアクセスすればよい。
コード
今日一日の予定を出力するコード。
プログラムの第一引数に整数を入れれば、n日後の予定を取得できる。
対象のカレンダーIDは予め調べて、ハードコーディング。
予定の開始時刻、終了時刻、内容、作成者をソートして出力するため、OneDayEvent というクラスを作っている。
タイムゾーンの調整はしていない。(手抜き)
もっとコメント書いた方がいいけどこれも手抜き。
Calendar API のサービスを取得した後、
service.events()list(...).execute() で条件に見合ったイベントのリストを取得している。
#!/usr/bin/env python # -*- coding: utf-8 -*- import httplib2 import os import sys import datetime from apiclient.discovery import build from oauth2client.file import Storage from oauth2client.client import AccessTokenRefreshError from oauth2client.client import flow_from_clientsecrets from oauth2client.tools import run # Calendar id for reading. CALENDAR_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxx.calendar.google.com' # Path to the credential files. BASE_DIR = lambda x: os.path.join(os.path.dirname(__file__), x) CLIENT_SECRETS_PATH = BASE_DIR('client_secrets.json') STORAGE_PATH = BASE_DIR('read_calendar.dat') # Set up a Flow object to be used for authentication. FLOW = flow_from_clientsecrets(CLIENT_SECRETS_PATH, scope=[ 'https://www.googleapis.com/auth/calendar.readonly', ]) def get_calendar_service(): storage = Storage(STORAGE_PATH) credentials = storage.get() if credentials is None or credentials.invalid: credentials = run(FLOW, storage) http = httplib2.Http() http = credentials.authorize(http) service = build('calendar', 'v3', http=http) return service class OneDayEvent(object): def __init__(self, start_time, end_time, summary, creator): if start_time is None: assert(end_time is None) self.start_time = start_time self.end_time = end_time self.summary = summary self.creator = creator def __lt__(self, that): if self.start_time is None and that.start_time is None: return self.summary < that.summary if self.start_time is None or that.start_time is None: return self.start_time is None return (self.start_time, self.end_time, self.summary, self.creator) < ( that.start_time, that.end_time, that.summary, that.creator) def __str__(self): if self.start_time is None: tm = u'終日' else: f = lambda x: datetime.datetime.strftime(x, '%H:%M') tm = '%s-%s' % (f(self.start_time), f(self.end_time)) return u'[%s] %s (%s)' % (tm, self.summary, self.creator) def read_events(date): """Returns sorted list of OneDayEvent objects.""" def format(x): return datetime.datetime.strftime(x, '%Y-%m-%dT%H:%M:%SZ') time_min = datetime.datetime.combine(date, datetime.time()) time_max = time_min + datetime.date.resolution time_min, time_max = map(format, (time_min, time_max)) service = get_calendar_service() events = service.events().list( calendarId=CALENDAR_ID, timeMin=time_min, timeMax=time_max).execute() def f(x): y = x.get('dateTime') if y: z = datetime.datetime.strptime(y[:-6], '%Y-%m-%dT%H:%M:%S') return datetime.datetime.combine(date, z.time()) ret = [OneDayEvent( f(event['start']), f(event['end']), event['summary'], event['creator']['displayName']) for event in events['items']] ret.sort() return ret def main(argv): offset = int(argv[1]) if len(argv) >= 2 else 0 for event in read_events( datetime.date.today() + datetime.date.resolution * offset): print(unicode(event)) if __name__ == '__main__': main(sys.argv)
- 出力例
[終日] 有給休暇 (James LaBrie) [11:00-12:00] ○○様来社 (John Petrucci) [14:00-15:00] [外出] △△訪問 (John Myung) [17:30-22:00] □□勉強会 (Jordan Rudess) [17:30-23:00] ☆☆飲み会 (Mike Mangini)
References