如何提取 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 或你最喜欢的观众。
我想从 "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 或你最喜欢的观众。