Python -docx - вставить картинку в docx из URL - PullRequest
0 голосов
/ 19 июня 2020

Я пытаюсь захватить изображение, размещенное на веб-сайте (например, 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 указывает на мою локальную систему (ie. изображение размещено на моем P C).

Но если я ссылаюсь на ссылку url (online = True), я получаю различные типы исключений (в моей попытке исправить это) от io.UnsupportOperation (поиск) до TypeError (ожидаемый строковый аргумент, получен 'bytes'), причиной всегда является строка run.add_picture.

Код в его нынешнем виде выдает исключение io.UnsupportOperation.

Ответы [ 2 ]

0 голосов
/ 22 июня 2020

Думаю, я решил проблему.

На основе этой ссылки я внес небольшие изменения в свой код.

Я добавил:

import requests, io

Затем я изменил:

imgLinkData = urlopen(imgLink )

на

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

И это, похоже, успешно сгенерировало изображение в моем документе docx, хотя я не совсем уверен, почему , помимо того факта, что urlopen вернул

<class 'http.client.HTTPResponse'>

, а request.get вернул

<class 'requests.models.Response'>

, а .content вернул объект

<class 'bytes'>

.

Дальнейшее чтение , кажется, даже указывает против использования urllib

0 голосов
/ 19 июня 2020

Сохраните изображение в файл, а затем используйте путь к файлу в качестве первого аргумента для .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

...