首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建图像,然后使用其API将其添加到Google幻灯片

创建图像,然后使用其API将其添加到Google幻灯片
EN

Stack Overflow用户
提问于 2021-02-25 19:34:29
回答 2查看 281关注 0票数 1

我想用Python创建一个图像,matplotlib图,然后自动插入到google幻灯片演示文稿中。

我已经有了一个自动的google幻灯片演示。它更新了大量的文本,还用一些文本交换了一些设置的照片,即这5张照片总是相同的。使用Google API文档,弄清楚所有这些花了相当多的时间。我非常依赖Google API Github DocumentationCore Python Programming BlogReplacing text & images with the Google Slides API

虽然有一些与Google Service API帐户共享图像的例子,但我从来没有让它工作过。我只能通过使我的google驱动器中的图像对公众可见来让它将文本更新为图像。否则(例如,当服务帐户有访问权限,但公众没有访问权限时),我会得到这个错误:

代码语言:javascript
运行
AI代码解释
复制
<HttpError 400 when requesting [image URL] returned "Invalid requests[2].replaceAllShapesWithImage: There was a problem retrieving the image. The provided image should be publicly accessible, within size limit, and in supported formats.". Details: "Invalid requests[2].replaceAllShapesWithImage: There was a problem retrieving the image. The provided image should be publicly accessible, within size limit, and in supported formats.">

如果我将图像共享更改为公共,它就会起作用。

我知道有时谷歌的应用程序接口就是不起作用,正如here和我所看到的那样,我也会遇到这个错误。只需等待几个小时或等到明天,它就会再次工作,只要图像是公开的。通常,当出现这种情况时,我会得到以下错误:

代码语言:javascript
运行
AI代码解释
复制
HttpError 400 when requesting [image URL] "Invalid requests[0].replaceAllShapesWithImage[or createImage]: Access to the provided image was forbidden."

如何使用google API将在Python中创建的图像保存到google驱动器文件夹中,并使其可公开访问?或!更妙的是,当照片与创建幻灯片的google服务帐户共享时,如何将照片保存到google驱动器文件夹中,并使图像批量更新工作,但没有将其完全公开?

这是我到目前为止的代码:

代码语言:javascript
运行
AI代码解释
复制
from matplotlib import pyplot as plt
import json
import unidecode
from oauth2client.service_account import ServiceAccountCredentials
from httplib2 import Http
from apiclient import discovery
import pandas as pd


plt.bar(['hi', 'how', 'are', 'you'], [3,6,3,8], color="skyblue")
plt.savefig('test_bar_plot.png')


# google slides authorization
json_key  = json.load(open('../../creds/creds_file.json'))
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] #would love to reduce scope if possible
creds = ServiceAccountCredentials.from_json_keyfile_dict(json_key, scope)

# file to copy for slide deck
TMPLFILE='test_run_slide_deck_template'

HTTP = creds.authorize(Http())
DRIVE =  discovery.build('drive',  'v3', http=HTTP)
SLIDES = discovery.build('slides', 'v1', http=HTTP)

# find slide template, delete copy if it already exists, then make a new copy
file_list = pd.DataFrame(DRIVE.files().list().execute().get('files'))
tempfileSTR = 'test_run_slide_deck'
new_file = '_copy'

try:
    DECK_ID= file_list[file_list.name == tempfileSTR+new_file]['id'].values[0]
    print("** Found File ID for %s" % (tempfileSTR+new_file))
    file = DRIVE.files().delete(fileId=DECK_ID).execute()
    print("** Deleting file for %s" % (tempfileSTR+new_file))
except IndexError:
    print("** Did NOT Find File ID for %s" % (tempfileSTR+new_file))
rsp = DRIVE.files().list(q="name='%s'" % TMPLFILE).execute().get('files')[0]
DATA = {'name': tempfileSTR+new_file, 'parents':['14CvIXemPv5fGcLaiTj_HfMXZS_OKI6Lv']}
print('** Copying template %r as %r' % (rsp['name'], DATA['name']))
DECK_ID = DRIVE.files().copy(body=DATA, fileId=rsp['id']).execute().get('id')

# get the presentation and slides 
presentation = SLIDES.presentations().get(presentationId=DECK_ID).execute()
slides = presentation.get('slides')

# create dictionary of what to update for text
report_dict = {"{{change_to_hey_SO}}":"Hi StackOverflow"
           ,"{{change_to_farewell}}":"Bye StackOverflow"}
reqs =[]
for key in report_dict:
    reqs.append({'replaceAllText': {'containsText': {'text': key},
        'replaceText': report_dict[key]}},)

# create dictionary for what to update for an image already in the drive 
def find_img(IMG_FILE):
    rsp = DRIVE.files().list(q="name='%s'" % IMG_FILE).execute().get('files')[0]
    baseURL = "http://drive.google.com/uc?export=view&id="
    return baseURL+rsp['id']

def image_section(image_replace_text, image_file_name):
    image_json = {
        'replaceAllShapesWithImage': {
        'imageUrl':  find_img(image_file_name),
        'imageReplaceMethod': 'CENTER_INSIDE',
        'containsText': {
            'text': image_replace_text,
            'matchCase': True
            }
        }
    }
    return image_json



# add image update to the list for batch updating 
reqs.append(image_section('{{make_me_a_rooster}}', 'rooster_test.png')) 
    
 

# take saved bar plot, 'test_bar_plot.png', upload it to google drive, make it public or make sharing it with the service account work and use the image_section and find_image functions to add it to the reqs updating list for the batch update below.

# [added edit] this uploads the image file, to the same shared folder as the slide deck (shared with user and service account). 
# but does not make the image public and I get the same error as above when it's not public. 
file_metadata = {'name': 'test_bar_plot.png', 'parents':['14CvIXemPv5fGcLaiTj_HfMXZS_OKI6Lv']}
media = discovery.MediaFileUpload('test_bar_plot.png', mimetype='image/png')
file = DRIVE.files().create(body=file_metadata,
                                        media_body=media,
                                        fields='id').execute()
    
# add to reqs list 
reqs.append(image_section('{{update_chart}}', 'test_bar_plot.png')) #, img_lookup

条形图

更新前的幻灯片

代码语言:javascript
运行
AI代码解释
复制
SLIDES.presentations().batchUpdate(body={'requests': reqs}, presentationId=DECK_ID).execute()
print('DONE')

更新后的幻灯片

This documentation是查找MediaFileUpload的主要链接,在示例中没有显示其他参数,我很难找到其他地方是否列出了其他参数。

EN

回答 2

Stack Overflow用户

发布于 2021-02-26 14:21:13

您遇到了问题,因为服务帐户是而不是域的一部分,因此权限将与任何不相关的用户相同。Like the documentation states

与用户帐户不同,

服务帐户不是您的Google Workspace域的成员。如果您与Google Workspace域中的所有成员共享Google Workspace资产,如文档或事件,则不会与服务帐户共享这些资产。同样,由服务帐户创建的Google Workspace资产也不是在您的Google Workspace域中创建的。因此,您的Google Workspace和云身份管理员无法拥有或管理这些资产。

发生在您身上的情况是,幻灯片的所有者没有添加图像的权限(您正尝试将其添加为链接)。当服务帐户尝试访问未公开的幻灯片时,也会发生同样的情况。

让它工作的最简单的方法是impersonate a user,这样服务帐户就可以像用户一样进行API调用。另一种选择是有一个共享文件夹/驱动器,服务帐户和用户都可以在其中添加切片和图像(文件将自动共享给所有帐户)。您也可以在每次上传或创建文件时手动与其他帐户共享该文件。

票数 0
EN

Stack Overflow用户

发布于 2021-08-31 08:43:28

我还想找到一种使用Python将图片上传到Google幻灯片的方法。我创建了一个程序,将图像上传到Google Cloud Storage;为它们创建一个签名的URL;然后使用该URL将图像导入到Google幻灯片中。它是麻省理工学院许可下的here,可能是一个有用的工具/资源。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66375296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档