Лучший способ получить доступ к Google Sheet с Python - PullRequest
3 голосов
/ 08 июля 2019

Как автоматизировать процесс получения доступа к таблицам Google?

Сейчас мы используем gspread и oauth2client.service_account, чтобы получить доступ к электронной таблице Google. Он работает нормально, но использование учетных данных OAuth2 заставляет нас вручную передавать каждую электронную таблицу в «client_email» из json-файла учетных данных.

import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = [
            'https://www.googleapis.com/auth/spreadsheets',
        'https://www.googleapis.com/auth/drive'
    ]
credentials = 
ServiceAccountCredentials.from_json_keyfile_name('path.json', scope)
    gs = gspread.authorize(credentials)

Это работает, но как изменить?

Итак, желаемый результат: кто-то поделится со мной электронной таблицей, и я могу сразу же начать работать с ней в Python. Является ли это возможным? Может быть, мы можем использовать некоторые триггеры из входящих писем с информацией об обмене или что-то подобное?

1 Ответ

1 голос
/ 10 июля 2019

Вы можете попробовать этот скрипт.Он имеет несколько разделов, которые мы можем выделить:

  1. Запрос доступа к Диску и Gmail.Как видите, мы используем полную область действия drive вместо drive.file. Это потому, что существует существующая ошибка, приводящая к сбою drive.file (1), поэтому мы должны использовать это.
     from __future__ import print_function
        import pickle
        import sys
        import os.path
        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://www.googleapis.com/auth/drive', 
              'https://www.googleapis.com/auth/gmail.modify']

        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)
        mail_service = build('gmail', 'v1', credentials=creds)
        drive_service = build('drive','v3', credentials=creds)
Объявление некоторых переменных.Здесь нет проблем, просто объявляя переменные, в которых мы будем хранить почтовые идентификаторы, имя файла и имя файла, отформатированные для наших нужд.
     mail_ids = []
     file_name = []
     name_string = []
Получите электронные письма.Мы будем принимать только непрочитанные письма от drive-shares-noreply.После этого мы помечаем их как «прочитанные», поэтому не будем брать их в следующий раз при выполнении скрипта.
    def get_emails(mail_ids):
        user_id = 'me' #Or your email
        query = 'from:drive-shares-noreply@google.com, is:UNREAD' #Will search mails from drive shares and unread
        response = mail_service.users().messages().list(userId=user_id, q=query).execute()
        items = response.get('messages', [])
        if not items:
            print('No unread mails found')
            sys.exit()
        else:
            for items in items:
                mail_ids.append(items['id'])
            for mail_ids in mail_ids:
                mail_service.users().messages().modify(userId=user_id, id=mail_ids, body={"removeLabelIds":["UNREAD"]}).execute() #Marks the mails as read
Получить имена файлов писем.Синтаксис темы сообщения электронной почты «Общие листы» - «Имя файла - приглашение к редактированию», поэтому мы выберем тему каждого сообщения и отформатируем строку позже.
def get_filename(mail_ids, file_name):
    user_id = 'me'
    headers = []
    for mail_ids in mail_ids:
        response = mail_service.users().messages().get(userId=user_id, id=mail_ids, format="metadata", metadataHeaders="Subject").execute()
        items = response.get('payload', [])
        headers.append(items['headers'])
    length = len(headers)
    for i in range(length):
        file_name.append(headers[i][0]['value'])

def process_name(file_name, name_string):
    for file_name in file_name:
        name_string.append(str(file_name).replace(" - Invitation to edit", ""))

Дать разрешения на client_email
def give_permissions(name_string):
    for name_string in name_string:
        body = "'{}'".format(name_string)
        results = drive_service.files().list(q="name = "+body).execute()
        items = results.get('files', [])
        if not items:
            print('No files found.')
            sys.exit()
        else:
            print('Files:')
            for item in items:
                print(u'{0} ({1})'.format(item['name'], item['id']))
                file_id = item['id']

    user_permission = {
        'type': 'user',
        'role': 'writer',
        'emailAddress': 'your_client_email'
    }
    drive_service.permissions().create(body=user_permission, fileId=file_id).execute()
И тогда нам просто нужно вызвать функции
get_emails(mail_ids)
get_filename(mail_ids, file_name)
process_name(file_name, name_string)
give_permissions(name_string)

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

(1) Область drive.file работает только с определенными файлами, согласно последнему обновлению документации

...