Google Cloud Storage上の特定のバケットに格納されているファイルの一覧をPythonで表示し、gcloud CLIでダウンロードする 

AIで指定した画像を生成できるCGAN(Conditional GAN)の開発に向けて、簡単に使える学習用の画像のデータセットを探していたところ、丁度良いデータセットとして「Quick Draw!」のデータセットを発見しました。Quick Draw!データセットはGoogle Cloud Driveに格納されているため、これをダウンロードする必要があり、本記事はそれについて試行錯誤した備忘録となります。

https://quickdraw.withgoogle.com/data

https://quickdraw.readthedocs.io/en/latest/

#### 本記事の扱う範囲 / できなかった事

本記事では **Google Cloud StorageをローカルPCから操作する方法と、Google Cloud Storage上のデータリストを表示する方法、そして、ローカルPCへgcloud CLIによりファイル(blob)をダウンロードする方法をご紹介します。** <font color="red">**なお、今回の環境ではQuick Draw!のバケットが「非公開」に設定されていたためPythonスクリプトを使ったファイル(blob)のダウンロードはできませんでした(403エラーが発生)。結果、gcloud CLIを使ってデータセットをダウンロードする方法のみ紹介します。**</font>

![スクリーンショット 2025-01-13 15.08.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/69d1c29f-9286-eb27-cccd-0d4b074a15a8.png)

### 今回ダウンロードするQuick Draw! データセット

今回はQuick Draw!のデータセットを取得します。Quick Draw!は各ストロークから構成されるベクタ形式の画像データですが、CGANの学習にはラスタライズされた28px x 28pxの画像(Numpy形式)のほうが都合が良いです。このラスタライズされたデータは **Google Cloud Storageのバケット「`quickdraw_dataset`」の中の「`/full/numpy_bitmap`」に格納** されています。

https://console.cloud.google.com/storage/browser/quickdraw_dataset/full/numpy_bitmap;tab=objects?inv=1&invt=Abms9Q&prefix=&forceOnObjectsSortingFiltering=false

![スクリーンショット 2025-01-13 12.33.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/453aa056-94a0-f30b-5bed-0dd1660373d9.png)

## Google Cloud Storageと連携するための設定を行う

Google Cloud Storageからファイルをダウンロードするプログラムを作成する前に、まず、Google Cloud StorageをローカルPCから操作するために必要な設定を行います。

### Google Cloud StogaeにアクセスするためのPython仮想環境を定義する

https://qiita.com/ao-show/items/89975420080f576f43eb

まず、Google Cloud Storageを操作するために、ファイルを格納するためのディレクトリを作成し、Google Cloud Storageを操作するために必要なPythonのパッケージ `google-cloud-storage` をインストールします。

```bash
# 作業ディレクトリを作成する
## -->> 今回はCGANの開発に使います
$ cd ~
$ mkdir cgan_test
$ cd cgan_test
$ mkdir dataset
$ cd dataset
$ pwd
# /home/shino/cgan_test/dataset

# 仮想環境を作成する
$ conda create -n gcs_download python=3.10
# 仮想環境にログインする
$ conda activate gcs_download
# Google Cloud Storageを操作するためのパッケージをインストールする
(gcs_download)$ pip install --upgrade google-cloud-storage
# Numpyを扱うのでインストールしておく
(gcs_download)$ conda install numpy=1.26.4
```

この状態でPythonからGoogle Cloud Storageへアクセスするコードを実行すると、下記のようなエラーが発生し、端末からGoogle Cloud Storageへのアクセス権がない旨のエラーが出力されます。

![スクリーンショット 2025-01-13 12.37.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/1ba37fbd-9c7d-e734-9586-6d375830a13d.png)

### Google Cloudへログインするための認証を実行して、ログインに必要な情報をホームディレクトリに格納する

これを対策するため、次に、Google Cloud Storageにアクセスするためのアクセス権限を取得します。この設定には **Google Cloud Storageと連携するためのツール「`gcloud CLI`」が必要** です。 `gcloud CLI` の提供する `gcloud init` を実行すると、下記のようなログイン画面が表示され、Google Cloud Storageへアクセスする際に利用する **「Googleアカウント」の選択** と、 **ログインに必要なパスフレーズの取得** ができます。

![スクリーンショット 2025-01-13 12.55.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/48420305-13aa-4f05-7f4c-016e41169a0f.png)

以下で紹介する操作を行うと `.config/gcloud/application_default_credentials.json` にGoogle Cloud Storageで **ファイルを操作するためのアクセス権限がに保存** され、ローカルPCからGoogle Cloud Storageを操作できるようになります。

https://cloud.google.com/docs/authentication/application-default-credentials?hl=ja#personal

まず、次のWebサイトを参考にgcloud CLIをインストールします。

https://cloud.google.com/sdk/docs/install?hl=ja#linux

```bash
# ホームディレクトリへ移動する
$ cd ~

# curlコマンドでインストーラを取得する
$ curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz

# インストーラーを展開する
$ tar -xf google-cloud-cli-linux-x86_64.tar.gz
# 展開後のディレクトリを確認
ls google-cloud-sdk/
# LICENSE        VERSION              completion.zsh.inc  install.bat  path.bash.inc  platform
# README         bin                  data                install.sh   path.fish.inc  properties
# RELEASE_NOTES  completion.bash.inc  deb                 lib          path.zsh.inc   rpm

# インストールする
$ ./google-cloud-sdk/install.sh
# Do you want to help improve the Google Cloud CLI (y/N)? <enter>
# Do you want to continue (Y/n)? <enter>
# Enter a path to an rc file to update, or leave blank to use [/home/shino/.bashrc]:  <enter>
# ==> Start a new shell for the changes to take effect.
# ...
###
# 端末を開きなおす or source ~/.bashrc
###
```

インストールしたgcloud CLIを実行し、アクセス権限を取得します。

```bash
# gcloud CLIでの操作を開始する
$ gcloud init

# You must sign in to continue. Would you like to sign in (Y/n)? 
# Go to the following link in your browser, and complete the sign-in prompts:
# 
#     https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fsdk.cloud.google.com%2Fauthcode.html&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=ZJm8uJMoE1a9e6cUvmLNnaWaSKzLdS&prompt=consent&token_usage=remote&access_type=offline&code_challenge=Ak-ECdJ9ZzXK-HS3ohM9B4yjsBlqNssThLQl4IqFd18&code_challenge_method=S256

######
### 上のリンクをブラウザで開く
######
```

操作の途中でWebブラウザを使ってログイン情報を取得することが求められますので、リンクURLをコピーしてブラウザからGoogleアカウントにログインし、下記のようなパスフレーズを取得します。

![スクリーンショット 2025-01-13 12.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/21fcf07d-30ad-71ba-172a-67b2516e73c7.png)

パスフレーズ取得後、コマンドラインにこれを指定し、認証を進めていきます。

```bash
# Once finished, enter the verification code provided in your browser: 
# -->> ブラウザを操作することで得ることのできるパスフレーズを入力する
### 4/0AanRRruvaRLT57HgLxQVUXIeNshadKDyuJek22fmalBHtRA_jtgwiQgxgbKymJLEg-VH-w

######
### アカウントを選択する
######
# Select an account:
#  [1] ixiv2015@gmail.com
#  [2] Sign in with a new Google Account
#  [3] Skip this step
# Please enter your numeric choice:  1

### You are signed in as: [ixiv2015@gmail.com].

######
### Cloud Projectを作成するか確認
######
# Pick cloud project to use: 
#  [1] ixydesign-webform
#  [2] Enter a project ID
#  [3] Create a new project

### Create a new projectを選択
# Please enter numeric choice or text value (must exactly match list item): 3
# Enter a Project ID. Note that a Project ID CANNOT be changed later.
# Project IDs must be 6-30 characters (lowercase ASCII, digits, or
# hyphens) in length and start with a lowercase letter. 
# -->> gcs-contents-download を入力
# Waiting for [operations/cp.8699767152410418838] to finish...done

# * Commands that require authentication will use ixiv2015@gmail.com by default
# * Commands will reference project `gcs-contents-download` by default
# Run `gcloud help config` to learn how to change individual settings
# ...
```

gcloud initの後、ログイン情報をホームディレクトリに保存するために `gcloud auth application-default login` を実行します。この時もブラウザにてGoogleアカウントへログインすることが求められますので、指示に従ってください。

```bash
######
### 認証情報を再度取得するには以下を実行
######
$ gcloud auth application-default login 
# Go to the following link in your browser, and complete the sign-in prompts:
# 
#     https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fsdk.cloud.google.com%2Fapplicationdefaultauthcode.html&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login&state=3Fm0hlyqFJCZwTnlMSrVqp3fSUO9eY&prompt=consent&token_usage=remote&access_type=offline&code_challenge=vJrnn99LhoEMPsxEy6Wtmmwe5pi-E9B4PRODqgtsAZs&code_challenge_method=S256
# 
# Once finished, enter the verification code provided in your browser: 
#　-->> ブラウザを操作することで得ることのできるパスフレーズを入力する
# 4/0AanRRrsfwoJ726vUdosRRNzMIZFjVXnf3m9sxZIAq_QDNt49sFpCUSW17MxXS1_wUclZxg
# 
# Credentials saved to file: [/home/shino/.config/gcloud/application_default_credentials.json]
# These credentials will be used by any library that requests Application Default Credentials (ADC).
# Quota project "gcs-contents-download" was added to ADC which can be used by Google client libraries for billing and quota. Note that some services may still bill the project owning the resource.
# ...
```

## Pythonを使ってGoogle Cloud StorageからNumpyデータをダウンロードするプログラムを作成する

Visual Studio Codeで仮想環境を選択します。画面右下に表示されているPythonのバージョンをクリックすることにより選択できるようになります。

![スクリーンショット 2025-01-13 12.28.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/833684e3-3cf1-645f-13bb-03a651c8298c.png)

### バケット内のすべてのファイルリストを表示するプログラムを実行する

まず、Google Cloud StorageとローカルPCが連携できているかを確認するために、まず **バケット内のファイル一覧を取得するプログラムを実行** してみましょう。下記のコードを、先の手順で作成したPython仮想環境の中で実行してください。

https://cloud.google.com/storage/docs/samples/storage-list-files?hl=ja#storage_list_files-python

https://qiita.com/suganoooo/items/070d4465708ff27c5e0c

```python
from google.cloud import storage

# アクセスするバケットを選択する
bucket_name = "quickdraw_dataset"

def list_blobs(bucket_name):
    ## bucketに格納されたファイルリストを取得する　
    # 接続用のクライアントを定義する
    storage_client = storage.Client()
    # クライアントでblobsのリストを取得する (least package version 1.17.0)
    blobs = storage_client.list_blobs(bucket_name)
    # bolbsのリストを表示する
    for blob in blobs:
        print(blob.name)
    # blobsリストを返す
    return blobs

list_blobs(bucket_name)
```

格納されているファイルを確認できると思います。

### ファイルリストのうちnumpy形式のデータをダウンロードする <font color="red">【失敗】</font>

次にファイルリストから、Google Cloud Storage上のbolbをダウンロードする方法を紹介します。ただし、本環境ではGoogle Cloud StorageのQuick Draw!のバケットが「非公開」となっていたため、ダウンロードはできませんでした。 **実行できませんが、参考までにトライしたソースコードを記録しておきます(403エラーで停止します)。**

https://note.nkmk.me/python-pandas-str-contains-match/#strendswith

https://note.nkmk.me/python-list-append-extend-insert/

https://qiita.com/XPT60/items/9161fe5eb75762ea113e

https://cloud.google.com/storage/docs/troubleshooting?hl=ja

https://stackoverflow.com/questions/44657902/how-to-load-numpy-npz-files-in-google-cloud-ml-jobs-or-from-google-cloud-storage

https://qiita.com/ao-show/items/89975420080f576f43eb

```python
from google.cloud import storage
import os

# アクセスするバケットを選択する
bucket_name = "quickdraw_dataset"
# ダウンロードするファイルが格納されているGCSのフォルダを選択
SELECT_DIR = 'full/numpy_bitmap'
# ダウンロードするファイルの拡張子を選択する
SELECT_EXT = 'npy'
# ダウンロードしたファイルを格納するディレクトリを選択する
SAVE_PATH = "/home/shino/cgan_test/dataset"

######
### バケット内に格納されたファイルリストを取得する　
######
def list_blobs(bucket_name):
    # 接続用のクライアントを定義する
    storage_client = storage.Client()
    # クライアントでblobsのリストを取得する (least package version 1.17.0)
    blobs = storage_client.list_blobs(bucket_name)
    # bolbsのリストを表示する
    filelist = []
    for blob in blobs:
        filelist.append(blob.name)
    # filelistを返す
    return filelist

######
### バケットから指定したファイルをダウンロードする　
######
def download_blob(bucket_name, source_blob_name, destination_file_name):
    storage_client = storage.Client()
    # バケットに接続する
    bucket = storage_client.bucket(bucket_name)
    # ファイルパスからダウンロード対象を選択する(blob)
    blob = bucket.blob(source_blob_name)
    # ファイルをダウンロードする
    # -->> バケットが非公開の場合、ここで403エラーが発生する
    blob.download_to_filename(destination_file_name)
    # ダウンロード結果を表示する
    print(
        "Downloaded storage object {} from bucket {} to local file {}.".format(
            source_blob_name, bucket_name, destination_file_name
        )
    )

######
# 関数でファイルリストを取得する　
full_filelist = list_blobs(bucket_name)

######
# 指定したフォルダの特定の拡張子のファイルを選択する
download_files = []
for filename in full_filelist:
    if filename.startswith(SELECT_DIR):
        if filename.endswith(SELECT_EXT):
            download_files.append(filename)

######
# ダウンロードする
for filepath in download_files:
    savepath = os.path.join(SAVE_PATH, os.path.basename(filepath))
    download_blob(bucket_name, filepath, savepath)
```

#### <font color="red">Quick Draw!のバケットが「非公開」のため、403エラーとなりました 【失敗】</font>

https://cloud.google.com/appengine/docs/legacy/standard/python/googlecloudstorageclient/errors?hl=ja

Pythonスクリプトによるダウンロードまで紹介する予定だったのですが **バケットが非公開となっていたため(?)、403エラーが発生** してダウンロードができませんでした...本スクリプトの動作確認は今後、別のバケットにて試してみようと思います。

![スクリーンショット 2025-01-13 14.39.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/dbd1ad71-53ce-789e-7aaf-0a1fe5a4fa96.png)

### gcloud CLIを使ってファイル(blob)をダウンロードする

そこで今回は **Google Cloud Storage / gcloud CLI のダウンロード機能を使ってQuick Draw!の画像データをダウンロードしました。** ディレクトリ内のファイルを全て選択し「ダウンロード」をクリックすることでダウンロード用のリンクが生成されます。これをコマンドプロンプトにて実行することにより学習用データセットを入手できます。 <font color="blue">**※このダウンロード操作にはgcloud CLIが必要です。**</font>

![スクリーンショット 2025-01-13 14.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/a5eaef23-2dc3-3e79-2a88-5b3c6010481f.png)

![スクリーンショット 2025-01-13 14.43.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3919880/edc4ce02-5eef-28bd-d261-e1043a262f7e.png)

----

Quick Draw!のデータ入手方法は以上の通りです。
是非、みなさまの開発にお役立てください。

----