智能自动脱敏工具 · 全景指南(规则 / 边界 / 流程 / 图像)
技能:
image-text-desensitization(别名”智能自动脱敏工具”)v3.0.0 主类:SmartDesensitizer能力:覆盖文本 / JSON / 图像三类对象的隐私脱敏,全程本地运行,不联网 安全背书:经腾讯云安全cloudsec.tencent.com与腾讯内部tix.qq.com扫描,状态均为”安全无风险(benign)“
颜色图例(贯穿全文)
| 颜色 | 类型 |
|---|---|
| 🟣 紫 | 手机号 |
| 🟠 橙 | 身份证 |
| 🩵 青 | 邮箱 |
| 🟢 绿 | 银行卡 |
| 🔴 红 | IP 地址 |
① 能力总览
该技能是一个被动库——需要显式调用才生效,不会自动拦截对话。它提供三个入口方法:
| 入口 | 方法 | 说明 |
|---|---|---|
| 📝 文本脱敏 | desensitize_text(text) | 基于 5 条正则逐类替换。已验证可用,纯 Python 即可。 |
| 🧾 JSON 脱敏 | desensitize_json(json_str) | 按字段名命中 + 按值形态智能遮蔽。已验证可用。 |
| 🖼️ 图像脱敏 | desensitize_image_base64(b64) | OCR 文字框 + 人脸检测后高斯模糊。需额外依赖(本地未装)。 |
② 文本脱敏规则 desensitize_text
源码写死 5 条正则,按固定顺序执行:手机 → 身份证 → 邮箱 → 银行卡 → IP。这是唯一在自由文本里能自动识别的类型集合。
| 类型 | 正则(源码) | 遮盖策略 | 实例(前 → 后) |
|---|---|---|---|
| 🟣 手机号 | 1[3-9]\d{9} | 前3后4:138****5678 | 13812345678 → 138****5678 |
| 🟠 身份证 | \d{17}[\dXx] | 前6后4:110101********1234 | 110101199003071234 → 110101********1234 |
| 🩵 邮箱 | 本地+@+域名 | 本地名留首字:a***@example.com | alice@example.com → a***@example.com |
| 🟢 银行卡 | \d{13,19} | 仅留后4:****0123 | 6222021234567890123 → ****0123 |
| 🔴 IP | \d{1,3}(\.\d{1,3}){3} | 末段保留:***.***.***.100 | 192.168.0.1 → ***.***.***.1 |
⚠️ 边界提醒:README 宣称”9 种文本类型”含姓名、地址、QQ、微信、车牌号——但自由文本中这些不会被自动识别。它们只在 JSON 模式下”字段名命中后”用通用
*占位(见第③节),并非专属正则。
🎯 实时感知演示
原 HTML 指南在第②节嵌入了浏览器端实时脱敏演示:粘贴文本点”脱敏”,JS 复刻上述 5 条规则(顺序与重叠处理同 Python),各类型按对应颜色高亮并遮盖,底部显示「检测 N 处 → 复检残留 0 处 ✅」。
③ JSON 脱敏规则 desensitize_json
与文本不同,JSON 模式按字段名命中(大小写不敏感 + 子串匹配),再按值的形态选遮蔽方式。因此它能在文本模式之外,再多脱好几类。
3.1 默认命中字段名(源码第 135–144 行)
| 类别 | 命中的字段名(子串匹配) |
|---|---|
| 🔑 密码 / 密钥 | password pwd secret token api_key apikey |
| 📞 电话类 | phone mobile tel telephone |
| 🪪 身份证类 | id_card idcard identity 身份证 |
| ✉️ 邮箱类 | email mail |
| 💳 银行卡类 | bank_card bankcard 银行卡 |
| 👤 身份 / 地址 | address 姓名 name real_name realname |
| 💰 收入 | salary wage 工资 |
| 🇺🇸 社保号 | ssn social_security |
3.2 值的遮蔽逻辑(_mask_value,第 180–220 行)
命中字段后,按值的”长相”选遮蔽方式——如果值本身就是手机/邮箱/身份证/银行卡/IP,就用对应类型化遮盖;否则:
- 值形如纯数字且 ≤12 位 → 金额遮蔽
***.** - 长度 ≤ 2 →
*(全遮,如短姓名、密码) - 长度 ≤ 4 → 首字 +
**(如张三→张**) - 更长 → 首字 +
**+ 尾字(通用占位)
💡 也就是说:密码、姓名、地址、工资、社保号这几类只在 JSON 模式下、且字段名命中时才被脱敏;在自由文本里它们原样保留。
3.3 容错
传入非合法 JSON 时,自动回退为 desensitize_text 处理。注意:该方法只接受JSON 字符串,直接传 dict 会报错。
④ 图像脱敏 desensitize_image_base64
这是”文字与图像都支持”的核心。把图片(base64)交给 DeepLearningDesensitizer,对检测到的敏感区域做高斯模糊。
4.1 处理流程
输入图片(base64) → OCR 文字检测(EasyOCR/PaddleOCR) → 人脸检测(OpenCV Haar) → 逐框高斯模糊(PIL) → 输出 JPEG(q95)
4.2 文字脱敏
用 EasyOCR(优先)或 PaddleOCR(备选)检测文字框,对每个框做高斯模糊,模糊半径 = blur_strength // 6(默认强度 51 → 半径约 8.5)。
4.3 人脸脱敏
优先用 OpenCV Haar 级联分类器检测人脸并模糊;若没有 OpenCV,会回退到 _simple_face_blur——而该方法实际直接返回原图(不做任何处理),即”无 opencv 时人脸不脱敏”。
4.4 例子
- 脱敏前(图像):一张含姓名牌 / 证件照 / 聊天截图——可见姓名文字”张三丰”、可见人脸区域、可见手机号文字串。
- 脱敏后(图像):同一张图——姓名文字区域被模糊成色块、人脸区域被模糊、手机号文字区域被模糊,其余背景保持清晰。
🛑 本地环境现状:
opencv-python因解压时内存超限(exit 137)未装上,easyocr/paddleocr也未装。因此当前desensitize_image_base64会原样返回原图(等于没脱敏)。本指南不含本地安装步骤,仅描述能力。若需真正启用,需在内存更充裕的环境补装opencv-python-headless+easyocr。
⚠️ 附带边界:输出强制转 JPEG(透明通道丢失);工具本身不会自动删除原图,删除原图是调用方责任(SOP 示例里有,但代码不保证)。
⑤ 工作流程(检测 → 脱敏 → 复检)
要让”脱敏起作用”可被感知,关键是在调用处把脱敏前 / 脱敏后 + 命中统计亮出来。推荐使用随技能附带的 desensitize_demo.py 闭环:
- 检测(预扫描):用同样的 5 条正则扫描原文,标出敏感实体并计数(重叠去重,更长优先,等长按类型优先级)。
- 脱敏:调用
SmartDesensitizer().desensitize_text / _json,产出遮盖后的文本。 - 复检(再扫描):对脱敏结果再做一次正则扫描,确认残留为 0——这是最硬核的”生效证据”。
- 输出对照:终端彩色前后对比 + 统计;或生成 HTML 左右对照报告。
终端输出样例
[检测] 原文敏感信息: 5 处 {手机1, 身份证1, 邮箱1, 银行卡1, IP1}
【脱敏前】…13812345678…110101199003071234…(敏感词彩色高亮)
【脱敏后】…138****5678…110101********1234…
[复检] 脱敏后残留: 0 处 ✅ 已全部清除
[结果] 本次已脱敏 5 处敏感信息 🛡️
⑥ 边界与坑(务必知悉)
🛑 ① 自由文本只有 5 种。 姓名 / 地址 / QQ / 微信 / 车牌号在正文里不会被自动识别;其中仅姓名、地址可在 JSON 字段名命中后被通用
*占位,QQ / 微信 / 车牌号在任何模式下都不支持。
⚠️ ② 子串匹配误伤。 字段名匹配是子串 + 大小写不敏感:
name会顺带命中username、filename;address命中home_address。非敏感字段若含这些子串会被误遮。
⚠️ ③ 身份证 / 银行卡正则串扰。 身份证正则匹配任意 18 位连续数字,会先”吃掉”19 位银行卡号的前 18 位,导致长银行卡被当身份证处理、露出不该露的片段。生产环境建议调正则顺序 / 加边界断言。
💡 ④ 自动初始化污染 cwd。 导入模块时底部
auto_init_desensitize_rules()会在当前工作目录生成./基础设定/DESENSITIZE_RULES.md和./MEMORY.md。真实项目首次import会触发,需自行清理(desensitize_demo.py已用try/finally自动清理)。
⚠️ ⑤ 图像人脸强依赖 OpenCV。 没装时
_simple_face_blur是空实现,人脸不脱敏;缺失 OCR/OpenCV 时desensitize_image_base64直接返回原图。
💡 ⑥ 不自动删原图。 文档说”脱敏后自动删除原图”,但代码里不删文件,删除原图是调用方
os.remove的责任。
⑦ 示例对照
7.1 文本
- 脱敏前:客户张三丰,手机13812345678,身份证110101199003071234,邮箱zhang@corp.com,银行卡6222021234567890123,服务器192.168.0.1
- 脱敏后:客户张三丰,手机
138****5678,身份证110101********1234,邮箱z***@corp.com,银行卡****0123,服务器***.***.***.1
7.2 JSON
// 输入
{"name":"李四","phone":"13900001111","id_card":"110101199001011234",
"email":"li@x.com","password":"mypass123","bank_card":"6222021234567890123",
"address":"北京市海淀区中关村大街1号","salary":"25000"}
// 输出(字段名命中 + 值形态遮蔽)
{"name":"李**","phone":"139****1111","id_card":"110101********1234",
"email":"l***@x.com","password":"*****","bank_card":"****0123",
"address":"北*******************","salary":"***.**"}
7.3 图像(描述,本地未运行)
输入含证件照的截图 → 输出同一张图,但姓名文字框、人脸区域、手机号文字框均被高斯模糊为色块,背景保持清晰。详见第④节。
⑧ 使用与感知
8.1 直接调用技能
import sys; sys.path.insert(0, "~/.workbuddy/skills/image-text-desensitization")
from smart_desensitize_skill import SmartDesensitizer
d = SmartDesensitizer()
d.desensitize_text("我的手机号13812345678") # 文本
d.desensitize_json('{"phone":"13812345678"}') # 传 JSON 字符串
d.desensitize_image_base64(img_b64) # 图片(需额外依赖)
8.2 感知工具 desensitize_demo.py(随本工作区提供)
# 文本
python desensitize_demo.py "我的手机号13812345678,身份证110101199003071234"
# JSON
python desensitize_demo.py -j '{"name":"李四","phone":"13900001111"}'
# 生成左右对照 HTML 报告
python desensitize_demo.py "..." --html report.html
该工具已修复:① 正则重叠导致的计数虚高(去重后贴近真实实体数);② 自动初始化在 cwd 落文件的问题(try/finally 自动清理)。