阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。
这篇先解决哪一个问题
图片所在段落的文字只是上下文候选,不是已经证明的图注。内联与浮动图应分开盘点;w:drawing 和 wp:inline 属于不同命名空间,错误的查询会静默漏掉图片。
自包含的合成示例
依赖见导入列表。代码在内存中构造输入;运行记录单独提供,不代表对所有真实文件的保证。
from io import BytesIO
from PIL import Image
from docx import Document
doc = Document()
picture = BytesIO()
Image.new("RGB", (10, 10), "red").save(picture, format="PNG")
picture.seek(0)
paragraph = doc.add_paragraph("Candidate context, not verified caption")
paragraph.add_run().add_picture(picture)
doc.add_paragraph("Unrelated paragraph")
records = []
for index, p in enumerate(doc.paragraphs):
inline = p._p.xpath(".//wp:inline")
floating = p._p.xpath(".//wp:anchor")
if inline or floating:
records.append({"paragraph": index, "inline_count": len(inline),
"floating_count": len(floating), "context_candidate": p.text})
assert len(records) == 1
assert records[0]["inline_count"] == 1
assert records[0]["floating_count"] == 0
assert records[0]["context_candidate"] == "Candidate context, not verified caption"
为什么你的图片说明文字总是对不上号
在处理包含大量技术插图的Word文档时,最令工程师头疼的故障并非图片丢失,而是“图文分离”。当你用脚本提取段落文本时,发现第5段的标题和第6段的图片在逻辑上是一体的,但在XML结构里它们可能相隔甚远;或者更糟糕的是,提取器自信地返回了“图3:系统架构”,但对应的图片其实是一个浮动对象(Floating Shape),而你的解析器只支持内联形状(Inline Shape),导致你误以为已经处理了该图,实际上却遗漏了关键视觉信息。这种“静默失败”比直接报错更具破坏性。
解决这个问题的核心在于理解Word的双层模型:文本层与绘图层。只有当图片作为“内联形状”嵌入文本层时,它才像一个巨大的字符一样拥有确定的段落归属和前后文顺序。而浮动图片位于独立的绘图层,其位置由绝对坐标或锚点决定,与文本流的物理相邻并不代表逻辑绑定。在编写自动化程序前,必须先确认目标图片的嵌入类型,再决定是否信任当前的段落索引关系。
内联形状与浮动对象的本质差异
python-docx
库目前仅完整支持内联图片(Inline Pictures)的读写操作。根据官方文档,内联形状被视为一个字形(Glyph),它会撑开行高,并随文本流动而移动。这意味着如果我们在代码中遍历
paragraph.runs
,能够稳定地捕获到内联图片对象,且该Run在列表中的索引直接反映了它在句子中的位置。
相比之下,浮动形状虽然在视觉上可能与某段文字紧密相邻,但在DOM树中它们通常挂载在段落之外的容器或特定的锚点属性下。如果你正在构建一个文档翻译或内容抽取管道,必须明确声明:“本脚本仅处理内联图片”。对于浮动图片,不应尝试通过启发式规则(如“距离最近”)来强行匹配说明文字,因为Word的排版引擎允许文字环绕浮动图,这种空间关系在纯文本解析视角下是完全不可靠的。正确的做法是记录浮动图的存在并抛出警告,而不是生成错误的关联数据。
合成示例:正确绑定与边界检测
为了演示如何安全地提取图文关系,我们构造一个合成场景。假设输入文档包含两种情况:一是标准的“标题+内联图+说明”结构;二是包含浮动图的干扰项。
预期正确输出
:程序应准确识别出内联图所在的段落,提取出紧邻的说明文字,并返回结构化数据。对于浮动图,程序应明确标记为“不支持/跳过”,而不是将其错误地归类为已处理的内联图。
错误/边界输入处理
:若用户传入一个仅含浮动图的文档,或者图片被包裹在复杂的嵌套表格、文本框中,脚本不应崩溃,也不应返回空字符串假装成功。它应当返回一个包含状态码的结果对象,明确指出“检测到非内联图形对象,需人工审查”。这种显式的“不处理”比隐式的“错误处理”更有价值。
以下代码展示了这一防御性编程思路。请注意,此示例为教学演示,未实际运行;
input.docx
需读者自行准备:新建Word文档,插入一张“嵌入型”图片并添加题注,另插入一张“四周型环绕”浮动图,保存为
input.docx
置于脚本同目录。
上述代码并未使用高级封装,而是直接查询XML命名空间。这是因为
python-docx
的高层API对浮动图的抽象有限,直接检查
w:drawing
下的
wp:inline
与
wp:anchor
标签是区分两者最可靠的手段。注意,代码中的命名空间URI是固定的OOXML标准,不随库版本变化。
验收标准与人工审查边界
在将此类脚本集成到生产环境前,必须建立清晰的验收矩阵。不要迷信“自动化率”,而要关注“错误可见性”。下表列出了实际工程中常见的观察点与处理决策:
观察现象
技术归因
自动化处理决定
人工审查触发条件
图片与说明文字在同一Run内
罕见格式错误或非标准生成器
按文本分割,标记置信度低
所有此类案例均需复核
段落含
wp:anchor
标签
浮动图/文字环绕
记录位置,返回
skipped
状态
当文档浮动图占比>10%时
图片在表格单元格内
嵌套结构
正常提取,但保留单元格坐标
表格跨页或合并单元格时
连续多个内联图无间隔文本
拼图或步骤截图
视为一组,合并说明文字
图片数量>3且无序号时
提取文本为空但有图片占位符
样式隐藏或OCR缺失
保留占位符标记
关键技术文档的关键图示
不适用范围声明
:本方案仅适用于以正文叙述为主的技术文档。对于海报、宣传册、复杂排版的杂志版式,由于大量使用文本框链接和绝对定位,段落遍历法完全失效。此外,代码演示仅验证了XML结构的识别能力,不代表端到端的翻译或转换效果。在实际业务中,还需考虑图片本身的分辨率、色彩模式以及说明文字的语言检测等正交问题。
参考资料与下一步
python-docx: Understanding pictures and other shapes
建议读者立即在自己的语料库中运行一次浮动图检测脚本,统计非内联图形的比例。若比例显著,应优先调整解析策略或与翻译服务方确认支持范围,而非盲目推进全自动化流程。
将这份检查清单用于文档翻译
Word 翻译容易把内容问题与格式问题混在一起。把样式、页眉和表格等检查项留到交付清单里,让审校知道该在哪里检查。
OmniDoc(产品入口)
提供多格式文档翻译入口,官网介绍了 OCR、术语表与双语对照功能。对希望直接从文件开始处理的团队,这是一条值得用实际样本评估的路径。请使用有权上传的脱敏文件,并用本篇的检查项复核结果;这里不声称 OmniDoc 使用了本文的开源库或内部算法,也不以示例代替产品性能测试。
- 1 -
更新于 2026-10-09