Word 转 Markdown 报"保真率 98%",可那张表散了
一份静静躺在目录里的发布说明 .docx,我顺手丢给 tri-docx2md 想转成 Markdown,四道门跑完门D 交的报告说保真率 98.4%、判定却是 C 级强制人工复核。真相反直觉:数字好看不代表能直接用,因为 mammoth 转出来字符都很齐,唯独把那张 4 列的表格拆成了一堆散行文本,Markdown 里连一个 | 都没有。这篇文章记录我用 tri-docx2md 转这份文档的全过程,以及后来换 pandoc 换出一个完全相反的"更差数字、更好结果"的结论。
这份 docx 是什么来头
要转的是一份「智能运维平台操作手册 v3.1」的发布会 .docx,python-docx 建的,里面有二级标题,一张 4 列 3 行的变更明细表格,还有几段正文。文件不大,37KB 出头。tri-docx2md 不是直接叫一个库去转,它是个编排车间:先体检、再选刀、干完活必须交一份账。
门A:预检说这是块"省心的料"
第一步跑 preflight.py:
bash
python scripts/preflight.py --doc release-notes.docx --json
它读文件头 8 个字节做魔数判定:PK\x03\x04 开头就是 OOXML 的 .docx,D0CF11E0 开头才是旧式 .doc。这份是标准的 zip 容器 .docx,没加密,6 个段落、1 张表格、0 张图,直接给 L0 快速档,风险列表是空的。
json
{
"detected_type": "docx",
"encrypted": false,
"paragraph_count": 6,
"table_count": 1,
"image_count": 0,
"grade_suggestion": "L0",
"risks": []
}
有意思的是 encrypted:false 这一项不是摆设------OOXML 文档如果带了 EncryptionInfo,这里会直接 BLOCK,提示你手动解密,绝不碰加密文件。tri-docx2md 在这点很老实,加密就停,不搞破解。
门B:刀库里 mammoth 被封了首选
门B 跑 detect_backends.py,把六个后端在本地探一遍,import 和 CLI 双路探测:
bash
python scripts/detect_backends.py --grade L0 --json
结果有点出乎意料,除了 antiword,其它全都装着:
| 后端 | 档位 | 本地状态 | 许可证 |
|---|---|---|---|
| mammoth | L0 | ✅ import 可用 | BSD-2-Clause |
| markitdown | L0 | ✅ import 可用 | MIT |
| python-docx | L0 | ✅ import 可用 | MIT |
| pandoc | L1 | ✅ CLI 可用 | GPL-2.0 |
| LibreOffice | DOC | ✅ CLI 可用 | MPL-2.0 |
| antiword | DOC | ❌ 未装 | GPL-2.0 |
L0 档首选 mammoth,降级链是 markitdown → python-docx。antiword 那条是给 .doc 旧格式兜底用的,没装暂时不碍事。我心想 mammoth 做 .docx 是出了名的稳,就让它上。
门C:mammoth 转完我心里咯噔一下
按手册里的命令用 mammoth 的 Python API 转:
python
import mammoth
with open("release-notes.docx", "rb") as f:
r = mammoth.convert_to_markdown(f)
open("release-notes.md", "w", encoding="utf-8").write(r.value)
转出来的 Markdown 一打开,标题还在,正文也在,但那张表格没了------它变成了一堆没有 | 分隔的散行:
markdown
模块
变更类型
说明
影响范围
告警中心
新增
风暴收敛聚合规则
告警详情页/通知通道
表格的语义在 Markdown 里是没勾的意思。我压着火没换刀,先跑门D 看它到底怎么判。
门D:保真率 98.4%,判定 C 级
门D 交账:
bash
python scripts/quality_check.py --doc release-notes.docx --md release-notes.md --backend mammoth --grade L0 --json
报告出来了,核心数据看着挺唬人:
| 关键数据 | mammoth(L0) |
|---|---|
| 保真率 | 98.4% |
| 丢失率 | 1.6% |
| 噪声率 | 1.6% |
| 结构对比 | 标题 2/2、表格 0/1、图片 0/0 |
| 置信度 | C(强制人工复核) |
保真率 98.4%,四舍五入就是"丢得很少"。可结构对比那一栏写着表格 0/1------源文档里明明有一张表,Markdown 里却找不到一个表格语法。门D 给的判定原因很直白:"源文档检出表格 1 处而 MD 无表格语法",直接 C 级。
这里我想岔了一点,差点误判:保真率高不等于能直接入库。因为保真率算的是"源文档的可提取文本被 MD 覆盖了多少",mammoth 把表格细胞里的文字都提出来了,字符一个没少,所以召回率很高;可它把表格的结构弄丢了,这在 Markdown 里等于把表拆平了。对要当知识库入库的文档来说,散行的表格比丢几个字严重得多------检索、引用都废了。
换 pandoc,数字变差结果反而更好
C 级除非用户点头,否则按管道要沿降级链重转。L0 的链是 markitdown/python-docx,基本是同类货,不如直接上 L1 的 pandoc:
bash
pandoc release-notes.docx -t gfm --wrap=none -o release-notes-pandoc.md
pandoc 输出里那表格回来了,成了规范的 GFM 语法,| 和分隔线一个不缺:
markdown
| 模块 | 变更类型 | 说明 | 影响范围 |
|---
|---
|---
|---
|
| 告警中心 | 新增 | 风暴收敛聚合规则 | 告警详情页/通知通道 |
| CMDB | 优化 | 查询接口二级缓存 | 资产列表/拓扑页 |
再跑一遍门D,结果让我愣住了:
| 关键数据 | mammoth(L0) | pandoc(L1) |
|---|---|---|
| 保真率 | 98.4% | 89.6% |
| 丢失率 | 1.6% | 10.4% |
| 噪声率 | 1.6% | 1.7% |
| 结构对比 | 表格 0/1 | 表格 1/1 |
| 置信度 | C | B(抽查复核) |
pandoc 的保真率反而"暴跌"到 89.6%,比 mammoth 低了快九个百分点。可它的表格在结构对比里是 1/1,全齐。门D 判成 B 级,原因是保真率落在 85--95% 区间,需要抽查复核,但结构上表格保住了。
我盯着这两组数想了半天,才想明白 tri-docx2md 这套分级的设计意图:结构对比是硬指标,保真率是软指标。 保真率的"低"很多是文字层面的假象------pandoc 输出 GFM 表格要占用 |、空格、分隔线这些符号,这些不是源文档里的"可见文字",bigram 一比就跟源文本对不上,召回率就掉下来了。但去掉 Markdown 语法符号后,真正的文字一个没丢,表格还整整齐齐。mammoth 那边字符都"召回"了,结构却平了,属于高召回、低可用。
所以那个"保真率 98.4% 却是 C 级"的怪象,本质是:结构丢失比文字丢失严重得多,而保真率这个单一数字根本看不出结构。要信,得看结构对比和置信度,不能只看最大那个百分比。

踩完这趟,我认了几条理
- 保真率高≠能用:mammoth 把文字都"召回"了但表格散架,照样 C 级。入库的文档,结构完整比字符齐全重要。
- 置信度分级是"结构优先":结构对比不吻合直接压到 C,哪怕保真率 98%。这是 tri-docx2md 最值钱的设计。
- 带表格的文档直接上 L1:L0 快速档的 mammoth 对这种小表就翻车了,复杂表格更悬。与其 C 级再降级,不如一开始就 pandoc。
- 数字要分开看:保真率、丢失率、噪声率、结构对比各回答一个问题,混在一起看会得出"98% 很稳"的错误结论。
顺带一提,我在做"雷达鸭"的案例库时,也常有人直接把 Word 导出的内容当知识源丢进来。用这套保真口径至少能一眼分清哪些文档是"文字齐但结构废",哪些是真的能入库------省去不少返工。
收尾
Word 转 Markdown 真正难的不是调用哪个库,而是知道自己丢了什么结构。mammoth 和 pandoc 都是好库,差别在于谁把表格当结构、谁只当文字。tri-docx2md 这个"质检车间"的价值,就是把这件事摊成了四个能对照的数字------而这次我最该记住的,是别被 98.4% 那张好看的脸骗了。
我是老三,10+ 年软件开发经验,软件设计师、人工智能应用工程师,专注鸿蒙应用开发(ArkTS)北向开发与 Web 前端,探索 AI 自动化,不定期在 CSDN 分享鸿蒙 / AI 方向技术文章。
本文遵循 MIT 协议,转载请注明出处。
这个系列的文章都来自开源的 tri 技能库。整套 tri-xxx 技能都能在 skillhub 找到并安装,一条命令装完即用,比如本文用到的 tri-docx2md:skillhub install tri-docx2md。装完每个技能都有 README,想摸清它到底能干嘛,读那个就够了。