从docx文件中删除所有图像

时间:2018-06-21 08:27:59

标签: python docx python-docx

我已经在文档中搜索了python-docx和其他软件包,以及堆栈溢出,但是找不到如何使用python从docx文件中删除所有图像的方法。

我的确切用例:我需要将数百个Word文档转换为“草稿”格式,以供客户查看。这些草稿应与原始文档相同,但所有图像都必须从中删除/编辑。

很抱歉,没有提供我尝试过的事情的示例,我尝试过的是数小时未提供任何信息的研究。我发现了有关如何从Word文件中提取图像的问题,但这并没有从实际文档中删除它们:Extract pictures from Word and Excel with Python

从那里和其他来源,我发现docx文件可以读取为简单的zip文件,我不知道这是否意味着可以在没有图像的情况下“重新压缩”而不影响docx文件的完整性(编辑:仅删除图像即可,但由于缺少对图像的引用而阻止python-docx继续使用此文件),但认为这可能是指向文件的路径。解决方案。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

如果您的目标是编辑图像,那么我在类似用例中使用的这段代码可能会有用:

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来模糊某些文件中的图像,但是可以使用任何其他合适的操作来代替模糊滤镜。对于我的用例来说,这很好。

答案 1 :(得分:1)

我认为它当前未在python-docx中实现。

Word对象模型中的图片定义为浮动形状或嵌入式形状。 docx documentation声明它仅支持嵌入式形状。

内联形状的Word Object Model支持Delete()方法,该方法应该可以访问。但是,它没有在examples of InlineShapes中列出,段落也有类似的方法。对于段落,有一个open feature request添加此功能-可以追溯到2014年!如果未将其添加到段落中,则InlineShapes将无法使用它们,因为它们被实现为离散的段落。

如果您安装了装有Word和Python的计算机,则可以使用win32com进行此操作。 这将允许您直接调用Word对象模型,从而使您可以访问Delete()方法。实际上,您可能会作弊-可以滚动查找和替换来清除图像,而不是滚动浏览文档以获取每个图像。 This SO question讨论了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和空白作为替换。

word.Selection.Find
find.Text = "^g"
find.Replacement.Text = ""
find.Execute(Replace=1, Forward=True)

答案 2 :(得分:0)

我对这个库不了解,但是翻阅我发现的文档this section about images。它提到当前无法插入除嵌入式图像以外的其他图像。如果那是您当前在文档中所拥有的,我想您还可以通过在Document对象中查找然后将其删除来检索它们?

here对文档进行了说明。

尽管不是重复的,但您可能还需要查看this question's answer,其中“ scanny”用户说明他如何使用该库查找图像。

相关问题