使用 python-docx 从 .docx 文件中提取图像位置

Extract image position from .docx file using python-docx

我正在尝试使用 python-docx 库从 .docx 文件中获取图像索引。我能够提取图像的名称、图像的高度和宽度。但不是它在 word 文件中的索引

import docx
doc = docx.Document(filename)
for s in doc.inline_shapes:
    print (s.height.cm,s.width.cm,s._inline.graphic.graphicData.pic.nvPicPr.cNvPr.name)

输出

21.228  15.920 IMG_20160910_220903848.jpg

事实上,我想知道是否有任何更简单的方法来获取图像名称,例如 s.height.cm 获取了我的身高(以厘米为单位)。我的主要要求是了解图像在文档中的位置,因为我需要提取图像并对其进行一些处理,然后再次将图像放回相同的位置

API不直接支持此操作。

但是,如果您愿意深入研究内部结构并使用底层 lxml API,这是可能的。

一般的做法是访问要检查和修改的图片对应的ImagePart实例,然后读写._blob属性(以字节形式保存图片文件) .

这个样本 XML 可能会有帮助: http://python-docx.readthedocs.io/en/latest/dev/analysis/features/shapes/picture.html#specimen-xml

从包含图片的内联形状中,您得到 <a:blip> 元素:

blip = inline_shape._inline.graphic.graphicData.pic.blipFill.blip

关系 ID(通常为 r:id,但在本例中为 r:embed)可在以下位置找到:

rId = blip.embed

然后就可以从文档部分得到图片部分

document_part = document.part
image_part = document_part.related_parts[rId]

然后二进制映像可用于在 ._blob 上读写。

如果您写入新的 blob,它将在保存时替换之前的图像。

您可能希望在单个文档中放大到多个图像之前先使用它来处理单个图像并感受一下。

可能会缓存一两个图像特征,因此在保存并重新加载文件之前,您可能无法使所有细节发挥作用,因此请对此保持警惕。

如您所见,不适合胆小的人,但如果您想要它足够糟糕并且可以稍微跟踪一下代码,应该可以工作:)

您还可以使用简单的循环检查段落,并检查哪个 xml 包含图像(例如,如果 xml 包含 "graphicData"),即是图像容器(你可以对运行做同样的事情):

from docx import Document

image_paragraphs = []
doc = Document(path_to_docx)
for par in doc.paragraphs:
    if 'graphicData' in par._p.xml:
        image_paragraphs.append(par)

比起解压 docx 文件,图像位于 "images" 文件夹中,它们的顺序与它们在 image_paragraphs 列表中的顺序相同。在每个段落元素上,您都有许多选项可以更改它。如果你想提取 img 处理它而不是将它插入同一个地方,那么

paragraph.clear()
paragraph.add_run('your description, if needed')
run = paragraph.runs[0]
run.add_picture(path_to_pic, width, height)

所以,我从来没有真正在这里写过任何答案,但我认为这可能是您问题的解决方案。使用这个小代码,您可以在给定所有段落的情况下查看图像的位置。希望对你有帮助。

import docx

doc = docx.Document(filename)

paraGr = []             
index = []

par = doc.paragraphs
for i in range(len(par)):
     paraGr.append(par[i].text)
     if 'graphicData' in par[i]._p.xml:
         index.append(i)

如果您正在使用 Python 3

pip install python-docx

import docx
doc = docx.Document(document_path)
P = []
I = []
par = doc.paragraphs
for i in range(len(par)):
     P.append(par[i].text)
     if 'graphicData' in par[i]._p.xml:
         I.append(i)
print(I)

#returns 索引列表(Image_Reference)