# tmkit — PDF 数据脱敏工具库(后端管线 · 最小可用版) 面向法律/金融文书 PDF 的 PII(个人敏感信息)自动脱敏。纯 Python 库,六大模块中的 4 个核心模块 + 测试 + 文档已交付。 ## 模块 | 模块 | 功能 | |---|---| | `tmkit.splitter` | PDF 分流:`get_text` 检测文字层,逐页返回 `native` / `scanned` | | `tmkit.extractor` | 原生页按词抽取(`get_text('words')`,含 bbox 坐标);扫描页 `raise NotImplementedError('OCR 待接入 PaddleOCR')` | | `tmkit.detector` | PII 识别引擎:身份证 18 位(GB 11643 校验位)、大陆手机号、银行卡(Luhn)、统一社会信用代码(GB 32100)、邮箱;支持自定义规则注册 | | `tmkit.redactor` | 坐标回写:`add_redact_annot` + `apply_redactions`(默认,删字最干净)或 `draw_rect` 黑条;输出脱敏后 PDF bytes | ## 用法示例 ```python import fitz from tmkit import default_detector, extract_page_words, redact_pdf pdf_bytes = open("input.pdf", "rb").read() det = default_detector() hits = [] with fitz.open(stream=pdf_bytes, filetype="pdf") as doc: for pno, page in enumerate(doc): hits += det.scan_page_words(extract_page_words(page), pno) # hits: [{"type": "id_card", "text": "1101...", "page": 0, "bbox": (x0,y0,x1,y1)}, ...] clean = redact_pdf(pdf_bytes, hits) # method="redact"(默认,真删除) open("output.pdf", "wb").write(clean) ``` 自定义规则: ```python from tmkit import PIIDetector, Rule import re det = PIIDetector() det.register(Rule("order_no", re.compile(r"(\d{4})京\d+民初\d+号"))) ``` ## 测试 ``` cd tmkit && python3 -m pytest tests/ -v ``` 样例 PDF 由 reportlab 在 conftest.py 中动态生成:纯文本页、身份证+手机号+银行卡+邮箱页、空白扫描页。断言覆盖:脱敏后 `get_text` 中 PII 不存在、非敏感文本保留、页数不变、黑块像素可见、校验算法正确性、无 PII 页零误报。 ## 已知限制(下一步) - 扫描页 OCR(PaddleOCR)尚未接入,`extractor` 直接抛 `NotImplementedError` - PII 跨行换行(如身份证分两行)不会命中;词拼接按行内进行 - `method="draw"` 只画黑条不删字,文本层仍可提取,仅作对比保留 - 未处理旋转页 / 加密 PDF