API Gmail получает только 1 МБ данных - PullRequest
0 голосов
/ 25 июня 2019

Я отфильтровал все сообщения, которые я хочу запросить, на ярлык в Gmail, и я успешно возвращаю почту, используя этот фрагмент кода в их сценарии quickstart.py:

# My Code
results = service.users().messages().list(userId='me',labelIds = '{Label_id}', maxResults='10000000').execute()
messages = results.get('messages', [])

for message in messages:
    msg = service.users().messages().get(userId='me', id=message['id'], format='metadata', metadataHeaders=['subject']).execute()
    print(msg['snippet'].encode('utf-8').strip())

Сначала я перечислил все метки и их идентификаторы в более раннем запросе и заменил его там, где написано {Label_id}. И тогда я спрашиваю только поле метаданных предмета. Проблема заключается в том, что ответ возвращает только 1 Мбайт данных. Я знаю это, потому что я перенаправляю вывод в файл и делаю ls -latr --block-size=MB. Более того, я вижу, что в этом ярлыке гораздо больше (более старых) сообщений, чем он возвращает, основываясь на датах. Запрос всегда останавливается на одном и том же сообщении. Ни у кого из них нет никаких привязанностей.

В соответствии с их API-интерфейсом мне следует разрешить:

Daily Usage 1,000,000,000 quota units per day

Per User Rate Limit 250 quota units per user per second

Я не думаю, что это то, что я бью, но, возможно, я ошибаюсь, потому что каждое сообщение имеет 1-3 ответа на него, которые я вижу, и, возможно, те, которые считаются 5 единицами квоты на? Точно сказать не могу. Я попытался поиграть с параметром maxResults, но это, похоже, ничего не изменило.

Я бью кепку здесь или это в моей логике запроса?

РЕДАКТИРОВАТЬ 1

from __future__ import print_function
import pickle
import os.path
import base64
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

## If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://mail.google.com/']

def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('gmail', 'v1', credentials=creds)

    messageArray = []
    pageToken = None
    while True:
        results = service.users().messages().list(userId='me',labelIds = '{Label_ID}', maxResults=500, pageToken=pageToken).execute()
        messages = results.get('messages', [])
        for message in messages:
            msg = service.users().messages().get(userId='me', id=message['id'], format='metadata', metadataHeaders=['subject']).execute()
            messageArray.append(msg)
        pageToken = results.get('nextPageToken', None)
        if not pageToken:
            print('[%s]' % ', '.join(map(str, messageArray)))
            break


if __name__ == '__main__':
    main()

РЕДАКТИРОВАТЬ 2

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

from __future__ import print_function
import pickle
import os.path
import base64
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

## If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://mail.google.com/']

def main():
    """Shows basic usage of the Gmail API.
    Lists the user's Gmail labels.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('gmail', 'v1', credentials=creds)

    pageToken = None
    while True:
        results = service.users().messages().list(userId='me',labelIds = '{Label_ID}', maxResults=500, pageToken=pageToken).execute()
        messages = results.get('messages', [])
        for message in messages:
            msg = service.users().messages().get(userId='me', id=message['id'], format='metadata', metadataHeaders=['subject']).execute()
            print(msg['snippet'].encode('utf-8').strip())
        pageToken = results.get('nextPageToken', None)
        if not pageToken:
            break


if __name__ == '__main__':
    main()

1 Ответ

1 голос
/ 25 июня 2019

maxResults максимальное значение равно 500. Если вы установите его выше, вы все равно получите только 500 сообщений в результатах. Вы можете подтвердить это с помощью лен чека messages.

Вам необходимо реализовать нумерацию страниц .

messages = []
pageToken = None
while True:
  results = service.users().messages().list(userId='me',labelIds = '{Label_id}', maxResults=500, pageToken=pageToken).execute()
  messages.append(results.get(messages, []))
  pageToken = results.get('nextPageToken', None)
  if not pageToken:
    break

Если вы просто хотите получить необработанное неразобранное сообщение электронной почты, попробуйте использовать

# at top of file
from base64 import urlsafe_b64decode

msg = service.users().messages().get(userId='me', id=message['id'], format='raw').execute()
print(urlsafe_b64decode(msg['raw']))
...