3.2 KiB
3.2 KiB
tmkit 后端管线 · 进展报告(管线组)
日期:2026-11-03 状态:✅ 最小可用版交付,pytest 12/12 全绿
做了什么
在 金唐智法/tm/tmkit/ 交付 Python 库 tmkit(纯库,不含 Web),四大核心模块 + 测试 + 文档:
| 模块 | 内容 |
|---|---|
splitter.py |
PDF 分流:get_text 检测文字层,逐页返回 native / scanned(阈值可调) |
extractor.py |
原生页按词抽取 bbox(get_text('words'));扫描页 raise NotImplementedError('OCR 待接入 PaddleOCR') |
detector.py |
PII 识别引擎:身份证 18 位(GB 11643 校验位验证)、大陆手机号、银行卡(Luhn 校验)、统一社会信用代码(GB 32100 校验)、邮箱;输出 [{type, text, page, bbox}],支持 register() 自定义规则 |
redactor.py |
坐标回写:两种方案都实现了——add_redact_annot + apply_redactions(默认,真删文字,测试验证 PII 从文本层消失、黑块像素可见)和 draw_rect 黑条(对比保留);输出脱敏后 PDF bytes |
tests/ |
reportlab 动态生成 3 个样例 PDF(纯中文文本页 / 身份证+手机号+银行卡+邮箱页 / 空白扫描页,中文字体用 STSong-Light CID),12 个用例全链路验证 |
README.md |
模块说明 + 代码示例 + 已知限制 |
测试结果(python3 -m pytest,12 passed)
- 全链路断言:脱敏后 PDF 用
get_text验证——身份证/手机号/银行卡/邮箱原文不存在、非敏感文本("张三""脱敏"等)保留、页数不变、bbox 区域像素为纯黑 - 校验算法单测:身份证校验位、Luhn 各有正反例
- 零误报:无 PII 的普通文本页检测结果为空
- 自定义规则:注册"案号"正则规则后命中正常
- 扫描页:正确抛
NotImplementedError(OCR 接口预留)
覆盖 PII 类型(5 类):身份证、手机号、银行卡、统一社会信用代码、邮箱
开发中解决的坑(经验沉淀)
- reportlab 默认字体 Helvetica 画中文全部变 "IIII",需注册
UnicodeCIDFont("STSong-Light") - Python 正则
\b在"中文紧贴数字"(如身份证号110101...)处不成立(中文和数字都是 Unicode\w),已改用 ASCII-only lookaround 边界 - 回写方案选择:
apply_redactions删字最干净(文本层彻底无 PII),定为默认;draw_rect黑条仅视觉遮挡、文字仍可复制提取,仅留作对比
已知限制 → 下一步
| 项 | 说明 | 计划 |
|---|---|---|
| OCR 未接入 | 扫描页直接抛 NotImplementedError | 接入 PaddleOCR,补齐扫描页链路(最高优先级) |
| 跨行 PII | 身份证分两行排版时不命中(行内拼接策略) | 行间相邻性合并 |
| 中文姓名/地址 | 属于 NER 范畴,正则不适用 | 待接入 NER 模型(第二优先级) |
| 旋转页/加密 PDF | 未处理 | 视真实样本需求补 |
draw 模式 |
不删字,仅演示用 | 文档已标注风险 |
环境备忘
python3(系统 3.9)+ pymupdf 1.26.5 / reportlab 5.0.0 / pytest 8.4.2(pip --user)- 复跑:
cd 金唐智法/tm && python3 -m pytest tmkit/tests/ -v