python-docx提取Docx时丢失Delaware,求无需手动改文件的解决代码
解决python-docx无法提取文档中特定文本(如"Delaware")的问题
我之前也碰到过一模一样的情况——python-docx的paragraph.text会漏掉某些特殊格式的文本,原因正如你提到的相关内容所说:这个"Delaware"并不是普通的段落文本,而是被放在了内容控件、隐藏域或者其他特殊XML节点里,python-docx的上层API默认不会遍历这些节点来拼接文本。
下面是几个无需手动修改文档就能提取到该文本的解决方案,完全支持批量处理你的数千份文件:
方法1:直接从文档XML提取所有文本
docx本质是一个ZIP包,所有内容都存在word/document.xml里,我们可以直接解析这个XML的所有文本节点,绕过上层API的限制:
import docx import io import requests from lxml import etree url = 'https://github.com/python-openxml/python-docx/files/1996979/Delaware_Test.docx' file = io.BytesIO(requests.get(url).content) # 加载文档并获取XML根节点 doc = docx.Document(file) root = doc._element.body # 提取所有文本节点内容 full_text = ''.join(root.xpath('//text()')) print(full_text)
这个方法会把文档里所有可见的文本都提取出来,不管它被放在什么格式容器里。
方法2:遍历段落的所有Run元素
有时候遗漏的文本会被放在单独的Run里,而paragraph.text可能因为Run的特殊属性(比如关联控件、隐藏格式标记)没有把它拼接进去,我们可以手动遍历每个段落的所有Run:
import docx import io import requests url = 'https://github.com/python-openxml/python-docx/files/1996979/Delaware_Test.docx' file = io.BytesIO(requests.get(url).content) doc = docx.Document(file) full_text = [] for para in doc.paragraphs: # 遍历段落里的每一个Run for run in para.runs: if run.text: # 避免加入空文本 full_text.append(run.text) print(''.join(full_text))
方法3:专门处理内容控件(Content Control)
如果你的批量文档里大量使用内容控件来放置这类文本,可以针对性地提取内容控件内的文本:
import docx import io import requests url = 'https://github.com/python-openxml/python-docx/files/1996979/Delaware_Test.docx' file = io.BytesIO(requests.get(url).content) doc = docx.Document(file) root = doc._element.body # 提取普通文本 + 内容控件内的文本 text_segments = root.xpath('//text() | //w:sdt//w:t/text()') full_text = ''.join(text_segments) print(full_text)
内容的提问来源于stack exchange,提问作者dshefman




