【问题标题】:Extract image position from .docx file using python-docx使用 python-docx 从 .docx 文件中提取图像位置
【发布时间】:2016-12-17 15:28:48
【问题描述】:

我正在尝试使用 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 为我获取了以厘米为单位的高度。我的主要要求是了解图像在文档中的位置,因为我需要提取图像并对其进行一些处理,然后再次将图像放回同一位置

【问题讨论】:

  • 您可以使用支持完整 MS Word 对象模型的 win32com 轻松完成此操作。 python-docx 库似乎特别有限,在使用或访问 Shape 对象时更是如此。此外,InlineShapes 序列支持索引访问 (read the dox),因此虽然s 没有index 属性,但您可以将它们视为索引序列。
  • @DavidZemens 您能否详细说明索引序列的概念?
  • 这意味着inline_shapes序列是有序的并且可以通过索引例如doc.inline_shapes[0]等来访问,不是吗? docs.python.org/3/tutorial/…
  • 好的。我得到它。但我最初的问题是不同的。假设.docx 文件的内容是:这是一个示例文档。图像位于此语句之前。 所以我需要的是 存在的索引或位置,在这种情况下,它在 document 之后和 .the image
  • 查看该库的 dox,似乎不受支持。使用 win32com 使用所有 Word 对象模型方法/属性来实例化 word 文档,内联形状应该有一个 .range(或 .Range,不确定大小写)属性来识别 字符 在文档中的位置。

标签: python python-docx


【解决方案1】:

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,它会在保存时替换之前的图像。

您可能希望让它与单个图像一起工作,并在放大到单个文档中的多个图像之前先感受一下。

可能会缓存一两个图像特征,因此在保存并重新加载文件之前,您可能无法获得所有细节,因此请注意这一点。

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

【讨论】:

    【解决方案2】:

    您还可以使用简单的循环检查段落,并检查哪个 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)
    

    【讨论】:

    • 为我工作,谢谢。但是,您必须计算段落内标签 graphicData 的出现次数,因为可能不止一个(如果使用 string.count(),由于打开和关闭标签,您必须将结果减半)。
    • 我解压了 docx,图像有扩展名:.png.jpg.htm.htm 实际上是用于 PNG 图像)。知道如何使用扩展名获取名称吗? (没有像these answers那样使用模块os?)
    【解决方案3】:

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

    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)
    

    【讨论】:

      【解决方案4】:

      如果您使用的是 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)

      【讨论】:

        猜你喜欢
        • 2014-10-03
        • 1970-01-01
        • 2020-05-28
        • 1970-01-01
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多