govdoc-md-cleaner

政务文档(招标 / 投标 / 采购 / 合同)PDF→Markdown 产物的规则化清洗工具。

上游解析管线(MinerU / OCR)把 PDF 转成 Markdown 后,会带入大量非正文噪音: 逐页重复的页眉页脚、页码行、目录点线、死链图片引用、压成单行的 HTML 表格、 行尾硬换行双空格,以及 OCR 重复崩坏段。本工具用一套 YAML 声明、按序应用、 逐条统计 的规则把它们清掉,输出可直接进入比对 / RAG / 审核管线的干净 Markdown。

数据来源

清洗目标为 /home/lihaoze/gov_test_data(律所上传的真实政务文件的筛选子集, 详见其 compare/readme.md),未来会持续接入更多批次的 Markdown 文件。 本项目只包含清洗代码与规则,不包含任何业务数据——测试数据不入库。

清洗规则(rules/default.yaml

顺序 规则 处理对象 示例
10 strip_page_lines 页码行 第 3 页 共 53 页第4页共4页Page 3 of 10- 4 -
20 strip_repeated_short_lines 页眉页脚 + OCR 崩坏 全篇重复 ≥3 次的短行;连续刷屏 ≥5 次(实测"审计程序"×1359
30 strip_toc_dots 目录点线 第一章 投标邀请函 ………… 2 → 保留标题,删点线页码
40 drop_images 死链图片 ![](images/xxx.jpg)、base64 内嵌图
50 normalize_tables HTML 表格 <table><tr><td>… 单行压缩 → Markdown 管道表格
60 strip_stray_html 散落标签 <br/>
70 rstrip_lines 行尾空白 MinerU 每行行尾的双空格硬换行
80 collapse_blank_lines 空行折叠 连续空行 → 1 行;裁掉文首文末

防误伤设计(来自真实数据踩坑)

  • protect 正则投标人:(公章)法定代表人签名:日期: 年 月 日致:xxx、声明函结尾句——标书里逐章重复,是正文模板不是页眉,默认保护。
  • 内容形态豁免:编号条款 1)…1、…一、…、列表/表格行、 乙方:xxx 字段行——平行结构天然重复,引擎侧直接不参与页眉判定。
  • burst 检测:同一短行连续刷屏 ≥5 次(间隔 ≤2 行)判为 OCR 重复崩坏, 直接删除(003-10 案例出现"审计程序"连续 1359 行)。

安装

pip install -e .   # 或直接 python -m cleaner.cli(仅需 PyYAML

使用

# 单文件:清洗 + 打印统计
md-clean single input.md -o output.md --diff

# 批量:递归清洗目录下所有 .md,输出到平行目录 + JSON 报告
md-clean batch /path/to/uploads -o /path/to/uploads_cleaned \
    --pattern "*.md" --report report.json

# 用自定义规则集(复制 default.yaml 改参数即可)
md-clean batch uploads/ --rules rules/strict.yaml

--diff 输出 unified diffreport.json 记录每个文件每条规则的命中数, 清洗过程完全可审计、可回滚(重跑即得原结果的对照)。

项目结构

govdoc-md-cleaner/
├── cleaner/
│   ├── cleaner.py     # 引擎:按序应用规则,输出 CleanResult(text, stats)
│   ├── rules.py       # 规则实现 + REGISTRY + YAML 加载
│   └── cli.py         # single / batch 两个子命令
├── rules/
│   └── default.yaml   # 默认规则集(顺序、开关、参数、protect 列表)
├── tests/
│   └── test_rules.py  # 每条规则的最小样例 + 防误伤回归
└── docs/
    └── RULES.md       # 规则编写指南(新增规则的方法)

新增一条规则

  1. cleaner/rules.py:实现 _your_rule(text, params, stats) -> text,注册进 REGISTRY
  2. rules/default.yaml:追加 - name: your_rule / order: / params:
  3. tests/test_rules.py:加一个真实数据浓缩出的最小样例。

原则:规则只删噪音不删正文;拿不准的形态默认保留,靠 protect/exempt 收紧。

测试

python -m unittest discover tests -v

License

MIT

S
Description
No description provided
Readme 802 KiB
Languages
Python 86.9%
TypeScript 10.5%
CSS 2.1%
JavaScript 0.3%
HTML 0.2%