Google Api python 的客户端库没有 return 文件中的 nextPageToken:带查询的列表方法

Google Api Client Library for python doesn't return nextPageToken in Files: list method with query

我需要获取用户拥有的 google 驱动器中所有文件和文件夹的列表。由于某些原因 file.list 方法没有 return nextPageToken 响应,我只看到很少的结果,因为我无法转到下一页。

我已经为 python 和 API 浏览器尝试了 API 客户端库,但我只收到每个用户的几条记录。

我的代码


users = ['user1@domain.com', 'user2@domain.com']
drive_array = []

if users: 
    for item in users:
        page_token_drive = None
        query = "'%s' in owners" % (item)
        while True:
            drive_result = service_drive.files().list(q=query, corpora='domain', includeTeamDriveItems=False, 
                                                      supportsTeamDrives=False, fields='nextPageToken, files(id,owners)', 
                                                      pageToken=page_token_drive).execute()
            drive_array.extend(drive_result.get('files', []))
            page_token_drive = drive_result.get('nextPageToken', None)
            if not page_token_drive:
                break

我希望获得用户拥有的所有文件的文件 ID 和所有者数组

[
    {
        "id": "12344",
        "owners": [
            {
                "kind": "drive#user",
                "displayName": "User1 User1",
                "photoLink": "https://lg",
                "me": false,
                "permissionId": "1234556",
                "emailAddress": "user1@domain.com"
            }
        ]
    },
    {
        "id": "09875",
        "owners": [
            {
                "kind": "drive#user",
                "displayName": "User1 User1",
                "photoLink": "https://lh5",
                "me": false,
                "permissionId": "56565665655656566",
                "emailAddress": "user1@domain.com"
            }
        ]
    }
]

根据 documentation,要授权对 G Suite API 的请求,您需要使用 OAuth 2.0,并且基本上有两个选项(或者 flows 如果需要坚持使用官方术语):

  1. 带有同意屏幕的用户授权(例如OAuth 2.0 for installed applications
  2. Domain-wide 服务器到服务器应用程序的委派(例如 Using OAuth 2.0 for Server to Server Applications

对于第一个选项,一旦用户完成流程,您就只能访问其资源。所以如果想列出G Suite域中不同用户的drive的所有内容,就需要使用第二个选项。

我还建议您使用 python 客户端 pagination 功能来管理文件列表。

这是选项 1 的工作示例 (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/drive', ]
users = ['user1@domain.eu', 'user2@domain.eu']

# 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())

drive_sdk = build('drive', 'v3', credentials=credentials)

# drive files API
drive_files_api = drive_sdk.files()

for item in users:
    query = "'{}' in owners".format(item)

    drive_list_params = {
        'q': query,
        'corpora': 'domain',
        'includeTeamDriveItems': False,
        'supportsTeamDrives': False,
        'fields': 'files(id,owners),nextPageToken',
    }

    # first request
    files_list_req = drive_files_api.list(**drive_list_params)

    while files_list_req is not None:
        drive_file_list = files_list_req.execute()

        print(drive_file_list.get('files', []))

        # pagination handling
        files_list_req = drive_files_api.list_next(files_list_req, drive_file_list)

如果您运行这样做,系统会提示您授权,脚本会运行在您的驱动器上列出其他用户拥有并与您共享的文件。

如果您想使用带有 domain-wide 委派的 server-to-server 流程来列出所有文件(而不仅仅是与您共享的文件),这里是另一个工作示例。

from googleapiclient.discovery import build
from google.oauth2 import service_account

SCOPES = ['https://www.googleapis.com/auth/drive', ]
users = ['user1@domain.eu', 'user2@domain.eu']

credentials = service_account.Credentials.from_service_account_file('client_secret.json', scopes=SCOPES)

for item in users:
    delegated_credentials = credentials.with_subject(item)
    drive_sdk = build('drive', 'v3', credentials=delegated_credentials)

    # drive files API
    drive_files_api = drive_sdk.files()

    drive_list_params = {
        'corpora': 'domain',
        'includeTeamDriveItems': False,
        'supportsTeamDrives': False,
        'fields': 'files(id,owners),nextPageToken',
    }

    # first request
    files_list_req = drive_files_api.list(**drive_list_params)

    while files_list_req is not None:
        drive_file_list = files_list_req.execute()

        print(drive_file_list.get('files', []))

        # pagination handling
        files_list_req = drive_files_api.list_next(files_list_req, drive_file_list)