犀牛鸟 2026 研究笔记 estelledc.github.io

Ch28: Python docreader——解析边界、单测与竞赛最快路径

Part 8 · 前置:Ch27 分块 · 后续:Ch29 docparser 案例:case-1785 · case-1743

结论先行docreader/格式脏活层——Excel IMAGE、PDF OCR、MHTML 内嵌图。竞赛 Python 路径 = parser 改动 + pytest,通常 1–3 天可合入。设计原则:噪声在 parse 最早阶段过滤,不要指望 Rerank 兜底(GIGO)。


一、日常类比

docreader 像进厂质检:Excel/PDF 是不同供应商的包装箱。有的在箱里塞了「占位符纸条」(DISPIMG),有的把图片贴在外面但说明书写「见上图」。质检必须在 开箱时 扔掉纸条;若纸条进了流水线(chunk → 向量),后面仓库管理员(Rerank)无法区分「真知识」和「印刷垃圾」。


二、目录职能地图

docreader/
├── parser/           # excel_parser, pdf_parser, mhtml, ...
├── tests/            # 边界用例 — 大师 PR 必带
└── api/              # gRPC/HTTP,Go 侧 consumer
格式 典型坑 案例
Excel WPS DISPIMG 文本进 cell.value #1785
MHTML 图片分辨率/链接在 Py→Go 丢失 #1743
扫描 PDF OCR 5–15% 错字 → BM25 miss 通用
双栏 PDF 阅读顺序左右栏交叉 Ch39

三、大师四步法(来自 case-1785)

  1. 复现 — 最小 fixture(xlsx/mhtml 单文件进 tests/fixtures/
  2. 根因 — 追踪 parse_into_text() 哪一步把噪声当文本
  3. 最早过滤 — 正则/规则在写入结果 之前
  4. 参数化单测 — 每个变体一行
import re
import pytest

IMAGE_FN = re.compile(r'^=?(?:_xlfn\.)?DISPIMG\s*\(', re.I)

@pytest.mark.parametrize("cell_value", [
    'DISPIMG("ID_x",1)',
    '=_xlfn.DISPIMG("ID_x",1)',
    '正常文本',
])
def test_image_function_filtered(cell_value):
    if IMAGE_FN.match(cell_value.strip()):
        assert extract_text(cell_value) == ""
    else:
        assert "正常" in extract_text(cell_value)

四、与 Go 的边界契约

docreader 输出 纯文本或 Markdown 字符串 → Go docparser 不再猜测 Excel 语义。

应留在 Python 应交给 Go
格式检测、OCR、IMAGE 过滤 HTML→MD 归一化、chunk 边界
二进制解析 与 chunker 的格式 invariant

Noise 不过界:Python 漏检的 HTML 表,Go 仍可部分修复(#1725);但 DISPIMG 字符串一旦写入,下游无法自动识别为噪声。


五、grep 与本地调试

cd WeKnora
rg -n "parse_into_text|ExcelParser" docreader/
pytest docreader/tests/test_excel_parser.py -q
# MHTML: rg -n "mhtml|MHTML" docreader/

Docker 全栈时改 Python 后 重建 docreader 镜像 或挂载 volume,否则 Go 仍调旧服务。


六、动手清单


章末自检


延伸阅读