【问题标题】:Python-docx - insert picture into docx from URLPython-docx - 从 URL 将图片插入 docx
【发布时间】:2020-06-19 07:49:29
【问题描述】:

我正在尝试抓取网站(例如 imgur)上托管的图像并将其添加到 docx。

这是我的初始代码(这是函数的一部分。我已将其剥离为相关代码):

from PIL import Image
from urllib.request import urlopen

thisParagraph = document.sections[0].paragraphs[0]
run = thisParagraph.add_run()

# imgLink is a direct link to the image. Something like https://i.imgur.com/<name>.jpg
# online is a parsed-in boolean to determine if the image link is from an image hosting site
# or from the local machine
if (online):
   imgLinkData = urlopen(imgLink )
   img = Image.open(imgLinkData )
   width, height = img.size
else:
   img = Image.open(imgLink )
   width, height = img.size
   imgLinkData = imgLink 

if (width > 250) or (height > 250):
   if (height > width):
       run.add_picture(imgLinkData, width=Cm(3), height=Cm(4) )
   else:
       run.add_picture(imgLinkData, width=Cm(4), height=Cm(3) )
else:
       run.add_picture(imgLinkData)

在大多数情况下,如果 imgLink 指向我的本地系统(即图像托管在我的 PC 上),则此方法有效。

但如果我引用一个 url 链接(online=True),我会得到各种类型的异常(我试图修复它),范围从 io.UnsupportOperation(搜索)到 TypeError(需要字符串参数,得到' bytes'),原因总是run.add_picture 行。

现在的代码会引发io.UnsupportOperation 异常。

【问题讨论】:

    标签: python python-3.x python-docx


    【解决方案1】:

    将图像保存到文件中,然后使用文件路径作为.add_picture() 的第一个参数。这大概是这样的:

    img.save("my-image.jpg")
    run.add_picture("my-image.jpg", width=Cm(3), height=Cm(4))
    

    作为替代方案,您可以创建一个包含图像的“内存中”文件 (io.BytesIO) 并使用它。第二种方法的优点是不需要访问文件系统。

    import io
    image_stream = io.BytesIO(imgLinkData)
    run.add_picture(image_stream, width=Cm(3), height=Cm(4))
    

    Document.add_picture() 的接口需要一个 str 路径或类似文件的对象(打开的文件或内存中的文件)作为其第一个参数:https://python-docx.readthedocs.io/en/latest/api/document.html#docx.document.Document.add_picture

    【讨论】:

    • 按照建议,我修改为:if (online): imgLinkData = urlopen(imgLink ) img = Image.open(imgLinkData ) width, height = img.size image_stream = io.BytesIO(imgLinkData) 我在该特定行得到了TypeError: a bytes-like object is required, not 'HTTPResponse'。如果可能的话,我宁愿不将图像保存到机器上。
    【解决方案2】:

    我想我可能已经解决了这个问题。

    基于this link,我对自己的代码做了一些细微的修改。

    我补充说:

    import requests, io
    

    然后我改变了:

    imgLinkData = urlopen(imgLink )
    

    imgLinkData= io.BytesIO(requests.get(imgLink ).content )
    

    这似乎已经成功地在我的 docx 文档中生成了图像,虽然我不完全确定为什么,除了 urlopen 返回的事实

    <class 'http.client.HTTPResponse'>
    

    requests.get 返回

    <class 'requests.models.Response'>
    

    和 .content 返回一个

    <class 'bytes'>
    

    对象。

    Further reading 甚至似乎表示反对使用urllib

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 2019-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多