1

Unable to get all results of mediaItems.search:

photos = google.get_service(credentials, 'photoslibrary', 'v1')
request = photos.albums().list(pageSize=50)
while request is not None:
    result = request.execute()
    for album in result['albums']:
        request2 = photos.mediaItems().search(body={'albumId': album['id']})
        while request2 is not None:
            result2 = request2.execute()
            request2 = photos.mediaItems().search_next(request2, result2)
            print('nextpageToken' in result2, request2)
    request = photos.albums().list_next(request, result)

Running this fails on the first search_next() call with

[...]
  File "/usr/local/lib/python3.7/dist-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/googleapiclient/http.py", line 851, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://photoslibrary.googleapis.com/v1/mediaItems:search?alt=json returned "Invalid JSON payload received. Unexpected end of string. Expected an object key or }.

That library isn't really supported it seems, so that might be the problem, or am I missing something here?

Lorenzo Persichetti
  • 1,480
  • 15
  • 24
Toto
  • 161
  • 4

2 Answers2

1

The google-api-python-client is generic client for all the Google's discovery based APIs and as such it supports all the API based on this protocol including the Photos one.

The correct way to use the services is to invoke the build method and after that use the available methods of the services.

Beside this you always want to use list_next as search_next does not exists.

Here is an example of the photos API working on my laptop (python 3.6)

import os
import pickle

from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

SCOPES = ['https://www.googleapis.com/auth/photoslibrary.readonly', ]


# we check if we save the credentials in the past and we reuse them
if not os.path.exists('credentials.dat'):

    # no credentials found, we run the standard auth flow
    flow = InstalledAppFlow.from_client_secrets_file('client_id.json', SCOPES)
    credentials = flow.run_local_server()

    with open('credentials.dat', 'wb') as credentials_dat:
        pickle.dump(credentials, credentials_dat)
else:
    with open('credentials.dat', 'rb') as credentials_dat:
        credentials = pickle.load(credentials_dat)

if credentials.expired:
    credentials.refresh(Request())

photos_sdk = build('photoslibrary', 'v1', credentials=credentials)

# photos API
photos_albums_api = photos_sdk.albums()
photos_mediaitems_api = photos_sdk.mediaItems()

albums_list_params = {
    'pageSize': 50,
}

# first request
albums_list_req = photos_albums_api.list(**albums_list_params)

while albums_list_req is not None:
    photos_albums_list = albums_list_req.execute()

    # print(photos_albums_list)

    for album in photos_albums_list['albums']:
        print(album['title'])

        mediaitems_search_req = photos_mediaitems_api.search(body={'albumId': album['id']})

        while mediaitems_search_req is not None:
            mediaitems_search = mediaitems_search_req.execute()

            print(mediaitems_search)

            # mediaItems pagination management
            mediaitems_search_req = photos_mediaitems_api.list_next(mediaitems_search_req, mediaitems_search)

    # albums pagination handling
    albums_list_req = photos_albums_api.list_next(albums_list_req, photos_albums_list)
Lorenzo Persichetti
  • 1,480
  • 15
  • 24
  • This is correct. Even though the python API shows the `search_next()` method to me, it's apparently a false positive, and you should (after calling e.g. `search()` once), follow up by running `list_next()` on the request and response returned by the first `search()` (or consecutive `list_next()`s. – myke Apr 16 '21 at 20:52
0

If there are more results than the specified pageSize, the API returns a pageToken, you should use to request the next part. See the example here Access Google Photo API with Python using google-api-python-client

Wilfried
  • 96
  • 2
  • 5