Python:从 google 驱动器 api 下载文件时出现问题,超出了未经身份验证使用的每日限制

Python: Issues downloading file from google drive api, getting daily limit for unauthenticated use exceeded

问题陈述:

当我尝试从 google 驱动器 api 为我的 python 应用程序下载文件时,我遇到了一个问题。我今天才开始使用它,所以我可能在做一些愚蠢的事情,所以请耐心等待 :)。

我遇到的问题是,在使用驱动器-api 验证我的应用程序后,我可以从 google 驱动器读取文件和元数据,但我无法下载它们。下面贴出相关代码供参考。

遵循的步骤:

我首先按照说明启用了 OAuth2,并获取了凭据。json/client_secrets。json。我确保范围在权限方面是正确的,然后生成了我的 pickle 文件。从那里,我使用文档和快速入门指南中的代码来编写我的代码。从那里,我无法取得任何进展。我认为我可能需要对我的应用程序进行安全评估,但我不打算发布它,所以我认为这种级别的权限对开发人员来说没问题。 我看到许多其他关于此的堆栈溢出帖子,但我没有得到任何帮助(我以为我遵循了所有相同的步骤来验证并为我的应用程序启用 drive-api 权限)。

我还无法下载单个文件,所以我认为我没有达到每日限制。我认为我没有正确进行请求身份验证,但我找不到任何相关文档。如果有任何帮助,我将不胜感激。

参考代码:

我所有的代码都是直接从文档中获取的。以下是相关的 links:

  1. 授权和列表文件:https://developers.google.com/drive/api/v3/quickstart/python
  2. 下载文件:https://developers.google.com/drive/api/v3/manage-downloads
  3. delete_file: https://developers.google.com/drive/api/v3/reference/files/delete#auth

初始化代码如下:

# packages
from __future__ import print_function
import pickle
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient import errors
from googleapiclient.http import MediaIoBaseDownload

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive'] # set permisions to read/write/delete
creds = None
if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
             'client_secrets.json', SCOPES)
        creds = flow.run_local_server(port=0)
    with open('token.pickle', 'wb') as token:
        pickle.dump(creds, token)
drive = build('drive', 'v3', credentials=creds)

这是我的驱动器下载功能:

def download_from_drive_to_local(drive, fname):
    # search for image in drive
    file_search = drive.files().list(
        q=f"name = '{fname}'", 
        spaces='drive', 
        fields="nextPageToken, files(id, name)").execute()
    items = file_search.get('files', [])
    print('Files retrieved: ', items)
    
    # download retrieved image from drive
    item_ids = [i['id'] for i in items]
    if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
    for i in items:
        request = drive.files().get_media(fileId=i)
        fh = io.BytesIO()
        downloader = MediaIoBaseDownload(fh, request)
        done = False
        while done is False:
            status, done = downloader.next_chunk()
        break

    # delete retrieved image from drive
    for i in items:
        try:
            drive.files().delete(fileId=i).execute()
        except errors.HttpError as error:
            print(f'An error occured deleting file id <{i}>: {error}.')
    # write bytearray to file
    with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)

还有我的错误结果:

点击 link 给我这个:

修改点:

  • 当我看到你的脚本时,我认为 for i in items:items 来自 items = file_search.get('files', [])。在这种情况下,i 就像 {'name': '###', 'id': '###'}。当它被用作 request = drive.files().get_media(fileId=i)i 时,文件被用作 {'name': '###', 'id': '###'}。我认为这就是您遇到问题的原因。

  • 并且,当您使用fh = io.BytesIO()将下载的数据保存为文件时,保存脚本如下

      with io.open(filename, 'wb') as f:
          fh.seek(0)
          f.write(fh.read())
    
  • item_ids的长度为0时,出现错误

当以上几点反映到你的脚本中,就变成了下面这样。

修改后的脚本:

从:
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1: print("Warning: multiple files exist with the same name. Using first file found.")
for i in items:
    request = drive.files().get_media(fileId=i)
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
    break

# delete retrieved image from drive
for i in items:
    try:
        drive.files().delete(fileId=i).execute()
    except errors.HttpError as error:
        print(f'An error occured deleting file id <{i}>: {error}.')
# write bytearray to file
with open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as file: file.write(fh)
到:
# download retrieved image from drive
item_ids = [i['id'] for i in items]
if len(item_ids) > 1:
    print("Warning: multiple files exist with the same name. Using first file found.")
for i in item_ids:
    request = drive.files().get_media(fileId=i)
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
    break

# delete retrieved image from drive
for i in item_ids:
    try:
        drive.files().delete(fileId=i).execute()
    except errors.HttpError as error:
        print(f'An error occured deleting file id <{i}>: {error}.')

# write bytearray to file
if item_ids != []:
    with io.open(os.path.join(self.download_dir, f'{fname}.tif'), 'wb') as f:
        fh.seek(0)
        f.write(fh.read())