【Python】Google Calendar APIを使ってGoogle Calendarの予定を取得・追加する

プログラミング
https://www.uniguest.com/en/reserva/logo_lockup_calendar_icon_horizontal/
この記事は約20分で読めます。

皆さんは日々のスケジュール管理は何を利用されているでしょうか?私は仕事で利用しているのもあり、自分のプライベートのスケジュールにもGoogle Calendarを使用しています。

そんなGoogle CalendarにはDeveloper用のGoogle Calendar APIがあり、APIを使ってGoogle Calendarの予定を取得したり、追加したりすることができます。

プログラムからGoogle Calendarの予定を操作できるとなにかと便利だと思ったので、利用方法を紹介したいと思います。

PythonのGoogle Calendar API設定

まずはPythonでGoogle Calendar APIを利用するための設定を行います。Google Calendar APIの設定は以下のGoogle Calendar APIのPython Quickstartのページに従いながら行います。

前提条件

Google Calendar APIを使うために以下の前提条件を満たしている必要があります。

  • Python 2.6以上
  • pipパッケージマネジメントツール
  • Google Calendarが有効になっているGoogleアカウント

pipはpython3.4以降のものをインストールすれば、一緒にインストールされるのであまり気にしなくても大丈夫だと思います。
pipって何ですか?ってゆう感じの人はこちらを御覧ください。
Pythonの始め方④ pipとは?Pythonを便利に利用するためのpipの理解

Step1:Google Calendar APIの有効化

Googleのアカウントにログインした状態で、先程のPython Quickstartのページへ移動し、Step1の箇所にある「ENABLE THE GOOGLE CALENDAR API」というボタンを押します。

ボタンを押すと以下のようなウィンドウが現れます。

ウィンドウ内の「DOWNLOAD CLIENT CONFIGURATION」ボタンを押します。
するとcredentials.jsonというファイルがダウンロードされます。
このファイルは後ほど利用するので、保管しておいてください。

ClientIDとClient Secretはダウンロードしたcredentials.json内にも記載されていますし、同じアカウントでもう一度「ENABLE THE GOOGLE CALENDAR API」ボタンを押せば再度表示できるので、特に記録しておく必要はありません。

Step2:Google Client Libraryのインストール

次にStep2に記載のコマンドをコピーして、ターミナルで実行します。

$ pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

Step3:sampleファイルを準備する

公式サイトに記載の通り、quickstart.pyファイルを作成し、以下の内容を記述します。

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def main():
    """Shows basic usage of the Google Calendar API.
    Prints the start and name of the next 10 events on the user's calendar.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
    print('Getting the upcoming 10 events')
    events_result = service.events().list(calendarId='primary', timeMin=now,
                                        maxResults=10, singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.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()

Step4:sampleファイルの実行

作成したquickstart.pyファイルを実行するのですが、その際にquickstart.pyと同じフォルダにStep1でダウンロードしたcredentials.jsonファイルがないといけません。
なので、quickstart.pyとcredentials.jsonを同一フォルダに置いてください。

そのフォルダ内で以下のコマンドを実行します。

$ python quickstart.py

コマンドを実行するとブラウザが起動し、Googleアカウントにログインする画面が現れると思います。
Step1を実施したときのアカウントを選択します。

すると以下のような警告画面が出ると思います。

これは問題ないので、左下の詳細をクリックします。
すると以下のような画面になります。

さらに左下に現れた「Quickstart(安全ではないページ)に移動」をクリックします。
すると以下のような画面が現れます。

これも「許可」をクリックします。
すると以下のような画面が現れます。

クドいですが、もう一度「許可」をクリックします。
するとブラウザ内に「The authentication flow has completed, you may close this window.」とだけ書かれた画面が現れます。これでブラウザは閉じて構いません。

ターミナル画面に戻ると画面内にGetting the upcoming 10 eventsという文字が現れ、google schedule内に予定があれば下記のように表示されるはずです。

Getting the upcoming 10 events
2019-09-02T07:00:00+09:00 予定1
2019-09-03T09:00:00+09:00 予定2

また、quickstart.pyとcredentials.jsonを置いているフォルダに戻るとtoken.pickleというファイルができていると思います。
このファイルがあれば今後は上記のクドい認証作業は不要となります。

Google Calendarの予定を取得

quickstart.pyがすでに直近の10件の予定を取得するコードになっていますが、もう少し追記して使いやすい形に変えておきましょう。

基本的には先程のコードの40行目のevents().list(calendarId=….)部分を変更していきます。
指定できるパラメータ一覧およびその説明の詳細は公式を参照ください。

今回はtimeMaxとtimeMinを使って、指定の期間の予定を取得するようにしましょう。
また、カレンダーIDをprimaryではなく、専用のカレンダーIDから取得するようにします。

新しいカレンダーの作成とカレンダーIDの取得

まずはGoogle Calendarに新しいカレンダーを追加します。
Google Calendarの左にある他のカレンダーの右にある「+」ボタンを押します。
すると以下のように「新しいカレンダーを作成」というのが現れるのでクリックします。

設定画面に切り替わり、新しいカレンダーを作成する画面が現れるので、新しいカレンダーの名前を入力し、「カレンダーを作成」ボタンをクリックします。
ここではsampleという名前にしました。

Google Calendarの画面に戻ると左下にsampleのカレンダーが現れているので、その右の縦に点が3つならんだボタンを押します。
すると設定と共有というボタンが現れるのでそれを押します。

設定画面にいくので、下の方にスクロールすると「カレンダーの統合」という見出しがあり、その下にカレンダーIDがあります。
ここに表示されているIDをコピーします。

PythonでGoogle Calendarの予定を取得

quickstart.pyの内容を少し書き換えるので、quickstart.pyの内容をコピーし、新たにget_event.pyというファイルを作ります。

先程コピーしたIDをget_event.pyのcalendarIdのところに貼り付けます。
また、2019年9月1日〜10月1日の1ヶ月の予定を取得するプログラムに変更するために、timefromとtimetoという変数を設定しました。(下記コードの35, 36行目)
Google Calendar APIは時間をISOフォーマットで受け取るようなので、isoformatに変換しています。(下記コードの37, 38行目)
一方、出力される結果はISOフォーマットではなく、普通の日次で表示されて欲しいので、その変換もしています。(下記コードの50行目)

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

def main():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # Call the Calendar API
    timefrom = '2019/09/01'
    timeto = '2019/10/01'
    timefrom = datetime.datetime.strptime(timefrom, '%Y/%m/%d').isoformat()+'Z'
    timeto = datetime.datetime.strptime(timeto, '%Y/%m/%d').isoformat()+'Z'
    events_result = service.events().list(calendarId='コピーしたIDを貼り付け',
                                        timeMin=timefrom,
                                        timeMax=timeto,
                                        singleEvents=True,
                                        orderBy='startTime').execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        start = datetime.datetime.strptime(start[:-6], '%Y-%m-%dT%H:%M:%S')
        print(start, event['summary'])

if __name__ == '__main__':
    main()

上記を実行すると以下のような結果が得られると思います。

$ python get_event.py
2019-09-03 11:00:00 予定1
2019-09-11 10:00:00 予定2
2019-09-20 15:30:00 予定3

これでPythonとGoogle Calendar APIを使って、Google Calendarの予定を取得することができました。

Google Calendarに予定を追加

Google Calendarの予定を取得するコードができたので、今度はGoogle Calendarに予定を追加するコードを書きましょう。

書き込み権限の付与

今度はGoogle Calendarへの書き込みを行うので、アクセス権限を変える必要があります。
書き込み権限はget_event.pyの10行目に記載のSCOPESから.readonlyの文字列を削除し、以下のように記述します。

SCOPES = ['https://www.googleapis.com/auth/calendar']

9行目にコメント文で記載がありますが、このSCOPESを変更した場合はtoken.pickleを一旦削除し、再度作成する必要があります。
token.pickleを削除して、一度プログラムを実行しましょう。

$ python get_event.py

すると、Step4:sampleファイルの実行で実施した流れになると思いますが、権限付与の箇所が異なります。
以下のような画面になっていると思いますので、両方とも許可を選択します。

PythonでGoogle Calendarに予定を追加

予定の書き込みにはevent().insert(calendarId=…)メソッドを使用します。
event().insertのパラメータも数が多いので詳細は公式で確認してください。

使い方はシンプルで、予定に書き込む情報を辞書(json)形式で記述し、それをbodyとしてinsert()に書き込む形です。
説明だけではわかりにくいと思いますので、以下がコードになります。

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar']

def main():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    event = {
      'summary': '予定1',
      'location': 'Shibuya Office',
      'description': 'サンプルの予定',
      'start': {
        'dateTime': '2019-09-10T09:00:00',
        'timeZone': 'Japan',
      },
      'end': {
        'dateTime': '2019-09-10T17:00:00',
        'timeZone': 'Japan',
      },
    }

    event = service.events().insert(calendarId='コピーしたIDを貼り付け',
                                    body=event).execute()
    print (event['id'])

if __name__ == '__main__':
    main()

34〜46行目にeventという辞書を作成しています。
eventの中身は以下になります。
summary:Google Calendarの予定の見出しの文字列です。
location:予定開催場所
description:Google Calendarの予定の中の説明を記述する部分です。
start:予定開始時間
end:予定終了時間

上記を実行します。ファイル名はinsert_event.pyとしました。

$ python insert_event.py

実行すると何やらよくわらかない文字列が表示されますが、それがeventのidになります。
eventのidが表示されたら、Google Calendarに移動してみてください。
おそらくeventに記載した日次に予定が追加されていると思います。

これでPythonとGoogle Calendar APIを使って、Google Calendarに予定を追加することができました。

まとめ

いかがだったでしょうか?
pythonでGoogle Calendar APIを利用している人がいないようでしたので、参考になればうれしいです。
よかったらこちらのボタンをポチッとしておいていただけると嬉しいです。

 にほんブログ村 IT技術ブログへ
タイトルとURLをコピーしました