CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: google-api-python-client とサービスアカウントで Google Docs のファイルをダウンロードする

今回は Google Cloud Platform のサービスアカウントと google-api-python-client を使って Google Docs のファイルをダウンロードしてみる。 サービスアカウントというのは、人間ではなくアプリケーションなどのシステムが使うアカウントのこと。 例えば CI などの環境で Google Docs にあるファイルを操作するのに使えるかな。

使った環境は次の通り。

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.14.5
BuildVersion:   18F132
$ python -V
Python 3.7.3

Google Cloud Platform にプロジェクトを作成する

まずは Google Cloud Platform にプロジェクトを用意する。 なお、プロジェクトの ID は Google Cloud Platform 上で一意な必要がある点に注意する。

プロジェクトは Google Cloud Console から作っても良いけど、今回は Google Cloud SDK の CLI から作る。 そこで、まずは Google Cloud SDK を Homebrew Cask でインストールしておく。

$ brew cask install google-cloud-sdk

インストールしたら gcloud コマンドが使えるようになるので、早速プロジェクトを作成する。

$ gcloud projects create <project-id>

今回は example-gdrive-service-account という名前のプロジェクトを使った。

$ gcloud projects create example-gdrive-service-account

プロジェクトを作ったら、以下のようにしてデフォルトのプロジェクトに設定しておくと良い。

$ gcloud config set project example-gdrive-service-account

上記の操作が終わったら、Google Cloud Console で Google Drive API を有効化しておく。 Google Docs のデータは Google Drive に保存されているため。 また、この作業だけは gcloud コマンドから実行できない。

プロジェクトにサービスアカウントを作成する

続いてプロジェクトにサービスアカウントを追加する。

プロジェクトにサービスアカウントを追加するには、以下のように gcloud iam service-accounts create コマンドを使う。

$ gcloud iam service-accounts create <sa-id> \
    --display-name <sa-name>

今回は、次のように gdrive-access-account という名前のアカウントを作った。

$ gcloud iam service-accounts create gdrive-access-account \
    --display-name gdrive-access-account

サービスアカウントに紐付いた認証情報をダウンロードする

サービスアカウントができたら、次はサービスアカウントに紐付いた認証情報をダウンロードする。 この認証情報があればサービスアカウントのできる操作は全てできてしまうので注意して管理しよう。

認証情報は次のように gcloud iam service-accounts keys create コマンドでダウンロードできる。 対象となるサービスアカウントは --iam-account というオプションで指定する。 このときメールアドレスのような形式でサービスアカウントを特定する。

$ gcloud iam service-accounts keys create <key-file> \
      --iam-account <sa-name>@<project-id>.iam.gserviceaccount.com

例えば今回であれば次のようになる。

$ gcloud iam service-accounts keys create ./key.json \
      --iam-account gdrive-access-account@example-gdrive-service-account.iam.gserviceaccount.com

実行すると、次のように認証情報がダウンロードされる。 デフォルトでは JSON 形式となる。

$ file key.json
key.json: ASCII text, with very long lines

操作したい Google Docs のファイルまたはディレクトリをサービスアカウントに共有する

続いて Google Drive をブラウザで開いてサービスアカウントから操作したいファイルまたはディレクトリに移動する。 そして、メニューから「ファイル > 共有」を選択する。 ここで、招待する相手としてサービスアカウントのメールアドレスを入力する。

または、公開しても問題ないファイルであれば共有メニューの「詳細設定」からアクセスできるユーザを変更する。 具体的には「ウェブ上で一般公開」または「リンクを知っている全員」に指定すれば良い。 ただ、この場合はクレデンシャルなしでアクセスできるので、別にサービスアカウントを作る必要はないはず。

サービスアカウントの認証情報と google-api-python-client を使ってファイルにアクセスする

ここまでで下準備は完了した。 続いては Python のクライアントからファイルを操作する作業に入る。

まずは必要なパッケージをインストールする。

$ pip install google-api-python-client

Python のインタプリタを起動しよう。

$ python

まずは、先ほどダウンロードしてきた認証情報を元に Credentials のインスタンスを作る。

>>> from google.oauth2.service_account import Credentials
>>> credential_file = 'key.json'
>>> c = Credentials.from_service_account_file(credential_file)

続いて、認証情報を元に Google Drive にアクセスするためのオブジェクトを作る。

>>> from googleapiclient import discovery
>>> service = discovery.build('drive', 'v3', credentials=c)

続いてファイル ID を指定して実際にファイルをダウンロード (エクスポート) する。 ファイル ID はファイルの共有メニューにある「共有可能なリンクを取得」から確認できる。 例えば Google 図形描画であれば以下の `<file-id> の部分がそれに当たる。

https://docs.google.com/drawings/d/<file-id>/edit

今回ダウンロードしたかったのは Google 図形描画の PNG ファイルなので mimeType オプションに image/png を指定した。

>>> file_id = '<file-id-to-download>'
>>> request = service.files().export(fileId=file_id, mimeType='image/png')
>>> image_data = request.execute()

ファイルのバイト列が取得できたら、あとはそれを使うだけ。 例えばローカルのディスクに書き出すのであれば次のようにする。

>>> with open('drive.png', mode='wb') as f:
...     f.write(image_data)
... 

いじょう。