第三章 材料进来:识别、脱敏、命名、索引
先说结论
尽调最耗时间的不是法律分析,是把一屋子材料变成能查的东西。这一章讲四个动作,每一个都能省下几十小时,也都能埋下大坑。
一、扫描件识别:选错引擎,后面全是错的
现实情况
企业提供的材料,大量是扫描件:营业执照复印件、合同扫描、判决书 PDF、盖章文件拍照。这些文件没有文字层,直接搜索搜不到,直接给 AI 看不了。
一本 651 页的扫描版专业书,用工具打开,get_text() 返回空字符串——一个字都没有。
引擎实测
同一页、同一 300dpi、同一台机器,两种引擎的结果:
| 项目 | Tesseract(chi_sim) | RapidOCR(PP-OCR ONNX) |
|---|---|---|
| 汉字间距 | 每个字之间插空格:「法 律 尽职 调查 指引」 | 正常连排 |
| 标点 | 全角转半角,句号变逗号 | 全角标点正确 |
| 错字 | 「瑕疵」→「瑕首」「瑕狂」;「应予」→「子」;「出让」→「出证」 | 基本正确 |
| 表格 | 丢失表头结构 | 能读出「文件名/具体条款规定/法律问题」 |
| 速度 | 5.0 秒/页 | 6.2 秒/页(部分页更快) |
结论:中文法律文本一律用 RapidOCR。 Tesseract 只在纯英文或版面极简时用。
为什么差这么多:Tesseract 的 chi_sim 模型训练语料以通用文本为主,对中文排版的字间距处理有缺陷;PP-OCR 是专门针对中文场景训练的,检测阶段就会把整行作为一个文本块处理。
落地做法
import fitz
from rapidocr_onnxruntime import RapidOCR
engine = RapidOCR()
doc = fitz.open("材料.pdf")
for i in range(doc.page_count):
pix = doc[i].get_pixmap(dpi=300) # 300dpi 是准确率与速度的平衡点
pix.save("_tmp.png")
res, _ = engine("_tmp.png")
text = "\n".join(x[1] for x in res) if res else ""
open("ocr/p%03d.txt" % (i + 1), "w", encoding="utf-8").write(text)
三个参数要点:
- dpi 用 300。低于 200 小字识别率明显下降;高于 400 速度翻倍但准确率提升有限。
- 逐页落盘,不要一次跑完再写。中断后可以跳过已存在的文件续跑。
- 保留页码。后续引用证据要能回到“第几页”。
识别之后必须做的事
OCR 结果不能直接当证据。三件事必须人工回原件:
- 关键条款的数字(金额、比例、期限)
- 签章是否存在、是否清晰
- 附件是否齐全(OCR 只识别有字的页,空白页和图片页会漏)
二、脱敏:一键本地跑完,不出网
为什么必须脱敏
客户材料进入任何云端模型之前,必须先脱敏。这不是谨慎,是执业义务——律师对委托人信息负有保密义务,把未脱敏材料发给第三方 AI 服务,等于把客户信息交给了不受控的第三方。
一条命令
本机工具 mask(本地运行,不联网):
# 第一步:PDF 转文本(有文字层直接抽,扫描页自动 OCR)
mask pdf2txt -i "材料.pdf" -o "工作/text"
# 第二步:脱敏(reversible 模式,生成代号 + 映射表)
mask redact -i "工作/text" -o "工作/masked" --mode reversible
# 第三步:自检残留(送外部模型前必跑)
mask check "工作/masked"
# 第四步:拿到模型返回稿后回填
mask restore -m "工作/masked/mapping.json" -i "模型返回.md" -o "成品.md"
三种模式怎么选
| 模式 | 用途 | 特点 |
|---|---|---|
reversible | 送 AI 处理,之后要还原 | 生成 [[CO-001]] 这类代号 + 映射表 |
production | 交法院、给对方、给客户 | 保留主体名、案号、金额;掩掉证件号、手机号、账号、车牌 |
irreversible | 发布、入库、做素材 | 代号不可逆,无法还原 |
最常犯的错:拿 reversible 的稿子去发布。代号一旦发出去,映射表在你手上也没用了——读者看到的是一堆 [[CO-001]]。
首次使用:先跑 dry-run
陌生当事人、陌生行业术语,第一次先看命中报告:
mask redact -i "工作/text" --dry-run --report "命中.json"
看什么:
- 公司名、人名、金额的命中数量对不对
- 有没有把普通词误判成人名(“王先生”里的“王”)
- 有没有漏掉的简称、代称
确认后把这些补进词典,再正式跑。
脱敏之后的自检
mask check 会扫残留。但自检通过不等于安全——它只能查它认识的模式。两类东西要人工再看一遍:
- 行业特有表述(“我们那个华东最大的 XX 项目”)
- 能反推到具体主体的组合信息(成立时间 + 注册地 + 主营业务 + 法定代表人姓氏)
三、命名:一条规则省下三天
材料收进来,第一件事是统一命名,不是急着看内容。
推荐规则:
<序号>_<材料类别>_<主体简称>_<日期或期间>_<版本>
例:
010_营业执照_目标公司_2024-06-30_原件扫描.pdf
045_增资协议_目标公司_2021-03-15_签署版.pdf
045a_增资协议补充协议_目标公司_2021-11-02_签署版.pdf
三条纪律:
- 序号与资料清单的编号一致,不要另起一套
- 版本用后缀区分(
_签署版/_扫描件/_补充协议),不要用_v2、_最终、_真的最终 - 原文件名保留在索引里,改名不改内容,可回溯
四、索引:四件套对应
材料收完,建一张索引表。这张表是后面所有工作的地基。
索引表的列:
| 列 | 说明 |
|---|---|
| 序号 | 与清单一致 |
| 材料名称 | 统一命名后的名字 |
| 原文件名 | 客户给的原名 |
| 类别 | 工商/合同/财务/诉讼/资产… |
| 对应专题 | 属于 15 个专题中的哪一个 |
| 页数 | 便于引用 |
| 取得方式 | 客户提供/自行查询/函证 |
| 查验状态 | 未查/已查/待补 |
| 底稿编号 | 归档时的编号 |
四件套必须逐项对应:资料目录、查验清单、报告章节、底稿索引。同一个材料在这四处出现时,编号一致。
不对应会出现什么:报告里写“已查验增资协议”,底稿里找不到;或者清单上有 80 份,实际只查了 60 份,剩下 20 份没人知道去哪了。
五、WorkBuddy 在这一步能做什么
可以交给它:
- 批量 OCR(651 页 25 分钟跑完,人工不可能)
- 按文件名和首页内容自动归类,生成索引初稿
- 交叉比对:同一份合同的签署日期与工商变更日期是否倒挂
- 生成命名规范化脚本
必须自己来:
- 判断某份材料是否属于本项目范围
- 确认 OCR 出来的关键数字(金额、比例、期限)
- 脱敏词表的行业补充
六、本章的自检
- [ ] 所有扫描件都跑过 OCR 了吗?识别率抽检过吗?
- [ ] 脱敏跑了吗?
mask check通过了吗?有没有人工看一遍组合信息? - [ ] 命名规则统一了吗?版本后缀清楚吗?
- [ ] 索引表建了吗?四件套能对上吗?