如何提取 python-docx 中插入的带有跟踪更改的文本

How to extract text inserted with track-changes in python-docx

我想从 "Track Changes" 模式下编辑的 word 文档中提取文本。我想提取插入的文本并忽略删除的文本。

运行 下面的代码我看到段落以 "track changes" 模式插入 return 一个空的 Paragraph.text

import docx

doc = docx.Document('C:\test track changes.docx')

for para in doc.paragraphs:
    print(para)
    print(para.text)

有没有办法检索修订后的插入内容(w:ins 元素)中的文本?

我正在使用 python-docx 0.8.6、lxml 3.4.0、python 3.4、Win7

谢谢

不直接使用python-docx;还没有 API 支持跟踪 changes/revisions。

这是一项非常棘手的工作,如果您搜索元素名称(也许 'open xml w:ins' 作为开始),您会发现它是第一个结果: https://msdn.microsoft.com/en-us/library/ee836138(v=office.12).aspx

如果我需要在紧要关头做类似的事情,我会使用以下方法获取 body 元素:

body = document._body._body

然后在上面使用 XPath 来 return 我想要的元素,有点像这个 aircode:

from docx.text.paragraph import Paragraph

inserted_ps = body.xpath('./w:ins//w:p')
for p in inserted_ps:
    paragraph = Paragraph(p, None)
    print(paragraph.text)

您将自己找出什么 XPath 表达式可以获得您想要的段落。

opc-diag可能是这方面的朋友,让你快速扫描.docx包的XML。 http://opc-diag.readthedocs.io/en/latest/index.html

来自 Etienne 的以下代码对我有用,它直接与文档的 xml 一起工作(而不是使用 python-docx)

http://etienned.github.io/posts/extract-text-from-word-docx-simply/

多年来我一直遇到同样的问题(也许只要这个问题存在)。

通过查看@yiftah 发布的 "etienned" 代码和 Paragraph 的属性,我找到了接受更改后检索文本的解决方案。

诀窍是让 p._p.xml 获取段落的 XML,然后在其上使用 "etienned" 代码(即从中检索所有 <w:t> 元素XML 代码,其中包含常规运行和 <w:ins> 块)。

希望它能帮助像我一样迷失的灵魂:

from docx import Document

try:
    from xml.etree.cElementTree import XML
except ImportError:
    from xml.etree.ElementTree import XML


WORD_NAMESPACE = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
TEXT = WORD_NAMESPACE + "t"


def get_accepted_text(p):
    """Return text of a paragraph after accepting all changes"""
    xml = p._p.xml
    if "w:del" in xml or "w:ins" in xml:
        tree = XML(xml)
        runs = (node.text for node in tree.getiterator(TEXT) if node.text)
        return "".join(runs)
    else:
        return p.text


doc = Document("Hello.docx")

for p in doc.paragraphs:
    print(p.text)
    print("---")
    print(get_accepted_text(p))
    print("=========")

我需要一个快速的解决方案,使被“智能标签”包围的文本对 docx 的文本可见 属性,我发现该解决方案也可以调整为使某些跟踪的更改可见。

它使用lxml.etree.strip_tags去除周围的“smartTag”和“ins”标签,并推广内容;和 lxml.etree.strip_elements 删除整个“del”元素。

def para2text(p, quiet=False):
    if not quiet:
        unsafeText = p.text
    lxml.etree.strip_tags(p._p, "{*}smartTag")
    lxml.etree.strip_elements(p._p, "{*}del")
    lxml.etree.strip_tags(p._p, "{*}ins")
    safeText = p.text
    if not quiet:
        if safeText != unsafeText:
            print()
            print('para2text: unsafe:')
            print(unsafeText)
            print('para2text: safe:')
            print(safeText)
            print()
    return safeText

docin = docx.Document(filePath)
for para in docin.paragraphs:
    text = para2text(para)

请注意,这仅适用于“跟踪更改”的子集,但它可能是更通用解决方案的基础。

如果您想直接查看 docx 文件的 xml:将其重命名为 .zip,提取“document.xml”,然后通过放入 chrome 或你最喜欢的观众。