Удалить все изображения из файлов DOCX

1

Я искал документацию для python-docx и других пакетов, а также переполнение стека, но не смог найти, как удалить все изображения из файлов docx с помощью python.

Мой конкретный прецедент: мне нужно преобразовать сотни текстовых документов в формат "черновик" для просмотра клиентами. Эти черновики должны быть идентичны исходным документам, но все изображения должны быть удалены/отредактированы от них.

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

Оттуда и из других источников я обнаружил, что файлы docx могут быть прочитаны как простые zip файлы, я не знаю, означает ли это, что это возможно "повторно застегнуть" без изображений, не затрагивая целостность файла docx ( edit: просто удаление изображений работает, но не позволяет python-docx продолжать работать с этим файлом из-за отсутствия ссылок на изображения), но подумал, что это может быть путь к решению.

Есть идеи?

Теги:
docx
python-docx

3 ответа

2
Лучший ответ

Если ваша цель состоит в том, чтобы редактировать изображения, возможно, этот код, который я использовал для аналогичного использования, может быть полезен:

import sys
import zipfile
from PIL import Image, ImageFilter
import io

blur = ImageFilter.GaussianBlur(40)

def redact_images(filename):
    outfile = filename.replace(".docx", "_redacted.docx")
    with zipfile.ZipFile(filename) as inzip:
        with zipfile.ZipFile(outfile, "w") as outzip:
            for info in inzip.infolist():
                name = info.filename
                print(info)
                content = inzip.read(info)
                if name.endswith((".png", ".jpeg", ".gif")):
                        fmt = name.split(".")[-1]
                        img = Image.open(io.BytesIO(content))
                        img = img.convert().filter(blur)
                        outb = io.BytesIO()
                        img.save(outb, fmt)
                        content = outb.getvalue()
                        info.file_size = len(content)
                        info.CRC = zipfile.crc32(content)
                outzip.writestr(info, content)

Здесь я использовал PIL для размытия изображений в некоторых файлах, но вместо фильтра размытия можно было использовать любую другую подходящую операцию. Это очень хорошо работало для моего использования.

  • 0
    Это работает довольно хорошо на самом деле, и будет очень полезно для моего сценария использования. Я надеялся на что-то родное для файлов docx которое удалит изображения (из xml?), Но ваше решение креативно и работает для меня, поэтому я выберу его сейчас (если не появится другое «родное» решение)
  • 0
    @ofer: не могли бы вы опубликовать адаптацию кода, необходимого для удаления изображения?
1

Я не думаю, что в настоящее время он реализован в python-docx.

Картинки в объектной модели Word определяются как плавающие формы или встроенные фигуры. Документация docx утверждает, что она поддерживает только встроенные формы.

Объектная модель Word для встроенных фигур поддерживает метод Delete(), который должен быть доступен. Однако он не указан в примерах InlineShapes и существует аналогичный метод для абзацев. Для абзацев есть открытый запрос функции, чтобы добавить эту функциональность, которая датируется 2014 годом! Если он не добавлен в абзацы, он не будет доступен для InlineShapes, поскольку они реализованы как отдельные абзацы.

Вы можете сделать это с помощью win32com, если у вас установлена машина с установленными Word и Python. Это позволит вам напрямую вызвать объектную модель Word, предоставляя вам доступ к методу Delete(). На самом деле вы, вероятно, можете обмануть - вместо прокрутки документа, чтобы получить каждое изображение, вы можете вызвать Find and Replace, чтобы очистить изображение. Этот вопрос SO говорит о том, что win32com находит и заменяет:

import win32com.client
from os import getcwd, listdir

docs = [i for i in listdir('.') if i[-3:]=='doc' or i[-4:]=='docx'] #All Word file

FromTo = {"First Name":"John",
      "Last Name":"Smith"} #You can insert as many as you want

word = win32com.client.DispatchEx("Word.Application")
word.Visible = True #Keep comment after tests
word.DisplayAlerts = False
for doc in docs:
    word.Documents.Open('{}\\{}'.format(getcwd(), doc))
    for From in FromTo.keys():
        word.Selection.Find.Text = From
        word.Selection.Find.Replacement.Text = FromTo[From]
        word.Selection.Find.Execute(Replace=2, Forward=True) #You made the mistake here=> Replace must be 2  
    name = doc.rsplit('.',1)[0]
    ext = doc.rsplit('.',1)[1]
    word.ActiveDocument.SaveAs('{}\\{}_2.{}'.format(getcwd(), name, ext))

word.Quit() # releases Word object from memory

В этом случае, поскольку нам нужны изображения, нам нужно будет использовать короткий код ^ g как find.Text и blank как замену.

word.Selection.Find
find.Text = "^g"
find.Replacement.Text = ""
find.Execute(Replace=1, Forward=True)
  • 0
    похоже, это может работать, но я в настоящее время не могу проверить с Windows
0

Я не знаю об этой библиотеке, но просматривая документацию, я нашел этот раздел об изображениях. В нем упоминается, что в настоящее время невозможно вставить изображения, отличные от встроенных. Если это то, что у вас есть в ваших документах, я предполагаю, что вы также можете получить их, просмотрев объект Document и затем удалить их?

Документ объясняется здесь.

Хотя это и не дубликат, вы также можете посмотреть на этот вопрос ответ, где пользователь "scanny" объясняет, как он находит образы с помощью библиотеки.

  • 0
    Те, кто является отправной точкой для исследований, я посмотрю на это

Ещё вопросы

Сообщество Overcoder
Наверх
Меню