Google 相册 API BatchRemoveMediaItems 适用于 Postman 但不适用于 Python

如何解决Google 相册 API BatchRemoveMediaItems 适用于 Postman 但不适用于 Python

我有一个脚本,可以定期将一些 Python 编辑的图像上传到 Google 相册。由于没有允许覆盖现有图像的公共 API,我必须

  1. 获取相册中图片的 MediaID,
  2. 将它们从相册中删除
  3. 上传新的。

脚本的上传和 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 拥有该媒体的人的那些规则。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?