问题描述
我有一个脚本,可以定期将一些 Python 编辑的图像上传到 Google 相册。由于没有允许覆盖现有图像的公共 API,我必须
脚本的上传和 GetMediaID 部分工作正常,但删除照片的脚本在 Postman 中测试时效果很好,但在 Python 中运行时,我收到 401 响应。
代码:
from GetMediaID import TACupdatemediaID,SeattleupdatemediaID,northupdatemediaID
import os
import pickle
from googlescript import Create_Service
import json
import requests
dir_path = os.path.join(os.getcwd())
API_NAME = 'photoslibrary'
API_VERSION = 'v1'
CLIENT_SECRET_FILE = dir_path + "\\" + "credentials.json"
print(CLIENT_SECRET_FILE)
ScopES = ['https://www.googleapis.com/auth/photoslibrary.edit.appcreateddata','https://www.googleapis.com/auth/photoslibrary.sharing',''
]
service = Create_Service(CLIENT_SECRET_FILE,API_NAME,API_VERSION,ScopES)
#print(service.albums().list().execute())
upload_url = 'https://photoslibrary.googleapis.com/v1/albums/AIJeZ-HdakZiXwq2i2jVhw8LR4NowHXBgPsBqYXZBt6qE61ELSGUprUkO1BVg4RJdMnzuxMotFJT:batchRemoveMediaItems'
token = pickle.load(open('token_photoslibrary_v1.pickle','rb'))
headers = {
'Authorization': 'Bearer ' + token.token,'Content-type': 'application/json',}
request_body = {
"mediaItemIds": [
SeattleupdatemediaID,TACupdatemediaID,northupdatemediaID,]
}
r = requests.post(upload_url,json=request_body)
print(r.json)
GoogleScript:
import pickle
import os
import datetime
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import Flow,InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
def Create_Service(client_secret_file,api_name,api_version,*scopes):
print(client_secret_file,scopes,sep='-')
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
ScopES = [scope for scope in scopes[0]]
cred = None
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
if os.path.exists(pickle_file):
with open(pickle_file,'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE,ScopES)
cred = flow.run_local_server()
with open(pickle_file,'wb') as token:
pickle.dump(cred,token)
try:
service = build(API_SERVICE_NAME,credentials=cred)
print(API_SERVICE_NAME,'service created successfully')
return service
except Exception as e:
print(e)
return None
def convert_to_RFC_datetime(year=1900,month=1,day=1,hour=0,minute=0):
dt = datetime.datetime(year,month,day,hour,minute,0).isoformat() + 'Z'
return dt
解决方法
看起来好像在你的范围中你只包含了
['https://www.googleapis.com/auth/photoslibrary.edit.appcreateddata','https://www.googleapis.com/auth/photoslibrary.sharing',''
]
我认为您得到的 401(未经授权的 http 代码)是因为您没有删除的范围,只有 appcreateddata
也许可以尝试添加 https://www.googleapis.com/auth/photoslibrary
范围
来源:https://developers.google.com/identity/protocols/oauth2/scopes#photoslibrary
编辑:
根据 the docs,您可能会遇到以下有关无效媒体项目的问题,或者有关媒体如何将其放入相册的情况(通过应用程序或作为上传的一部分——您是否手动在您开发时推送这些媒体项目之一?)。也许尝试删除媒体项目,直到找到一个有效的媒体项目。
您可以通过以下方式从相册中删除已添加的媒体项目 调用相册.batchRemoveMediaItems。
如果指定了无效的媒体项目,则整个请求将失败。 不支持部分成功。
请注意,您只能删除应用程序拥有的媒体项目 添加到相册或已作为相册的一部分在相册中创建的 上传。对于共享的相册,您只能删除由 其他合作者(如果您代表该所有者的行为) 专辑。
要从相册中删除媒体项目,请调用相册.batchRemoveMediaItems 带有媒体项和专辑的标识符。
我冒昧地亲自尝试了一下,我能够让它发挥作用。也许以下步骤可以帮助您解决删除问题,您可以从那里开始。
我首先使用 Try This API 来处理一些媒体项目。我抓住了第一个以确保我 100% 有一个有效的 mediaId。
这是我的身份验证方法:
def get_authorized_session():
scopes = ['https://www.googleapis.com/auth/photoslibrary','https://www.googleapis.com/auth/photoslibrary.sharing']
cred = None
if os.path.exists('config/token.pickle'):
with open('config/token.pickle','rb') as token:
cred = pickle.load(token)
# If there are no (valid) credentials available,let the user log in.
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'config/client_id.json',scopes)
cred = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('config/token.pickle','wb') as token:
pickle.dump(cred,token)
session = AuthorizedSession(cred)
return session
我通过(注意 appcreatedOnly 的参数)获得了专辑 ID
def get_albums(session,appCreatedOnly=False):
params = {
'excludeNonAppCreatedData': appCreatedOnly
}
while True:
albums = session.get('https://photoslibrary.googleapis.com/v1/albums',params=params).json()
# print(f"Server response: {albums}")
if 'albums' in albums:
for a in albums["albums"]:
yield a
if 'nextPageToken' in albums:
params["pageToken"] = albums["nextPageToken"]
else:
return
else:
return
并提出以下要求:
session = get_authorized_session()
album_ids = get_albums()
album_title = 'albumtitlename'
album_id = album_ids[album_title]
request_body = {
"mediaItemIds": [
"ABg_5juBs_P76D6xYEgl3H0hZJB5n3qq1wFbGmRsl16B5dTvbNAa7G8-kxRrQZjBzGIf4SGMtpfdMRBSxEDhoy"
]
}
response = session.post(f'https://photoslibrary.googleapis.com/v1/albums/{album_id}:batchRemoveMediaItems',request_body)
print(response)
回复:
<Response [200]>
结束语:在我得到正确的专辑和媒体 ID 之前,我收到了 400 个错误。这让我相信您的 401 源于我链接的文档中关于您尝试删除的媒体是如何上传的以及根据 API 拥有该媒体的人的那些规则。