使用Google API创建和共享电子表格

时间:2018-11-19 05:11:44

标签: python-3.x google-sheets google-drive-api

我有一个脚本,我试图通过该脚本传递数据,这将创建一个Google电子表格并与一群人共享。我不知道为什么会遇到拒绝我的权限的错误。

我已经通过了Google Developer Console,并创建了一个项目,并启用了电子表格api和驱动器api。我下载了一组oauth2凭据,并将其命名为“ credentials.json”

从那里我使用v4表格和v3驱动器版本根据google api示例编写了此脚本:

from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

SCOPES = ['https://www.googleapis.com/auth/drive',
          'https://www.googleapis.com/auth/spreadsheets']
CREDENTIALS = r'google_api\credentials.json'
TEST_ADD_EMAIL = <the test gmail address>

class GoogleManager:
    def __init__(self):
        self.sheets_service = None
        self.drive_service = None

    def connect(self):
        store = file.Storage(r'google_api\token.json')
        creds = store.get()

        if not creds or creds.invalid:
            flow = client.flow_from_clientsecrets(CREDENTIALS, SCOPES)
            creds = tools.run_flow(flow, store)

        self.sheets_service = build('sheets', 'v4', http=creds.authorize(Http()))
        self.drive_service = build('drive', 'v3', http=creds.authorize(Http()))

    def drive_add_writer_perm(self, fileId, emails):
        def callback(request_id, response, exception):
            if exception:
                raise exception
            else:
                print(f"Permission Id: {response.get('id')}")

        if isinstance(emails, str):
            emails = [emails]
        elif not isinstance(emails, (list,tuple)):
            raise TypeError('Emails must be str or list-like object')

        batch = self.drive_service.new_batch_http_request(callback=callback)
        for email in emails:
            user_permission = ({'type': 'user',
                                'role': 'writer',
                                'emailAddress': email
                                })
            batch.add(self.drive_service.permissions().create(fileId=fileId,
                                                      body=user_permission,
                                                      fields='id'))
        res = batch.execute()
        return res

    def create_new_sheet(self, workbook_name):
        spreadsheet = {'properties': {'title': workbook_name}
                       }
        gSheet = self.sheets_service.spreadsheets()
        newsheet = gSheet.create(body=spreadsheet, fields='spreadsheetId').execute()
        return newsheet

从那里运行:

gmanager = GoogleManager()
gmanager.connect()

new_sheet = gmanager.create_new_sheet('Test Sheet')

sheet_id = new_sheet.get('spreadsheetId')
gmanager.drive_add_writer_perm(sheet_id, TEST_ADD_EMAIL)

但是我得到这个错误:

raise HttpError(resp, content, uri=request.uri).errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/drive/v3/files/1PuxZR0Cx2tGi7c1worVc_Ivj9kZijq_xwwndix6I9as/permissions?fields=id&alt=json returned "Insufficient Permission">

谁能解释为什么?我究竟做错了什么?

编辑:当我进入该链接时,我得到的响应是这样的:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "required",
    "message": "Login Required",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Login Required"
 }
}

我没有登录屏幕,这是怎么回事?

1 个答案:

答案 0 :(得分:0)

经过一番游戏之后,似乎不建议同时建立两个服务。我无法解释为什么,希望有人可以解释,但是通过构建两者,然后先调用另一个,则其他服务被破坏了。

将我的代码更改为此可行:

from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

SCOPES = ['https://www.googleapis.com/auth/drive',
          'https://www.googleapis.com/auth/spreadsheets']
CREDENTIALS = r'google_api\credentials.json'
TEST_ADD_EMAIL = <my_test_email>

class GoogleManager:
    def __init__(self):
        self.store = None
        self.flow = None
        self.creds = None

    def connect(self):
        self.store = file.Storage(r'google_api\token.json')
        self.creds = self.store.get()

        if not self.creds or self.creds.invalid:
            self.flow = client.flow_from_clientsecrets(CREDENTIALS, SCOPES)
            self.creds = tools.run_flow(self.flow, self.store)

    def add_writer_perm(self, fileId, email):
        def callback(request_id, response, exception):
            if exception:
                raise exception
            else:
                print(f"Permission Id: {response.get('id')}")

        user_permission = ({'type': 'user',
                            'role': 'writer',
                            'emailAddress': email
                            })
        drive_service = build('drive', 'v3', http=self.creds.authorize(Http()))
        res = drive_service.permissions().create(fileId=fileId,
                                                  body=user_permission,
                                                  fields='id').execute()
        return res

    def create_new_sheet(self, workbook_name):
        spreadsheet = {'properties': {'title': workbook_name}
                       }
        sheets_service = build('sheets', 'v4', http=self.creds.authorize(Http()))
        gSheet = sheets_service.spreadsheets()
        newsheet = gSheet.create(body=spreadsheet, fields='spreadsheetId').execute()
        return newsheet


def main():
    gmanager = GoogleManager()
    gmanager.connect()

    new_sheet = gmanager.create_new_sheet('Test Sheet')
    sheet_id = new_sheet.get('spreadsheetId')

    gmanager.drive_add_writer_perm(sheet_id, TEST_ADD_EMAIL)