Google Drive API(Python)從0開始到從URL下載檔案範例

湯沂達(Yi-Dar, Tang)
Taiwan AI Academy
Published in
20 min readJul 2, 2021

--

unfinished horse drawing

閱讀門檻:看得懂python,有google帳號

你是否想要一套方便、現成、有很多延伸的後端工具?
你是否很常把檔案丟到google drive上,並且想要做一些客製化的管理?
你是否想要把google drive上的檔案用程式自動下載,並且這些檔案是只有自己的帳號有權限閱覽的?

如果上面的問題,至少有一個是”YES”,並且你還沒使用過google drive API,那麼花個15分鐘看看這篇文章也許未來能幫你入門google後端。

這篇文章會做一些Google Drive API的簡單介紹;兩個官方範例;和一個簡單的範例延伸

  1. Google Drive API Introduction
  2. Google Drive API Quickstart (Python)
  3. Download a file stored on Google Drive
    Download a Google Workspace Document
  4. Download from URLs in Google Drive

而若不需要太複雜的功能,只是想要用指令下載別人分享在Google Drive上的公開檔案,記下下方的gdown指令即可。

gdown https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c
# gdown --id 0B_NiLAzvehC9R2stRmQyM3ZiVjQ # This also work
# replace "0B9P1L--7Wd2vU3VUVlFnbTgtS2c" to the file_id you want

而若懶得自己動手寫一個google drive API程式來下載一批google雲端硬碟檔案的話,可以直接下載我的github,然後按下拍手後就可以離開這個頁面了♡

Google Drive API Introduction

https://developers.google.com/drive/images/drive-intro.png

在應用程式中,可以透過Google Drive API的方式去操作在Google Drive/Shared Drives中的檔案。

其中,OAuth部分為在使用應用程式時,需要的憑證。這邊並不做特別介紹,我把示意圖放在下面,有興趣者可以去看OAuth的官方文件

https://developers.google.com/identity/protocols/oauth2

你可以使用Google Drive API做到什麼?

https://developers.google.com/drive/api/v3/about-sdk#what_can_you_do_with_google_drive_api

你可以使用Google Drive API做到下面這些事情

  • 下載、上傳檔案到Google Drive
  • 搜尋在google drive上的資料夾、檔案。
    其中,可以搜尋檔案中比較特殊的額外屬性(metadata),像是該檔案
    * 檔案名稱
    * 是什麼檔案?(google 簡報檔/google 表格/一般檔案…等等)
    * 擁有者是誰
    * 等等
  • 讓使用者可以將檔案、資料夾、雲端硬碟共享給其他人
  • 等等

在官方的說明文件中,已經有很多可以直接使用的範例程式碼,若使用者想要入門、縫合一些功能,這些範例程式碼都是很好上手的

上方藍色框選部分為要等等會帶給各位看的範例程式碼

  • 第一個Google Drive應用程式(Python)
  • 下載檔案

以及最後要帶給各位的簡單卻實際的應用

  • 直接用所見的url從google drive下載檔案

其中,還有很多範例不在上方圖片內,詳情請去
https://developers.google.com/drive/api中觀看

不包括的大項如下

  • Handle changes and revisions
  • Integrate with the Drive UI
  • Integrate Drive widgets into your web app
  • Handle errors and improve performance
  • Publish your Drive app
  • Stay updated

Before Google Drive API

註:以下操作步驟為2021 July操作,也許會隨著版本更新有所不同,請以google官方文件為準

在google drive API的快速開始前,有三件事情需要做

  1. 開啟一個新專案
  2. 在已經有的雲端專案中啟用Google Drive API
  3. 為專案建立憑證

開啟專案的步驟有些冗長,若單純想看Google Drive API如何撰寫者請直接下拉至Google Drive API Quickstart (Python)

舊版本的步驟沒這麼冗長,不過現在官方是讓使用者用這個方法操作

開啟新專案的步驟如下

一:開啟Google雲端控制台
二 & 三、點選左上角選取專案,點下新增專案
四 & 九、打上期望的專案名稱,並按下建立

到此為止,已經建立好了一個Google Cloud Project,接下來要啟用該專案的Google Drive API功能

一 & 二、在選取專案處找到剛剛建立的專案,並且開啟
三、依序點下左上角的 ≡ ,API和服務,資料庫
五 & 六、在搜尋欄位處打上“google drive api”,並點下對應的圖標
六、啟用Google Drive API
七、能看到該API的導覽頁,其中若專案還沒有憑證,必須先建立一個憑證

接下來要為專案建立

  1. OAuth 同意畫面
  2. 桌面版本應用程式憑證
什麼是 OAuth 同意畫面?

建立OAuth同意畫面的步驟如下

https://developers.google.com/workspace/guides/create-credentials#configure_the_oauth_consent_screen
二、點下左上專案選取處▼,再點下要建立憑證的專案
三 & 五、依序點下左上角的 ≡ ,API和服務,OAuth同意畫面
六 & 七、選擇外部,並按下建立
八 & 九、在有星號(*)處填上對應之物件,按下儲存並繼續
十三、儲存並繼續
十四、儲存並繼續
十五、已成功建立OAuth同意畫面,最後按下發布應用程式

建立完OAuth同意畫面後,接下來要建立一個桌面版本應用程式憑證

https://developers.google.com/workspace/guides/create-credentials#create_a_oauth_client_id_credential
一 & 二、依序點選”API和服務”底下的”憑證”,”建立憑證”,”OAuth 用戶端ID”
三 & 四、選擇電腦版應用程式,打上期望顯示的名稱、按下建立

建立完桌面版憑證後,要將其下載至本機

https://developers.google.com/workspace/guides/create-credentials#desktop
二 & 三、點下確定後,再按右邊的下載
四、因應這次範例,將檔案名稱更名為 “credentials.json”

到此為止,我們終於完成了Quickstart的前置作業了

Google Drive API Quickstart (Python)

終於要開始這次的正題了,假如前面你已經下載完憑證,且將名稱更名為 credentials.json後,就可以開始準備開始第一個 Google Drive API 的程式了

列出你的google drive中的前10筆檔案

Step 1: Install the Google client library

首先需要在有python≥2.6的環境中安裝上方套件

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
Step 2: Configure the sample
Step 2: Configure the sample加了額外註解(#*#)的版本

將上方程式碼下載至與credentials.json相同的位置,且命名要為quickstart.py

Step 3: Run the sample

先帶操作步驟再講程式碼

在終端機打上

python quickstart.py

接下來,如果是第一次執行,會跳出一個網頁,這時需要去選擇用哪個帳號的角色去執行這個應用程式

選擇帳號
由於未經過驗證,要用非安全模式進入,此處先點下進階
然後按下前往
按下允許
再次按下允許
接下來可以關閉網頁了
這時在終端機上就會顯示 10個檔案名稱,以及檔案在google雲端硬碟中獨特的id

這份程式碼做的事情很簡單

  1. 讀取套件

2. 設定應用程式權限

設定SCOPES為只需要讀取檔案的額外屬性(metadata)的唯讀模式
drive.metadata.readonly
一些metadata像是檔案名稱、檔案型態、檔案大小、是否被加到最愛、擁有者等等。
因為是唯讀模式,所以用這個程式碼如果要求了修改metadata,則程式會回傳錯誤。
若要做額外權限更改,可以參考程式碼中附上之額外連結,該連結有列出Google Drive API的各種權限要求
下個範例中會更改此處的SCOPE

3. 生成or讀取token.json

生成專屬於該使用者的對應此應用程式憑證、SCPOES要求的token.json
接下來使用者可以直接使用該token.json去呼叫Google Drive API

4. 讀取雲端資料

用files().list(…)去列出幾筆資料,並且印出這些資料的檔案名稱、檔案id
其中 fields=”nextPageToken, files(id, name)” 代表著回傳的資訊,包含了
一個結構如下的python字典

{
"nextPageToken":string, #是否已經列完所有檔案
"files":list({"id":string, "name":string}) #所要求檔案的metadata
}
results structure

第一個官方範例就到這邊結束了。

Download a file stored on Google Drive
Download a Google Workspace Document

第二個官方範例為從google dirve中下載檔案的片段

其核心函式為

if file_mimeType is google_format:
# 特殊檔案,如google doc/sheet/slide
# 下方的mimeType為期望轉換的格式
request = export_media(fileId, mimeType)
else:
# 一般檔案,如pdf, mov, mp4
request = get_media(
fileId,
supportAllDrives=True, # 加這行會讓程式更泛用一點
)

而有哪些Google特殊檔案的型態可以觀看下方圖片

https://developers.google.com/drive/api/v3/ref-export-formats

在開始程式碼改動前,要先注意權限問題

  • Quickstart處,所採用的權限為
    drive.metadata.readonly
    這種權限是沒有讀取檔案本身資料的功能的
  • 而若要使用下載功能,最低權限至少需要
    drive.readonly
    並且使用這種權限時,是不用害怕不小心修改到雲端硬碟中的檔案的
  • 各種權限可以去此處觀看
    https://developers.google.com/drive/api/v3/about-auth

在此處若要實現一個簡單的下載功能,我們針對以下三種資料型態做一些額外處理

  1. document #Google 文件
  2. presentation #Google 簡報
  3. spreadsheet #Google 試算表

將其對應的office形式下載(*.docx / *.pptx / *.xlsx),可以在 這邊 查詢到對應的office mimeType字串

  1. application/vnd.openxmlformats-officedocument.wordprocessingml.document
  2. application/vnd.openxmlformats-officedocument.presentationml.presentation
  3. application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

接下來就知道對應的檔案應該輸出爲什麼格式了,但是我們仍未知道對應檔案的格式,這時就需要用 get 來得知該檔案的一些metadata了。

file_metadata = service.files().get(
fileId = file_id,
# 檔案的額外資訊列表,可以去下方連結查詢
# https://developers.google.com/drive/api/v3/reference/files
fields="id, name, mimeType, size, parents",
# 下面這行會讓使用者可以去讀取共用雲端硬碟中的資料
supportsAllDrives=True,
).execute()

接下來要建一個python字典的mapper,將上方的mimeType映射至對應格式

google_file_prefix = "application/vnd.google-apps."
office_prefix = "application/vnd.openxmlformats-officedocument."
google_office_mapper = {
google_file_prefix+google_postfix:
office_prefix+office_postfix

for google_postfix,office_postfix in [
["document", "wordprocessingml.document"],
["presentation", "presentationml.presentation"],
["spreadsheet", "spreadsheetml.sheet"]
]
}

若是google 雲端檔案,則為其個別檔案補上他應有的副檔名後,最後再新增一些額外判別式即能完成從雲端下載檔案至本機,完整版程式碼列在下方

執行方式如下

python download_with_fileId $fileId

其中fileId為檔案在google drive中唯一的ID,取得方式如下

如何得到fileId
兩次的執行結果如上,分別為一般檔案,以及google簡報

第二個到這邊結束了。

接下來是第三個範例,從一批URL中下載檔案

Download from URLs in Google Drive

URLs Example

先假設個情境,要共享一些檔案給其他人。
這時直接給了他們一批原始的分享連結,讓他們能直接用瀏覽器打開。
不直接分享fileId的原因是別人會以為那是串亂碼

但是google drive API目前只支援使用fileId
若想要直接將上面的N個URLs對應的檔案下載下來,總不能一個個手動把fileId切出來

這邊查到了一個在stackoverflow上用正規表達式實現的簡易作法

https://stackoverflow.com/a/16840612

用python的語言來做的話

import re
pattern = "([-\w]{25,})"
fileIds_list = re.findall(
pattern,
urls,
)

這樣能切出 N 個 fileId 的 list

parse fileIds list example

最後再把這坨fileId用for迴圈送進去範例二就結束了~

如果不想自己寫一遍的,可以參考我的github

git clone https://github.com/mistake0316/Download-Google-Drive-Files-From-URLs.gitcd Download-Google-Drive-Files-From-URLs
pip install --upgrade -r requirements.txt
python download_utils.py --urls_file=sample_urls.txt --folder=data

就可以完成下載了

sample_urls.txt
下載結果

結尾

其實Google API拿來寫一些東西蠻方便的,而且並沒有想像中的困難

相信如果有稍微看看上面的程式碼的話,應該知道核心部分其實只有幾行程式碼而已

如果有耐心,相信能夠用Google API寫出一些實用、炫砲的玩意

一個例子像是

  1. 先用人工方式定義好一頁Google簡報的模板
  2. 用 GMail API 並設定若收到什麼關鍵字的電子郵件做什麼事情
  3. 用 Slide API 去生成新的簡報檔
  4. (optional) 用 Drive API 儲存生成簡報檔的 fileId
  5. 用 Drive API 將新的簡報檔共享給先前Email中的發信者
  6. 用 GMail API 將該簡報檔的連結回信給發信者
  7. (optional) 當根源簡報的模板有更動時,觸發一個事件,將所有子簡報檔更新後,重複步驟 6

有時候如果專案要整合的功能太多,用上述方法會要整合一堆套件,有些麻煩,但較可高度客製化

另一種比較進階的模式是直接使用Google Appscripts,該語言已經整合了下面這些功能,如果已經會javascript者,可以無痛的使用該語言

https://developers.google.com/apps-script

最後,下方連結有一些 Google Drive API 的官方教學影片

包含了

File storage in the cloud
Listing your files on Google Drive
Google Drive: uploading & downloading files

想看一些額外範例的可以直接去看看

湯沂達(Yi-Dar, Tang)
Taiwan AI Academy

Self supervised writer. Ask question to myself. Transfer the meaningful path as an article.