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