API Google Фото 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)

Гуглскрипт:

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, api_name, api_version, 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, API_VERSION, 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

person Brad Farrell    schedule 04.01.2021    source источник
comment
Какое полное сообщение об ошибке?   -  person DaImTo    schedule 04.01.2021
comment
RemoveMediaItems просто выдает пустое сообщение JSON даже в случае успеха. Вывод приведенного выше скрипта — это связанный метод Response.json из ‹Response [401]››   -  person Brad Farrell    schedule 04.01.2021


Ответы (1)


Похоже, что в ваших областях вы только включили

['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

Редактировать:

В соответствии с документами вы можете столкнулись с приведенной ниже проблемой, касающейся либо недопустимого элемента мультимедиа, либо случаев, связанных с тем, как мультимедиа попали в альбом (через приложение или как часть загрузки — вы вручную отправляли один из этих элементов мультимедиа во время разработки?) . Может быть, попробуйте удалить элементы мультимедиа, пока не получите тот, который работает.

Вы можете удалить элементы мультимедиа, которые вы добавили из альбома, вызвав Albums.batchRemoveMediaItems.

Весь запрос завершится ошибкой, если будут указаны недопустимые элементы мультимедиа. Частичный успех не поддерживается.

Обратите внимание, что вы можете удалять только элементы мультимедиа, которые ваше приложение добавило в альбом или которые были созданы в альбоме как часть загрузки. Для альбомов, к которым предоставлен общий доступ, вы можете удалять элементы, добавленные другими соавторами, только если вы действуете от имени владельца альбома.

Чтобы удалить элементы мультимедиа из альбома, вызовите Albums.batchRemoveMediaItems с идентификаторами элементов мультимедиа и альбома.

Я взял на себя смелость попробовать это на себе, и мне удалось заставить его работать. Возможно, следующие шаги помогут вам устранить неполадки при удалении, и вы сможете перейти оттуда.

Я начал с использования Попробуйте этот 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)

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]>

Заключительные мысли: я получил 400 ошибок для неправильных идентификаторов альбомов и медиа, прежде чем я понял это правильно. Это наводит меня на мысль, что ваш 401 связан с теми правилами в документах, на которые я ссылался, относительно того, КАК был загружен носитель, который вы пытаетесь удалить, и кому принадлежит этот носитель в соответствии с API.

person Vizzyy    schedule 04.01.2021
comment
Спасибо Виззи. Я добавил область фотобиблиотеки, но все равно получаю ошибку 401. - person Brad Farrell; 04.01.2021
comment
Удалите файл pickle с токеном и повторите авторизацию. Вы должны делать это каждый раз, когда меняете область видимости @BradFarrell - person Vizzyy; 04.01.2021
comment
Кроме того, если вы добавляете эти разрешения верхнего уровня для полного доступа к фотобиблиотеке, я думаю, вы можете удалить другую область edit.apponly. Кроме того, из вашего кода не похоже, что вы делитесь альбомами с другими пользователями, поэтому область общего доступа, возможно, не нужна. - person Vizzyy; 04.01.2021
comment
Сделанный. Все еще есть ошибка 401. Заранее спасибо @Vizzyy. - person Brad Farrell; 04.01.2021
comment
@BradFarrell я добавил еще несколько заметок в свой исходный пост. - person Vizzyy; 05.01.2021