VSCodeローカルJupyter環境にてスプレッドシートのデータをpandasデータフレームとして読み込む

# ▼背景
ローカルにてAPI経由でGoogleスプレッドシートのデータにアクセスするには、認証を突破する必要がある。
認証方法は、サービスアカウントやOauth認証など種類がいくつかある。
これまでサービスアカウントでは認証を行ったことがあったがOauth認証では躓いていた。そのため、今回はOauth認証にて行ってみた。
そのため、Oauth認証以外の箇所については説明を詳しくは行わない。

# ▼やりたいこと
スプレッドシートに置いているデータをPythonにてpandasデータフレームに変換する

| 読み込むスプレッドシート | pandasデータフレームへ| 
|--------|--------|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/73c0148e-56b3-4beb-80a5-3ffd33d8e5b9.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/a78ef048-631d-4ce4-9c37-2e864cdf6112.png)| 

# ▼全体像
1. GCPプロジェクト作成
1. API有効化
1. **Oauth認証設定**
1. ローカルにPython環境構築
   1. クライアントシークレットファイルを設置
2. Pythonコード記述
3. 実行
   1. **Oauth認証**

# ▼つまづいたこと・感想
- Oauth同意画面の公開設定を行わないとエラーになる。
    - テストユーザに自分のメールアドレスを追加すればよい
- クライアントシークレットファイル名を`credentials.json`に変更する必要があった
    - これは必須なのかどうかは不明
- やり方さえ理解すればこの認証方法は簡単。サービスアカウント認証ではセキュリティ的に問題があるとされているのでOauth認証をこれからは主に使用していきたい

----------------------------

# 〇手順

## ➀GCPプロジェクト作成 ~ API有効化
GCP consoleを開いてプロジェクトを作成する。既にプロジェクトがある場合は必要なし。
そして、今回の作業に必要なAPIを有効化する。今回は以下の二つ。
- Google Sheets API
- Goolge Drive API

## ➁**Oauth認証設定**
流れは以下
1. OauthクライアントIDを作成
1. クライアントシークレットJSONをダウンロード
1. Oauth同意画面構成
1. 公開設定

### Oauth認証の流れをオフィルビルへの入館を例に理解する

あるオフィスビルがあるとする。
初来客のゲストに対し、オフィスビルに入った後、自社のオフィスフロアに入るための入館許可を行うことを想定してほしい。
このビルでは、ゲストを迎えに行く受け入れ係が必須となるルールらしい。(Oauth認証)
受け入れ係がユーザでゲストがアプリケーションである。アプリが認証情報をクリアして自社オフィスのフロアに入館するをことを想定する。受け入れ係であるユーザがアプリケーションの入館には必須となっている。
受け入れ係が行う行動を追っていく

まず、受付にてゲスト用の受付番号が書かれた入館証を手に入れる。(OauthクライアントID)
そして、受付用の社員証のバッジと暗証番号を発行しゲストに渡しておく(クライアントシークレットJSONをダウンロードし、ローカルに保存)
次に、自社オフィスのフロア前まで移動する。入口にて受付パネル(Oauth同意画面)がある。ゲストにここに入館証をかざし、暗証番号も入力してもらう。
この受付パネルにはゲストが行うことが出来る項目が記載されている。(例えば、会議室への入室を許可。社長室への入室は不許可)この項目をゲストに許可しても良いかを受け入れ係が判断する。問題なければ許可ボタンを押す。
すると、入館が許可される。
次回以降入館する際は、受け入れ係を読んで受付パネルを操作するところからスタートするイメージだ。

以上のようにユーザがアプリケーションの認証クリアをサポートすることによって認証行う仕組みを「Oauth認証」という。

また、初回は入口にある受付パネルには何も表示されないため設定を行う必要がある。これがOauth同意画面の構成である。

### 実際の流れ

1. クライアントIDの作成とクライアントシークレットのダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/73435e5d-bd40-4601-a637-dc101ebf124b.png)

2. Oauthの同意画面の作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/92e7a437-0d83-4a88-ace3-976306cea4fe.png)

流れに沿えば簡単に作成することが出来る

3. Oauth同意画面の公開設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/01334fff-9717-44b9-a03d-0c2e0a6dfeff.png)

**デフォルトでは公開が行われない**ので注意
公開するまたはテストユーザとして自分のアカウントを登録する必要があった。私はこれを忘れており最初は認証が行えなかった。
よくよく考えれば、作成したアプリケーションは公開されないと自分のローカルからはアクセス出来ないのは当たり前だった

## ③ローカルにPython(jupyter)環境構築

ここは詳しくは行わない。私はjupyter環境を構築した。
後に使うライブラリもインストールしておく。
また、私はvenvにて仮想環境を立ち上げてカーネルを登録した。
手順は以下をリンクを参照してほしい

[VSCodeにてjupyter環境を構築するには](https://zenn.dev/torakm/articles/55b16afb0a3941)
[VSCodeにてvenvで環境構築~カーネル登録](https://qiita.com/kez/items/9626af27685579282740)

また、Oauth認証を行うための認証情報と暗証番号にあたるクライアントシークレットを実行ファイルと同階層に設置する必要がある。名前は`credentials.json`としておく

ライブラリのインストールは以下コマンド
```
pip install jupyter ipykernel gspread pandas gspread_dataframe google-auth google-auth-oauthlib
```

## ④Pythonコード記述
スプレッドシートのURLとシート名は適当なものに変更が必要

```Python
import gspread
from google.auth.transport.requests import Request
from google.oauth2.service_account import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
import pandas as pd
from gspread_dataframe import get_as_dataframe

# スコープ定義（Google SheetsとDrive）
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly',
          'https://www.googleapis.com/auth/drive.readonly']

# OAuth2.0 フローで認証
flow = InstalledAppFlow.from_client_secrets_file(
    'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)

# 認証後、gspreadクライアント作成
gc = gspread.authorize(creds)

# スプレッドシートのURLまたはID
spreadsheet_url = "https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=0"
spreadsheet = gc.open_by_url(spreadsheet_url)

# 「シート名」を指定（例: 'Sheet1'）
worksheet = spreadsheet.worksheet('Sheet1')

# pandasデータフレームとして読み込み（1行目をヘッダーとして）
df = get_as_dataframe(worksheet, evaluate_formulas=True, header=0)

# 表示確認
df.head()

```
## ⑤実行

後は実行するだけ。
実行するとOauth同意画面が表示されるので、問題なければ続行を押していくだけ。
完成！

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2998651/a78ef048-631d-4ce4-9c37-2e864cdf6112.png)