如何使用 Python 的 ID 获取 Google Drive 上文件的 url

Posted

技术标签:

【中文标题】如何使用 Python 的 ID 获取 Google Drive 上文件的 url【英文标题】:How to get the url of a file on Google Drive using its ID with Python 【发布时间】:2022-01-20 08:33:11 【问题描述】:

在下面的代码中,我获取了 Google Drive 上 csv 文件的 fileID。现在,我想将文件内容直接存储在 pandas 框架中,而不是下载 csv 文件然后提取数据(如代码所示)。

import io
import os.path
import pandas as pd

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload


# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']

# Login to Google Drive
def login():

    creds = None
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)

    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        print ("Login to your to your Google Drive account which holds/shares the file database")
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                './src/credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    # Return service
    service = build('drive', 'v3', credentials=creds)
    
    return service


# Download files from Google Drive
def downloadFile(file_name):

    # Authenticate
    service = login()

    # Search file by name
    response = service.files().list(q=f"name='file_name'", spaces='drive', fields='nextPageToken, files(id, name)').execute()
    for file in response.get('files', []):
        file_id = file.get('id')

    # Download file file if it exists
    if ("file_id" in locals()):
        request = service.files().get_media(fileId=file_id)
        fh = io.FileIO(f"./data/file_name.csv", "wb")
        downloader = MediaIoBaseDownload(fh, request)
        print (f"Downloading file_name.csv")
    else:
        print (f"\033[1;31m Warning: Can't download >> file_name << because it is missing!!!\033[0;0m")

    return


downloadFile("NameOfFile")

有什么方法可以实现吗? 非常感谢您的帮助

【问题讨论】:

虽然我不确定我是否能正确理解你的情况,但我提出了一个答案。你能确认一下吗?如果我误解了您的情况并且没有用处,我深表歉意。 【参考方案1】:

来自The problem is to be able to do that I need the file's URL but I'm not able to retrieve it.,我认为您的文件可能是 Google 电子表格。当文件是 Google 电子表格时,webContentLink 不包含在检索到的元数据中。

如果我对你的情况的理解是正确的,那么下面的修改呢?

修改脚本:

发件人:

file_id = file.get('id')

# !!! Here, I would like to get the URL of the file and download it to a pandas data frame !!!
file_url = file.get("webContentLink")

收件人:

file_id = file.get('id')
file_url = file.get("webContentLink")
if not file_url:
    request = service.files().export_media(fileId=file_id, mimeType='text/csv')
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download %d%%" % int(status.progress() * 100))
    fh.seek(0)
    df = pd.read_csv(fh)
    print(df)
在此修改中,使用 Drive API 将 Google 电子表格导出为 CSV 数据,并将导出的数据放入数据框中。 在本次修改中,请添加import iofrom googleapiclient.http import MediaIoBaseDownload

注意:

在这种情况下,Google 电子表格使用 Drive API 导出为 CSV 数据。所以请包括https://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/drive的范围。当您的作用域仅为https://www.googleapis.com/auth/drive.metadata.readonly 时,会发生错误。请注意这一点。

参考:

Files: export

补充:

当文件为CSV数据时,请进行如下修改。

file_id = file.get('id')
request = service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
    status, done = downloader.next_chunk()
    print("Download %d%%" % int(status.progress() * 100))
fh.seek(0)
df = pd.read_csv(fh)
print(df)

【讨论】:

您好 Tanaike,感谢您的快速回答。不幸的是,在执行您的代码提案时,它总是给我一个错误,说“pandas.errors.EmptyDataError: No columns to parse from file”。我会更新我的问题,让它变得更准确。 我解决了这个问题。无法使用“export_media”下载 csv 文件。相反,必须使用“get_media”,然后你的代码就像一个魅力。能否请您更新一下,以便我将其标记为正确答案? @pa1ric6 感谢您的回复。我为文件是 CSV 数据的情况添加了一个修改后的脚本。你能确认一下吗?使用io.FileIO 时,将下载的文件保存为文件。使用io.BytesIO()时,无需创建文件即可将CSV数据放入dataframe中。 修改后的脚本完美运行。谢谢你帮助我。 @pa1ric6 感谢您的回复。我很高兴你的问题得到了解决。也谢谢你。

以上是关于如何使用 Python 的 ID 获取 Google Drive 上文件的 url的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python获取gmail的ID

如何在 Python Cassandra 中获取最后插入的 id?

Python 如何从使用 oauthlib 的帐户身份验证获取 ID_Token 以与 Open ID Connect 一起使用

如何使用 Python 的 ID 获取 Google Drive 上文件的 url

如何在使用 Python 插入 MySQL 数据库后获取“id”?

在 python 中使用 MySQLdb 插入 mysql 后,如何安全有效地获取行 ID?