Python, PyDriveでGoogle Driveのファイルのリストを作成
PyDriveを使うとPythonからGoogleドライブを簡単に操作できる。
ここでは、Googleドライブ上のファイルやフォルダのリスト作成について説明する。検索条件を指定して該当するファイルやフォルダを抽出してリスト化することも可能。
- Googleドライブのファイル・フォルダのリスト作成
ListFile()
の基本的な使い方- ソートの基準を指定
- ページングと
maxResults
- 検索条件を指定
- 条件指定の基本
- ファイルのみ・フォルダのみ:
mimeType
- ファイル名・フォルダ名:
title
- 指定のフォルダに含まれるファイル・フォルダ:
parents
- ゴミ箱:
trashed
- リストのファイル・フォルダを一括処理(削除・ダウンロードなど)
- リストをCSVで保存(csvモジュール使用)
- リストを
pandas.DataFrame
に変換- CSVで保存
- 親フォルダをパス形式(
xxx/yyy/zzz
)で表す
PyDriveの基本的な使い方(利用登録や認証、ファイルのダウンロード、アップロード、削除など)は以下の記事を参照。
サンプルコードでは、以下の構成のファイル・フォルダを例とする。
root
├── dir1
│ ├── file11
│ ├── file12
│ └── subdir1
│ └── file111
├── dir2
│ └── file21
├── file1
└── file2
なお、以下はPyDriveバージョン1.3.1
の情報。
Googleドライブのファイル・フォルダのリスト生成
ListFile()の基本的な使い方
ListFile()
でGoogleDriveFileList
オブジェクトを生成し、さらにGetList()
でリスト化する。
GoogleDriveFile
オブジェクトを要素とするリストが取得できる。
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
file_list = drive.ListFile().GetList()
print(type(file_list))
# <class 'list'>
print(len(file_list))
# 9
print(type(file_list[0]))
# <class 'pydrive.files.GoogleDriveFile'>
for f in file_list:
print(f['title'], ' \t', f['id'])
# file21 1hJ7WQDiZyefLCQsDBE8J5-Nz847Vp670
# dir2 1wmWf1fhJTgi3X1Y07t2T8KYm4GtYEgxP
# file111 1789K-xv4ereCSOKrDKiAQI5bBypjqtIB
# subdir1 1k154tW38rbXxj88fjV8IZVkgB3EZ7g2M
# file12 1QRndXjXG9p2MEnVuotGd-eCNE2vNpkfp
# file11 1nCotx1q3DEaRWQOqbPqbPS1rGMWXRt8q
# dir1 1qQEUlPaIiDR_WI3hNf25rXUCHrlZIK_y
# file2 1ewv3ht8J2T3oMFmBgpqeS8zWHyHJsEwg
# file1 1WY5-WfWxj-ovefoE1dzWEfzgt8wtfbwY
デフォルトではすべてのファイル・フォルダが対象となる。大量にファイル・フォルダがある状態だとリストの生成に時間がかかるので注意。16,000個ぐらいあるアカウントだと1分程度かかった。
条件で絞る方法については後述。
ソートの基準を指定
ListFile()
ではGoogle Drive APIのFiles: list
を呼んでおり、そのパラメータを辞書(dict
)で引数に指定できる。
例えば、ソートの基準を決めるorderBy
を設定する例は以下の通り。降順にしたい場合はdesc
を付ける。
for f in drive.ListFile({'orderBy': 'title'}).GetList():
print(f['title'], ' \t', f['id'])
# dir1 1qQEUlPaIiDR_WI3hNf25rXUCHrlZIK_y
# dir2 1wmWf1fhJTgi3X1Y07t2T8KYm4GtYEgxP
# file1 1WY5-WfWxj-ovefoE1dzWEfzgt8wtfbwY
# file11 1nCotx1q3DEaRWQOqbPqbPS1rGMWXRt8q
# file111 1789K-xv4ereCSOKrDKiAQI5bBypjqtIB
# file12 1QRndXjXG9p2MEnVuotGd-eCNE2vNpkfp
# file2 1ewv3ht8J2T3oMFmBgpqeS8zWHyHJsEwg
# file21 1hJ7WQDiZyefLCQsDBE8J5-Nz847Vp670
# subdir1 1k154tW38rbXxj88fjV8IZVkgB3EZ7g2M
for f in drive.ListFile({'orderBy': 'title desc'}).GetList():
print(f['title'], ' \t', f['id'])
# subdir1 1k154tW38rbXxj88fjV8IZVkgB3EZ7g2M
# file21 1hJ7WQDiZyefLCQsDBE8J5-Nz847Vp670
# file2 1ewv3ht8J2T3oMFmBgpqeS8zWHyHJsEwg
# file12 1QRndXjXG9p2MEnVuotGd-eCNE2vNpkfp
# file111 1789K-xv4ereCSOKrDKiAQI5bBypjqtIB
# file11 1nCotx1q3DEaRWQOqbPqbPS1rGMWXRt8q
# file1 1WY5-WfWxj-ovefoE1dzWEfzgt8wtfbwY
# dir2 1wmWf1fhJTgi3X1Y07t2T8KYm4GtYEgxP
# dir1 1qQEUlPaIiDR_WI3hNf25rXUCHrlZIK_y
Google Drive APIのパラメータについては以下の公式ドキュメントを参照。なお、バージョン1.3.1
時点ではPyDriveはGoogle Drive APIのv2を使用しているので注意。
検索条件を指定するq
については後述。
ページングとmaxResults
パラメータmaxResults
を設定して、一度に決まった件数ずつ取得することも可能。
for i, f_list in enumerate(drive.ListFile({'maxResults': 3})):
print('=====', 'page', i)
for f in f_list:
print(f['title'], ' \t', f['id'])
# ===== page 0
# file21 1hJ7WQDiZyefLCQsDBE8J5-Nz847Vp670
# dir2 1wmWf1fhJTgi3X1Y07t2T8KYm4GtYEgxP
# file111 1789K-xv4ereCSOKrDKiAQI5bBypjqtIB
# ===== page 1
# subdir1 1k154tW38rbXxj88fjV8IZVkgB3EZ7g2M
# file12 1QRndXjXG9p2MEnVuotGd-eCNE2vNpkfp
# file11 1nCotx1q3DEaRWQOqbPqbPS1rGMWXRt8q
# ===== page 2
# dir1 1qQEUlPaIiDR_WI3hNf25rXUCHrlZIK_y
# file2 1ewv3ht8J2T3oMFmBgpqeS8zWHyHJsEwg
# file1 1WY5-WfWxj-ovefoE1dzWEfzgt8wtfbwY
これまでの例のようにmaxResults
を設定せずにGetList()
を使うと、自動的に全件を取得してリストを返してくれる。
for f in drive.ListFile().GetList():
print(f['title'], ' \t', f['id'])
# file21 1hJ7WQDiZyefLCQsDBE8J5-Nz847Vp670
# dir2 1wmWf1fhJTgi3X1Y07t2T8KYm4GtYEgxP
# file111 1789K-xv4ereCSOKrDKiAQI5bBypjqtIB
# subdir1 1k154tW38rbXxj88fjV8IZVkgB3EZ7g2M
# file12 1QRndXjXG9p2MEnVuotGd-eCNE2vNpkfp
# file11 1nCotx1q3DEaRWQOqbPqbPS1rGMWXRt8q
# dir1 1qQEUlPaIiDR_WI3hNf25rXUCHrlZIK_y
# file2 1ewv3ht8J2T3oMFmBgpqeS8zWHyHJsEwg
# file1 1WY5-WfWxj-ovefoE1dzWEfzgt8wtfbwY
公式ドキュメントの記述は以下。
GetList()
Get list of API resources.
If ‘maxResults’ is not specified, it will automatically iterate through every resources available. Otherwise, it will make API call once and update ‘pageToken’. pydrive package - pydrive.apiattr.ApiResourceList.GetList — PyDrive 1.2.1 documentation
ソースコードは以下。maxResults=1000
としてイテレートしている模様。
ファイルやフォルダを少しずつ処理したいというような場合でなければ、maxResults
を設定せずに全件取得すればよい。
検索条件を指定
条件指定の基本
検索条件を指定してリスト化するには、q
に検索条件を表す文字列を設定する。
例えば、名前(ファイル名・フォルダ名)がfile1
から始まるファイル・フォルダを抽出する例。
for f in drive.ListFile({'q': 'title contains "file1"'}).GetList():
print(f['title'], ' \t', f['id'])
# file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
and
やor
で複数条件を組み合わせることも可能。否定のnot
も使える。上の条件に、親フォルダがルートではない、という条件を追加した例。
for f in drive.ListFile({'q': 'title contains "file1" and not "root" in parents'}).GetList():
print(f['title'], ' \t', f['id'])
# file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
検索条件の文字列(クエリ文字列)で使える演算子および語句(フィールド名)は以下の公式ドキュメントを参照。
なお、クエリ文字列の中でファイル名などの文字列を表す場合はシングルクォーテーション'
でもダブルクォーテーション"
でもどちらを使ってもいい。以下のどのパターンでもOK。
# 'title contains "file1"'
# "title contains 'file1'"
# 'title contains \'file1\''
# "title contains \"file1\""
Pythonの文字列リテラルにおける引用符の扱いについては以下の記事を参照。
クエリ文字列の例は以下の記事を参照。ファイル名・フォルダ名(title
)や更新日時(modifiedDate
)などで条件を指定できる。このあとでいくつか具体例を示す。
上述のように、バージョン1.3.1
時点ではPyDriveはGoogle Drive APIのv2を使用している。ファイル名・フォルダ名はv2ではtitle
だがv3ではname
に変更されているなどの違いがある。v3のGoogle Drive APIのサンプルコードを参考にするとエラーになる可能性があるので注意。
ファイルのみ・フォルダのみ: mimeType
項目がファイルかフォルダかはmimeType
で判定する。GoogleドライブにおけるフォルダのmimeType
はapplication/vnd.google-apps.folder
。
等価(〜である)を表す演算子は=
。==
ではないので注意。等価でない、は!=
。
for f in drive.ListFile({'q': 'mimeType = "application/vnd.google-apps.folder"'}).GetList():
print(f['title'], ' \t', f['id'])
# dir2 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9
# subdir1 1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck
# dir1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1
for f in drive.ListFile({'q': 'mimeType != "application/vnd.google-apps.folder"'}).GetList():
print(f['title'], ' \t', f['id'])
# file21 1o-pFt-9Hrj_z3FmlsQfa8duo_ZfuEh5S
# file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
# file2 1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
mimeType
を利用すると、'mimeType = "image/jpeg"'
のようにしてJPEG画像のみを抽出したりもできる。
ファイル名・フォルダ名: title
ファイル名・フォルダ名についての条件はtitle
を使う。演算子として、=
, !=
, contains
が使える。
for f in drive.ListFile({'q': 'title = "file1"'}).GetList():
print(f['title'], ' \t', f['id'])
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
for f in drive.ListFile({'q': 'title contains "file1"'}).GetList():
print(f['title'], ' \t', f['id'])
# file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
for f in drive.ListFile({'q': 'title contains "11"'}).GetList():
print(f['title'], ' \t', f['id'])
contains
は前方一致検索なので注意。上のサンプルコードの最後の例のように、途中の文字列にはマッチしない。
The contains operator only performs prefix matching for a title. For example, the title "HelloWorld" would match for title contains 'Hello' but not title contains 'World'. Search query terms | Drive REST API v2 | Google Developers
指定のフォルダに含まれるファイル・フォルダ: parents
親フォルダの判定はparents
とin
で'"<folder_id>" in parents'
とする。フォルダ名ではなくIDを指定する必要があるので注意。
dir1_id = drive.ListFile({'q': 'title = "dir1"'}).GetList()[0]['id']
for f in drive.ListFile({'q': '"{}" in parents'.format(dir1_id)}).GetList():
print(f['title'], ' \t', f['id'])
# subdir1 1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
ルートフォルダ(マイフォルダ)はroot
という文字列で代用できる。
for f in drive.ListFile({'q': '"root" in parents'}).GetList():
print(f['title'], ' \t', f['id'])
# dir2 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9
# dir1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1
# file2 1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
この方法で取得できるのはあくまでも親フォルダが指定したフォルダであるファイル・フォルダのリスト。サブフォルダ(さらに下の階層)まで対象としたい場合は再帰的に処理する必要がある。詳細は以下の記事を参照。
ゴミ箱: trashed
ファイル・フォルダがゴミ箱に入っているかどうかはtrashed
で判定する。trashed
はtrue
かfalse
のいずれかの値を持つ。
Googleドライブにおいては、ゴミ箱に入っていても親フォルダparents
自体は変わらないため、trashed
を設定しないとゴミ箱の中のファイルやフォルダまでリストアップされてしまう。要注意。
file1_id = drive.ListFile({'q': 'title = "file1"'}).GetList()[0]['id']
file1 = drive.CreateFile({'id': file1_id})
file1.Trash()
for f in drive.ListFile({'q': '"root" in parents'}).GetList():
print(f['title'], ' \t', f['id'])
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
# dir2 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9
# dir1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1
# file2 1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz
for f in drive.ListFile({'q': '"root" in parents and trashed = false'}).GetList():
print(f['title'], ' \t', f['id'])
# dir2 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9
# dir1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1
# file2 1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz
リストのファイル・フォルダを一括処理(削除・ダウンロードなど)
ListFile()
で取得できるのはGoogleDriveFile
オブジェクトを要素とするリスト。
これまでの例ではprint(f['title'], ...)
のようにファイル名などを出力していたが、そこでファイルのダウンロードやリネームなどの処理を行えばよい。
ダウンロードする例。
file_list = drive.ListFile({'q': 'title contains "file1" and trashed = false'}).GetList()
for f in file_list:
print(f['title'], ' \t', f['id'])
# file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
# file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
dst_dir = 'dst'
for f in file_list:
f.GetContentFile(os.path.join(dst_dir, f['title']))
リネームする例。
for f in file_list:
f['title'] = 'XXX_' + f['title']
f.Upload()
for f in file_list:
print(f['title'], ' \t', f['id'])
# XXX_file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
# XXX_file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# XXX_file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# XXX_file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
削除の場合も同様にTrash()
やDelete()
を使えばよい。
なお、フォルダを削除するとその中のファイルやフォルダも同時に削除されるので、フォルダを丸ごと削除する場合は特にリストを作成する必要はない。
サブフォルダ(さらに下の階層)までまとめてダウンロードやリネームなどをしたい場合は再帰的に処理を行う。以下の記事を参照。
リストをCSVで保存(csvモジュール使用)
取得したリストをCSVとして保存したい場合、2次元のリスト(リストのリスト)を作成する。
- 関連記事: Pythonリスト内包表記の使い方
import csv
import pprint
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
l = [[f['title'], f['id']] for f in drive.ListFile().GetList()]
pprint.pprint(l)
# [['file11', '15sy12U3d845pXjLaEWww4VLO9Vs7C4J9'],
# ['file12', '1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx'],
# ['file111', '1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech'],
# ['file1', '1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo'],
# ['file21', '1o-pFt-9Hrj_z3FmlsQfa8duo_ZfuEh5S'],
# ['dir2', '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9'],
# ['subdir1', '1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck'],
# ['dir1', '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1'],
# ['file2', '1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz']]
この例はファイル名・フォルダ名とIDのみを抽出しているが、その他の情報が必要であれば同じ要領でリストの要素を増やせばよい。次のpandasの例でさらに多くの要素を抽出する例を紹介している。
ヘッダーとなるリストを先頭に追加し、csvモジュールのwriterows()
で書き込む。
l.insert(0, ['title', 'id'])
with open('dst/use_csv.csv', 'w') as f:
writer = csv.writer(f)
writer.writerows(l)
リストをpandas.DataFrameに変換
取得したデータを処理したい場合、pandasのDataFrame
に変換すると便利。
csvモジュールを使う例と同様に、まずは2次元のリスト(リストのリスト)を作成する。ここではより複雑な例を紹介する。
import pprint
import pandas as pd
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
l = [[f['title'], f['id'], f['parents'][0]['id'], f['mimeType'], f.get('fileSize')]
for f in drive.ListFile().GetList()
if len(f['parents'])]
pprint.pprint(l, width=200)
# [['file11', '15sy12U3d845pXjLaEWww4VLO9Vs7C4J9', '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1', 'application/octet-stream', '0'],
# ['file12', '1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx', '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1', 'application/octet-stream', '0'],
# ['file111', '1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech', '1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck', 'application/octet-stream', '0'],
# ['file1', '1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo', '0AAeKIFCqYN07Uk9PVA', 'application/octet-stream', '0'],
# ['file21', '1o-pFt-9Hrj_z3FmlsQfa8duo_ZfuEh5S', '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9', 'application/octet-stream', '0'],
# ['dir2', '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9', '0AAeKIFCqYN07Uk9PVA', 'application/vnd.google-apps.folder', None],
# ['subdir1', '1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck', '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1', 'application/vnd.google-apps.folder', None],
# ['dir1', '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1', '0AAeKIFCqYN07Uk9PVA', 'application/vnd.google-apps.folder', None],
# ['file2', '1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz', '0AAeKIFCqYN07Uk9PVA', 'application/octet-stream', '0']]
フォルダはfileSize
を持たないので、キーがなくてもエラーにならないget()
メソッドを使う。
また、共有フォルダのファイルなどはparents
を持たない場合もあるので、リスト内包表記の条件式で判定して除外している。
作成した2次元リストをコンストラクタpd.DataFrame()
に渡してDataFrame
を生成する。
df = pd.DataFrame(l, columns=['title', 'id', 'parents_id', 'mimeType', 'fileSize'])
print(df)
# title id \
# 0 file11 15sy12U3d845pXjLaEWww4VLO9Vs7C4J9
# 1 file12 1iv9UB1pi65MqfFmqYwBoz3AfZbKr2jLx
# 2 file111 1bfc7jlDobxuoyZeF8CDyXlN66zl84Ech
# 3 file1 1z1vv7Zd1k14JebVghq8NlVpLWmFhZybo
# 4 file21 1o-pFt-9Hrj_z3FmlsQfa8duo_ZfuEh5S
# 5 dir2 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9
# 6 subdir1 1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck
# 7 dir1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1
# 8 file2 1HaHLB19oU_he6LI_6mkQsPr9uH_JK_oz
#
# parents_id mimeType \
# 0 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1 application/octet-stream
# 1 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1 application/octet-stream
# 2 1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck application/octet-stream
# 3 0AAeKIFCqYN07Uk9PVA application/octet-stream
# 4 1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9 application/octet-stream
# 5 0AAeKIFCqYN07Uk9PVA application/vnd.google-apps.folder
# 6 1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1 application/vnd.google-apps.folder
# 7 0AAeKIFCqYN07Uk9PVA application/vnd.google-apps.folder
# 8 0AAeKIFCqYN07Uk9PVA application/octet-stream
#
# fileSize
# 0 0
# 1 0
# 2 0
# 3 0
# 4 0
# 5 None
# 6 None
# 7 None
# 8 0
DataFrame
が生成できれば、CSVやEXCELなどのファイルとして保存するのも簡単。
df.to_csv('dst/use_pandas.csv', index=False)
親フォルダをパス形式(xxx/yyy/zzz)で表す
リストをDataFrame
に変換すると様々な処理が簡単に行える。
ここでは親フォルダをパス形式(xxx/yyy/zzz)で表す例を示す。なお、Googleドライブは様々なケースがあるため、以下のコードはすべての状況での動作を保証するものではない。
上のサンプルコードのように、すべてのファイル・フォルダを対象としたリストから、id
, parents_id
, mimeType
の情報を含むDataFrame
を生成したとする。
まず、mimeType
を判定し、フォルダのみのDataFrame
を取得。
フォルダのみのDataFrame
をもとに、フォルダのIDとそのタイトル(フォルダ名)、フォルダのIDとその親フォルダのIDをマッピングした辞書をそれぞれ生成する。
df_folder = df.query('mimeType == "application/vnd.google-apps.folder"')
d_id_title = dict(zip(df_folder['id'], df_folder['title']))
d_id_parents_id = dict(zip(df_folder['id'], df_folder['parents_id']))
pprint.pprint(d_id_title)
# {'1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck': 'subdir1',
# '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1': 'dir1',
# '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9': 'dir2'}
pprint.pprint(d_id_parents_id)
# {'1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck': '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1',
# '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1': '0AAeKIFCqYN07Uk9PVA',
# '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9': '0AAeKIFCqYN07Uk9PVA'}
ルートフォルダ(マイフォルダ)のIDを取得。親フォルダのIDをルートになるまで遡り、パス形式(xxx/yyy/zzz)の文字列に変換し、フォルダのIDとその文字列をマッピングした辞書を生成する。
def get_parents_path(current_id, root_id, sep='/'):
l = []
while current_id != root_id:
if current_id not in d_id_title.keys():
return None
l.append(d_id_title[current_id])
current_id = d_id_parents_id[current_id]
return sep.join(reversed(l))
root_id = drive.ListFile({'q': '"root" in parents'}).GetList()[0]['parents'][0]['id']
d_id_path = {i: get_parents_path(i, root_id) for i in df_folder['id']}
d_id_path[root_id] = ''
pprint.pprint(d_id_path)
# {'0AAeKIFCqYN07Uk9PVA': '',
# '1CpPdnFTdN6DWPz7VBM1pV-RMZfcbvzck': 'dir1/subdir1',
# '1DX1YFUdbSAeIvuXVLoosAKY2eX27Q4Y1': 'dir1',
# '1UaNdnbqCKe2ALtZp6hirvCgZl7OVpTI9': 'dir2'}
map()
でフォルダのIDをパス形式の文字列に置き換え、新たな列を追加。ソートなどを行う。
df['parents_path'] = df['parents_id'].map(d_id_path)
df_result = df.sort_values('parents_path').reset_index(drop=True)
print(df_result[['title', 'parents_path']])
# title parents_path
# 0 file1
# 1 dir2
# 2 dir1
# 3 file2
# 4 file11 dir1
# 5 file12 dir1
# 6 subdir1 dir1
# 7 file111 dir1/subdir1
# 8 file21 dir2
例ではルート以下すべてのファイル・フォルダをリスト化して処理したが、特定のフォルダ以下のサブフォルダの中身を含むすべてのファイル・フォルダのリストがあれば同様の処理が可能。そのフォルダのIDになるまで遡ればよい。
サブフォルダの中身を含むすべてのファイル・フォルダのリストの取得については以下の記事を参照。