Files
mdpolish/README.md
T
Bepr4 c19e9fcebf govdoc-md-cleaner v0.1.0: 政务文档 Markdown 清洗工具(规则引擎 + CLI + 测试)
- 8 条 YAML 声明规则:页码/页眉页脚/目录点线/图片/HTML表格/散落标签/行尾空白/空行
- 防误伤设计:protect 正则 + 内容形态豁免 + OCR burst 检测
- md-clean single/batch CLI,JSON 清洗报告
- 18 个单元测试

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-20 17:04:10 +08:00

94 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 行)。
## 安装
```bash
pip install -e . # 或直接 python -m cleaner.cli(仅需 PyYAML
```
## 使用
```bash
# 单文件:清洗 + 打印统计
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 diff`report.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 收紧。
## 测试
```bash
python -m unittest discover tests -v
```
## License
MIT