python-3.x - Python:从谷歌驱动器 api 下载文件时出现问题,超过了未经身份验证的使用的每日限制
问题描述
问题陈述:
尝试从 google drive api 为我的 python 应用程序下载文件时,我遇到了一个问题。我今天才开始使用它,所以我可能在做一些愚蠢的事情,所以请耐心等待:)。
我遇到的问题是,在使用 drive-api 对我的应用程序进行身份验证后,我可以从谷歌驱动器中读取文件和元数据,但我无法下载它们。下面贴出相关代码供参考。
遵循的步骤:
我首先按照说明启用 OAuth2,并获取 credentials.json/client_secrets.json。我确保范围在权限方面是正确的,然后生成了我的 pickle 文件。从那里,我使用文档和快速入门指南中的代码来制作我的代码。从那里,我无法取得任何进展。我认为我可能需要对我的应用程序进行安全评估,但我不打算发布它,所以我认为这种级别的权限对开发人员来说会很好。我看到许多其他关于此的堆栈溢出帖子,但我没有得到任何帮助(我以为我遵循了所有相同的步骤来验证和启用我的应用程序的驱动器 API 权限)。
我还无法下载单个文件,所以我认为我没有达到每日限制。我认为我没有正确地进行请求身份验证,但我找不到任何文档。我会很感激任何帮助,谢谢。
参考代码:
我拥有的所有代码都直接取自文档。以下是相关链接:
- 授权和列表文件:https ://developers.google.com/drive/api/v3/quickstart/python
- 下载文件:https ://developers.google.com/drive/api/v3/manage-downloads
- 删除文件: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)
解决方案
修改点:
当我看到你的剧本时,我以为
items
是for i in items:
来自items = file_search.get('files', [])
. 在这种情况下,i
就像{'name': '###', 'id': '###'}
. 当 this 用作i
of 时request = drive.files().get_media(fileId=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())
推荐阅读
- powershell - 从脱机注册表文件中读取值
- ios - 加载 youtube 视频后获取视频时长
- angular - Angular 5:TypeScript 编译中缺少。请通过 'files' 或 'include' 属性确保它在您的 tsconfig 中
- laravel - 我们如何在 ReactJS 渲染中显示 Laravel 验证响应?
- opencv - cv2.stereoCalibrate 标准错误
- rest - 将 cURL 转换为浏览器请求?
- reactjs - React 正在将 FontAwesome 样式渲染到页面
- python - 对特定数据框列应用 zscore 规范化
- scheme - 环境模型
- css - 我的 Tumblr 博客第一列中的帖子之间的空格