当方Google教原理主義者につき何から何までGoogleを利用していますが、もうデータベースまでGoogle様を利用することにしました。でも敬虔故に(?)無料で使用可能なGoogle Driveを今回は利用します。
Google Driveへのファイルアップロード・ダウンロードには「Google Drive API」というライブラリが公式で用意されているためこちらを利用しましょう。またアップロード・ダウンロードするファイルには、前回Pythonで株価情報を取得・チャート化してみた。で使用したデータを使ってみたいと思います。全体の流れとしては以下の通りです。
Google Drive APIを利用するにはGoogle Cloud Platform(以下GCP)からAPIの有効化が必要です。まずはこのリンク にアクセスして"有効にする"のボタンを押してください。
続いてGCPで下画像の通りサービスアカウントを作成します。
「サービスアカウント」とはGoogle APIを利用するための認証情報の1種です。Googleは数多くのAPIを提供していますがAPIの利用には認証が必要になります。他の認証手段としては「APIキー」と「OAuth 2.0 クライアントID」の2つがありますが、それぞれ取得情報と取得主体に応じて以下のような使い分けがされています。
例えば、Googleマップの情報やYouTubeの情報を取得する場合にはAPIキーが利用できますが、今回はGoogle DriveへのアクセスとなるためOAuth 2.0 クライアントIDもしくはサービスアカウントでアクセスする必要があります。しかし、OAuth 2.0 クライアントIDの場合、現在の当方の環境(外部ユーザへ開放されている、かつTesting版)ではRefresh Tokenが7日間で失効するという制約があったため、サービスアカウントを使用することにしました。
こちらのリンクからも飛べますが、GCPから"APIとサービス" > "認証情報"で下の画面に行けます。この画面から、"認証情報を作成" > "サービスアカウント"をクリックしてください。
下画像の通りサービスアカウント作成画面に遷移したら、詳細を設定していきます。まずは赤枠の通りサービスアカウント名を入力しましょう。するとサービスアカウントIDが自動で入力されるので、それで問題がない場合はそのまま使用してOKです。サービスアカウント名とサービスアカウントIDが入力できたら、一旦ここでは完了ボタンを押してください。上画像のサービスアカウント欄に今作成したサービスアカウントが確認できると思います。
次に秘密鍵を作成しましょう。サービスアカウント欄に上で新規作成されたサービスアカウントが表示されていると思いますが、一番右にペンのアイコンがあると思います。それをクリックすると下画像のような"IAMと管理"というページに飛びます。画面左のナビゲーションで"サービスアカウント"が選択されていること、主画面上のタブで"キー"が選択されていることを確認した上で、"鍵を追加" > "新しい鍵を作成"というボタンを押してください。すると下画像の通りダイアログが出てきます。ここでキーのタイプを"JSON"の状態にしたまま"作成"ボタンを押すとJSONファイルがダウンロードされます。このJSONファイルがAPIを利用する際の秘密鍵となりますので、今回作成するPythonファイルと同じディレクトリに格納しておいてください。
GCP側の設定が終わったら次はGoogle Drive側の設定ですが、その前に1つGCP側から重要な情報を控えてくる必要があります。メールアドレスです。2つ上の画像内で、サービスアカウントIDというものが出てきましたが、ここに"abcde-460@quicstart-~~~~~.iam.gserviceaccount.com"という情報があると思います。このメーアドレスがGoogle Drive側の設定で必要になりますのでコピーしておきます。コピーできたら早速Google Driveを開きましょう(※URL)。
ここで適当にフォルダを作ってください。参考までにsample_folder
としました。sample_folder
内に遷移しパンくずリストのsample_folder
をクリックし、下画像のように"共有" > "共有"を押してください。
すると下のようなダイアログが出てきます。ここで先ほど控えておいたメールアドレスを入力して(任意ですが)"通知"を外すと"共有"ボタンが出てきます。これをクリックしたらGoogle Drive側の設定は完了です。これでPythonコードからアクセスできるようになりました。
ようやく準備が整ったので、最後にcsvファイルをアップロード・ダウンロードするための記述をしていきましょう。今回はupdown_sample.py
というファイルを作ってそこに記述していきます。また、先ほど作成したJSONファイルの秘密鍵を同じディレクトリ内に格納しましょう。格納する際にはこのJSONファイル名をclient_secrets.json
に変更しておいてください。
BytesIO()
メソッドをダウンロード時に利用します。sample_folder
というフォルダをGoogle Drive上に作成しましたがそのフォルダのIDとなります。IDについてはフォルダを開いた際のURLから取得できます。(URLの最後のディレクトリそのものです。)scopes
を設定しています。今回利用するスコープではドライブにあるすべてのファイルを表示・管理できます。なお、scopes
の種類についてはこちら、service_account
に関わるGitHubレポジトリはこちらをご利用ください。build()
メソッドを用いて作成します。クライアントライブラリとはGoogleのAPIと通信を行い様々な操作(取得・作成・削除等)するためのオブジェクトのようなものです。引数にはGoogle Drive APIを指す"drive"
、対象のAPIのバージョンを指す"v3"
、 (l.31-34) で設定した認証情報を指定しています。MediaFileUpload
というクラスを利用してアップロードのためのインスタンスを作成しています。第一引数にはアップロードしたいファイルのファイルパスを指定します。第二引数にはresumable=True
とすることで、アップロードが中断された場合に再開できるように、リジューマブル(再開可能)なアップロードを有効にしています。これにより大きなファイルのアップロード時に途中で接続が切れた場合に再開が可能となります。build()
メソッドで作成したクライアントライブラリに対して.files()
メソッドを呼び出すことでファイル操作関連のリソースを呼び出します。さらに.create()
メソッドでファイルを作成し、引数としてbody
とmedia_body
内にそれぞれ上で作成したfile_metadata
とmedia
を指定します。fields
にはレスポンスとして返される情報として今回はid
のみ指定しています。最後に.execute()
メソッドを呼び出すことで、処理を実行をします。これでファイルアップロードは完了です。file_path
が空でない(具体的なファイル名が指定されている)場合、かつfolder_id
が指定されている場合に、parents
フィールドが指定されたフォルダ内で検索する条件を追加しています。これにより、特定のフォルダ内で指定されたファイル名に一致するファイルを検索する条件が構築されます。build()
メソッドで作成したクライアントライブラリに対して.files()
メソッドを呼び出しています。ここでは検索を実行したいので、引数として (l.48) で作成したクエリを指定することで指定条件に一致するファイルを.list()
メソッドで検索しています。"files"
キーに検索結果のファイルリストが格納されています。.get()
メソッドを使ってこのキーにアクセスし、検索結果を取得しています。もし"files"
キーが存在しない場合には空のリストが返されます。downloaded_file_id
に格納しています。見つかったファイルは後でターミナルから確認できるように、 (l.59) の通り出力しておきます。build()
メソッドで作成したクライアントライブラリに対して.files()
メソッドを呼び出してファイル操作関連のリソースを呼び出した上で.create()
メソッドでファイルを作成しました。今度はパラメータに先ほどの変数downloaded_file_id
を指定して.get_media()
メソッドでファイルダウンロードの準備をします。"wb"
を指定してio.FIle()
メソッドでファイルを開きます。続いて、 (l.63) についてはio.BytesIO()
メソッドを利用することでメモリ上に一時的にダウンロードするようにします。MediaIoBaseDownload
クラスを利用して (l.61-63) で設定した情報をもとにそれぞれローカル・メモリにダウンロードするためのインスタンスを作成します。done1 = False
としていますが、変数done1
をFalse
初期化することによってダウンロードが完了したかどうかを示すフラグを用意して、次のwhile
に備えています。MediaIoBaseDownload
クラス内のnext_chunk()
メソッドを呼び出して、複数のかたまりに分割してGoogle Driveからファイルをダウンロードする部分です。status1
にはダウンロードの進捗情報が含まれ、ダウンロードが完了したかどうかを示すフラグが更新されます。MediaIoBaseDownload
クラス内の.progress()
メソッドを利用してファイルダウンロードの進捗率を表示します。io.BytesIO()
のオブジェクトであるfh1
に対して、.seek(0)
とすることでファイルポインタの位置を"0"=先頭に戻しています。通常ファイルを読み取り後に再度同じファイルを読み取る際、ファイルポインタがファイルの最後に進んだままだと何も読み取れないません。そのためファイルポインタをファイルの先頭に戻しておくことで期待通り全データを取得できるようにしています。これでupdown_sample.py
によるファイルのアップロード・ダウンロード設定が完了しました。
今回Google Drive APIの基本操作として「アップロード」、「検索」、「ダウンロード」の3種類を実行しました。CRUDなアプリケーションを作るのには物足りないですが、個人的にはデータベース代わりに少量のデータを保管・読み取りするだけなら使えそうだなという印象です(がいかがでしょうか?)。
よろしければこちらの記事も参考にしてみてください。
Loading...