如果我想在本地将 Google sheet 下载到 CSV,是否需要为 Google API v4 定义 "redirect_uris"?
If I want to download a Google sheet to CSV locally, do I need "redirect_uris" defined for Google API v4?
我正在尝试使用 Python API 和 Google API v4 在本地下载 Google sheet 并转换它到 CSV 文件。我很高兴这个 运行 作为我本地机器上的脚本。我不需要网络能力。我有这个 Python 代码 ...
from gsheets import Sheets
...
sheets = Sheets.from_files('/Users/davea/Documents/workspace/chicommons/maps/web/configuration_g_client.json')
url = 'https://docs.google.com/spreadsheets/d/1ifpqxxxxxxxxxxxxx5gmvevJ7jc-xxxxxxxxjDS8Me7U/edit#gid=0'
s = sheets.get(url)
out = s.sheets[3].to_csv('Spam.csv', encoding='utf-8', dialect='excel')
print(out)
从 Google 下载的 configuration_g_client.json 文件如下所示 ...
{"web":
{
"client_id":"124xxxx.apps.googleusercontent.com",
"project_id":"ccc-directory-xxxxxxxxx08","auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"xxxxxx13s9",
"javascript_origins":["http://localhost:8000"]
}
}
但是这一行
sheets = Sheets.from_files('/Users/davea/Documents/workspace/chicommons/maps/web/configuration_g_client.json')
死于
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/gsheets/api.py", line 31, in from_files
creds = oauth2.get_credentials(scopes, secrets, storage, no_webserver)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/gsheets/oauth2.py", line 48, in get_credentials
flow = client.flow_from_clientsecrets(secrets, scopes)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/client.py", line 2134, in flow_from_clientsecrets
client_type, client_info = clientsecrets.loadfile(filename,
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 165, in loadfile
return _loadfile(filename)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 126, in _loadfile
return _validate_clientsecrets(obj)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 99, in _validate_clientsecrets
raise InvalidClientSecretsError(
oauth2client.clientsecrets.InvalidClientSecretsError: Missing property "redirect_uris" in a client type of "web".
如果我想在本地 运行,我应该使用不同的客户端类型吗?否则,我需要为“redirect_uris”设置什么值?
编辑: 作为对给出答案的回应,我更新了我的凭据 JSON 文件以包含
"redirect_uris":["http://localhost:8000"]
现在当我在本地 运行 我的脚本时,它会尝试生成浏览器
这很糟糕,因为我想通过 cron 作业在本地 运行 脚本并且不想与浏览器交互。
编辑: 根据有关 运行 使用服务帐户设置脚本的建议。我按照此处的说明创建了服务帐户 - https://developers.google.com/ad-manager/api/authentication#service。以下是生成的项目和关键屏幕...
凭据 JSON 文件如下所示
{
"type": "service_account",
"project_id": "chicommons",
"private_key_id": "ecf14d...",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCcSISusTKvBcO1\nRn9bdD/vYWYyoi0ERi5P0u8+iJQ6WUmYIkKG2aYfyp3kt1/KQJ4YW0M4/AUGAQlz\n5FdS1kTqHkmzwtd+FN8FE6...xxx.../OmXZkvjQej2eA6Txcm/hfuyebkrXnyUm\nycuVzNRsywvGQf/7gWP0y9oQ\n-----END PRIVATE KEY-----\n",
"client_email": "google-sheets-download@chicommons.iam.gserviceaccount.com",
"client_id": "116134130252723375625",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-sheets-download%40chicommons.iam.gserviceaccount.com"
}
但是现在当我 运行 我的脚本试图下载我的 Google sheet 时,我得到这个错误
oauth2client.clientsecrets.InvalidClientSecretsError: Invalid file format. See https://developers.google.com/api-client-library/python/guide/aaa_client_secrets Expected a JSON object with a single property for a "web" or "installed" application
你的情况,下面的修改怎么样?
从您的 configuration_g_client.json
中,我注意到 "javascript_origins":["http://localhost:8000"]
而没有 redirect_uris
。所以请将http://localhost:8080/
添加到redirect_uris
并再次测试。下图是将http://localhost:8080/
设置为redirect_uris
。在这种情况下,您可以按如下方式删除 javascript_origins
。
- 在这里,请将
http://localhost:8080/
设置为redirect_uris
的值,然后点击“保存”按钮。 http://localhost:8080/
的最后一个字符是 /
。似乎默认的 redirect_uris
是 http://localhost:8080/
for oauth2.get_credentials
。请注意。
更新问题的答案:
- 在您更新的问题中,您想使用服务帐户而不是使用 python 的 OAuth2 从 Google 驱动器下载 CSV 数据。
为此,我认为您的授权脚本需要修改。在这个回答中,我想提出一个示例脚本来使用服务帐户实现您的目标。
重要提示:
在使用服务账号的时候,有一点很重要。这是服务帐户的 Google 驱动器与您的 Google 驱动器不同。因此,为了在您的 Google 驱动器中下载 Google Spreadsheet,请与服务帐户的电子邮件共享 Google Spreadsheet。这样,文件就可以被服务账号下载了。请注意这一点。您可以在服务帐户的凭据文件中看到它是client_email
。
示例脚本 1:
在使用之前,请设置credentialFileOfServiceAccount
、emailOfServiceAccount
和file_id
的变量。
import requests
from oauth2client.service_account import ServiceAccountCredentials
credentialFileOfServiceAccount = './###.json'
emailOfServiceAccount = '###'
file_id = '###'
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, scopes='https://www.googleapis.com/auth/drive.readonly')
access_token = creds.create_delegated(emailOfServiceAccount).get_access_token().access_token
url = 'https://www.googleapis.com/drive/v3/files/' + file_id + '/export?mimeType=text%2Fcsv'
headers = {'Authorization': 'Bearer ' + access_token}
res = requests.get(url, headers=headers)
print(res.text)
with open('Spam.csv', 'wb') as f:
f.write(res.content)
- 以上脚本为运行时,
file_id
的Spreadsheet导出为CSV数据,数据保存为Spam.csv
的文件。在这种情况下,检索 Spreadsheet 的第一个选项卡的数据。这与您的脚本相同。
示例脚本 2:
在此示例脚本中,使用了 python 的 googleapis。
import io
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
credentialFileOfServiceAccount = './###.json'
file_id = '###'
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, ['https://www.googleapis.com/auth/drive.readonly'])
service = build('drive', 'v3', credentials=creds)
request = service .files().export_media(fileId=file_id, mimeType='text/csv')
fh = io.FileIO('Spam.csv', mode='wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print('Download %d%%.' % int(status.progress() * 100))
最后一个后续问题的答案:
在上面的示例脚本中,第一个选项卡导出为 CSV 数据。为了导出除第一个选项卡 Google Spreadsheet 之外的 sheets,在此答案中,我想建议更改端点。我认为这种方式可能更简单。示例脚本如下
示例脚本:
使用前,请设置credentialFileOfServiceAccount
、emailOfServiceAccount
和file_id
变量。另外,请设置要导出的 sheet 名称。
import requests
from oauth2client.service_account import ServiceAccountCredentials
credentialFileOfServiceAccount = './###.json'
emailOfServiceAccount = '###'
file_id = '###'
sheet_name = 'Sheet2' # <--- Please set the sheet name you want to export.
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, scopes='https://www.googleapis.com/auth/drive.readonly')
access_token = creds.create_delegated(emailOfServiceAccount).get_access_token().access_token
url = 'https://docs.google.com/spreadsheets/d/' + file_id + '/gviz/tq?tqx=out:csv&sheet=' + sheet_name
headers = {'Authorization': 'Bearer ' + access_token}
res = requests.get(url, headers=headers)
print(res.text)
with open('Spam.csv', 'wb') as f:
f.write(res.content)
如果要使用sheetID(gid),端点如下
url = 'https://docs.google.com/spreadsheets/d/' + file_id + '/gviz/tq?tqx=out:csv&gid=' + gid
当上面的脚本为运行时,file_id
的Spreadsheet中的“Sheet2”导出为CSV数据,数据保存为Spam.csv
.
的文件
我正在尝试使用 Python API 和 Google API v4 在本地下载 Google sheet 并转换它到 CSV 文件。我很高兴这个 运行 作为我本地机器上的脚本。我不需要网络能力。我有这个 Python 代码 ...
from gsheets import Sheets
...
sheets = Sheets.from_files('/Users/davea/Documents/workspace/chicommons/maps/web/configuration_g_client.json')
url = 'https://docs.google.com/spreadsheets/d/1ifpqxxxxxxxxxxxxx5gmvevJ7jc-xxxxxxxxjDS8Me7U/edit#gid=0'
s = sheets.get(url)
out = s.sheets[3].to_csv('Spam.csv', encoding='utf-8', dialect='excel')
print(out)
从 Google 下载的 configuration_g_client.json 文件如下所示 ...
{"web":
{
"client_id":"124xxxx.apps.googleusercontent.com",
"project_id":"ccc-directory-xxxxxxxxx08","auth_uri":"https://accounts.google.com/o/oauth2/auth",
"token_uri":"https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
"client_secret":"xxxxxx13s9",
"javascript_origins":["http://localhost:8000"]
}
}
但是这一行
sheets = Sheets.from_files('/Users/davea/Documents/workspace/chicommons/maps/web/configuration_g_client.json')
死于
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/gsheets/api.py", line 31, in from_files
creds = oauth2.get_credentials(scopes, secrets, storage, no_webserver)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/gsheets/oauth2.py", line 48, in get_credentials
flow = client.flow_from_clientsecrets(secrets, scopes)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/client.py", line 2134, in flow_from_clientsecrets
client_type, client_info = clientsecrets.loadfile(filename,
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 165, in loadfile
return _loadfile(filename)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 126, in _loadfile
return _validate_clientsecrets(obj)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.8/site-packages/oauth2client/clientsecrets.py", line 99, in _validate_clientsecrets
raise InvalidClientSecretsError(
oauth2client.clientsecrets.InvalidClientSecretsError: Missing property "redirect_uris" in a client type of "web".
如果我想在本地 运行,我应该使用不同的客户端类型吗?否则,我需要为“redirect_uris”设置什么值?
编辑: 作为对给出答案的回应,我更新了我的凭据 JSON 文件以包含
"redirect_uris":["http://localhost:8000"]
现在当我在本地 运行 我的脚本时,它会尝试生成浏览器
这很糟糕,因为我想通过 cron 作业在本地 运行 脚本并且不想与浏览器交互。
编辑: 根据有关 运行 使用服务帐户设置脚本的建议。我按照此处的说明创建了服务帐户 - https://developers.google.com/ad-manager/api/authentication#service。以下是生成的项目和关键屏幕...
凭据 JSON 文件如下所示
{
"type": "service_account",
"project_id": "chicommons",
"private_key_id": "ecf14d...",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCcSISusTKvBcO1\nRn9bdD/vYWYyoi0ERi5P0u8+iJQ6WUmYIkKG2aYfyp3kt1/KQJ4YW0M4/AUGAQlz\n5FdS1kTqHkmzwtd+FN8FE6...xxx.../OmXZkvjQej2eA6Txcm/hfuyebkrXnyUm\nycuVzNRsywvGQf/7gWP0y9oQ\n-----END PRIVATE KEY-----\n",
"client_email": "google-sheets-download@chicommons.iam.gserviceaccount.com",
"client_id": "116134130252723375625",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google-sheets-download%40chicommons.iam.gserviceaccount.com"
}
但是现在当我 运行 我的脚本试图下载我的 Google sheet 时,我得到这个错误
oauth2client.clientsecrets.InvalidClientSecretsError: Invalid file format. See https://developers.google.com/api-client-library/python/guide/aaa_client_secrets Expected a JSON object with a single property for a "web" or "installed" application
你的情况,下面的修改怎么样?
从您的 configuration_g_client.json
中,我注意到 "javascript_origins":["http://localhost:8000"]
而没有 redirect_uris
。所以请将http://localhost:8080/
添加到redirect_uris
并再次测试。下图是将http://localhost:8080/
设置为redirect_uris
。在这种情况下,您可以按如下方式删除 javascript_origins
。
- 在这里,请将
http://localhost:8080/
设置为redirect_uris
的值,然后点击“保存”按钮。http://localhost:8080/
的最后一个字符是/
。似乎默认的redirect_uris
是http://localhost:8080/
foroauth2.get_credentials
。请注意。
更新问题的答案:
- 在您更新的问题中,您想使用服务帐户而不是使用 python 的 OAuth2 从 Google 驱动器下载 CSV 数据。
为此,我认为您的授权脚本需要修改。在这个回答中,我想提出一个示例脚本来使用服务帐户实现您的目标。
重要提示:
在使用服务账号的时候,有一点很重要。这是服务帐户的 Google 驱动器与您的 Google 驱动器不同。因此,为了在您的 Google 驱动器中下载 Google Spreadsheet,请与服务帐户的电子邮件共享 Google Spreadsheet。这样,文件就可以被服务账号下载了。请注意这一点。您可以在服务帐户的凭据文件中看到它是client_email
。
示例脚本 1:
在使用之前,请设置credentialFileOfServiceAccount
、emailOfServiceAccount
和file_id
的变量。
import requests
from oauth2client.service_account import ServiceAccountCredentials
credentialFileOfServiceAccount = './###.json'
emailOfServiceAccount = '###'
file_id = '###'
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, scopes='https://www.googleapis.com/auth/drive.readonly')
access_token = creds.create_delegated(emailOfServiceAccount).get_access_token().access_token
url = 'https://www.googleapis.com/drive/v3/files/' + file_id + '/export?mimeType=text%2Fcsv'
headers = {'Authorization': 'Bearer ' + access_token}
res = requests.get(url, headers=headers)
print(res.text)
with open('Spam.csv', 'wb') as f:
f.write(res.content)
- 以上脚本为运行时,
file_id
的Spreadsheet导出为CSV数据,数据保存为Spam.csv
的文件。在这种情况下,检索 Spreadsheet 的第一个选项卡的数据。这与您的脚本相同。
示例脚本 2:
在此示例脚本中,使用了 python 的 googleapis。
import io
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
credentialFileOfServiceAccount = './###.json'
file_id = '###'
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, ['https://www.googleapis.com/auth/drive.readonly'])
service = build('drive', 'v3', credentials=creds)
request = service .files().export_media(fileId=file_id, mimeType='text/csv')
fh = io.FileIO('Spam.csv', mode='wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print('Download %d%%.' % int(status.progress() * 100))
最后一个后续问题的答案:
在上面的示例脚本中,第一个选项卡导出为 CSV 数据。为了导出除第一个选项卡 Google Spreadsheet 之外的 sheets,在此答案中,我想建议更改端点。我认为这种方式可能更简单。示例脚本如下
示例脚本:
使用前,请设置credentialFileOfServiceAccount
、emailOfServiceAccount
和file_id
变量。另外,请设置要导出的 sheet 名称。
import requests
from oauth2client.service_account import ServiceAccountCredentials
credentialFileOfServiceAccount = './###.json'
emailOfServiceAccount = '###'
file_id = '###'
sheet_name = 'Sheet2' # <--- Please set the sheet name you want to export.
creds = ServiceAccountCredentials.from_json_keyfile_name(credentialFileOfServiceAccount, scopes='https://www.googleapis.com/auth/drive.readonly')
access_token = creds.create_delegated(emailOfServiceAccount).get_access_token().access_token
url = 'https://docs.google.com/spreadsheets/d/' + file_id + '/gviz/tq?tqx=out:csv&sheet=' + sheet_name
headers = {'Authorization': 'Bearer ' + access_token}
res = requests.get(url, headers=headers)
print(res.text)
with open('Spam.csv', 'wb') as f:
f.write(res.content)
如果要使用sheetID(gid),端点如下
url = 'https://docs.google.com/spreadsheets/d/' + file_id + '/gviz/tq?tqx=out:csv&gid=' + gid
当上面的脚本为运行时,
的文件file_id
的Spreadsheet中的“Sheet2”导出为CSV数据,数据保存为Spam.csv
.