Python: Google Drive APIで共有ドライブにアクセスする

#はじめに
Google Drive APIで共有ドライブにアクセスする方法について記述します。
通常のドライブとはパラメータ指定が異なるので、解決するまで時間がかかりました。

#準備1（セットアップ）
Google Drive APIで通常のドライブにアクセスできるようにします。
下記の記事がわかりやすかったです。

https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e

この記事の「[パッケージインストール](https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)」「[OAuthクライアントID取得](https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e#oauth%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88id%E5%8F%96%E5%BE%97)」「[Google Drive APIを有効にする](https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e#google-drive-api%E3%82%92%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B)」を実施します。
※私のスキルではPyDriveで共有ドライブにアクセスできなかったので使っていません。
※「[OAuthクライアントID取得](https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e#oauth%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88id%E5%8F%96%E5%BE%97)」の最後でダウンロードした「client_secret_～.json」を「credentials.json」にリネームします。

#準備2（テスト）
「credentials.json」と下記の記事の「quickstart.py」を同じフォルダに置きます。

https://developers.google.com/drive/api/v3/quickstart/python

「quickstart.py」を実行すると「通常」のドライブにあるファイルが10個表示されます。

```
> py quickstart.py
Files:
ファイル名1 (ファイルID1)
ファイル名2 (ファイルID2)
...
```

次に、（「通常」のドライブにある）指定したフォルダのファイルを表示するよう「quickstart.py」を改造します。
（```1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx```にフォルダIDを記述します。）

```py:quickstart.py（フォルダ指定）
    # Call the Drive v3 API
    query = "'1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' in parents"
    results = service.files().list(
        q=query,
        pageSize=10, fields="nextPageToken, files(id, name)").execute()
    items = results.get('files', [])

    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1})'.format(item['name'], item['id']))
```

これで、指定したフォルダのファイルを表示するようになりました。

#共有ドライブのファイルを表示する
上記のプログラムで、フォルダIDの代わりに共有ドライブのID（あるいは共有ドライブの中にあるフォルダのID）を指定すると、「No files found.」になります。
共有ドライブの中にあるファイルを表示するには、以下のように記述します。
（```0xxxxxxxxxxxxxxxxxx```に共有ドライブIDを指定します。）

```py:quickstart.py（共有ドライブ指定）
    # Call the Drive v3 API
    results = service.files().list(
        driveId="0xxxxxxxxxxxxxxxxxx",
        corpora="drive",
        includeItemsFromAllDrives=True,
        supportsTeamDrives=True,
        pageSize=10, fields="nextPageToken, files(id, name)").execute()
    items = results.get('files', [])

    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1})'.format(item['name'], item['id']))
```

#共有ドライブにファイルをアップロードする

```py:quickstart.py（ファイルアップロード）
    # Call the Drive v3 API
    drive_id = '0xxxxxxxxxxxxxxxxxx'
    file_name = 'test.xlsx'
    file_path = './'
    
    # 共有ドライブにファイルが存在するかチェック
    query = "name = '{}' and trashed=false".format(file_name)
    res = service.files().list(
        q=query,
        driveId=drive_id,
        corpora="drive",
        includeItemsFromAllDrives=True,
        supportsTeamDrives=True
    ).execute()
    
    # アップロードするファイル
    file_metadata = {
        'name': file_name,
        'parents': [drive_id]
    }
    media = MediaFileUpload(
        file_path + file_name, 
        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    )
    
    # ファイルの有無によって作成または更新
    if len(res['files']) == 0:
        res2 = service.files().create(
            body = file_metadata,
            media_body = media,
            fields = 'id',
            supportsTeamDrives = True
        ).execute()
    else:
        res2 = service.files().update(
            fileId = res['files'][0]['id'],
            media_body = media,
            fields = 'id',
            supportsTeamDrives = True
        ).execute()
```