智能自动脱敏工具 · 全景指南(规则 / 边界 / 流程 / 图像)

技能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****567813812345678138****5678
🟠 身份证\d{17}[\dXx]前6后4:110101********1234110101199003071234110101********1234
🩵 邮箱本地+@+域名本地名留首字:a***@example.comalice@example.coma***@example.com
🟢 银行卡\d{13,19}仅留后4:****01236222021234567890123****0123
🔴 IP\d{1,3}(\.\d{1,3}){3}末段保留:***.***.***.100192.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 闭环:

  1. 检测(预扫描):用同样的 5 条正则扫描原文,标出敏感实体并计数(重叠去重,更长优先,等长按类型优先级)。
  2. 脱敏:调用 SmartDesensitizer().desensitize_text / _json,产出遮盖后的文本。
  3. 复检(再扫描):对脱敏结果再做一次正则扫描,确认残留为 0——这是最硬核的”生效证据”。
  4. 输出对照:终端彩色前后对比 + 统计;或生成 HTML 左右对照报告。

终端输出样例

[检测] 原文敏感信息: 5 处  {手机1, 身份证1, 邮箱1, 银行卡1, IP1}
【脱敏前】…13812345678…110101199003071234…(敏感词彩色高亮)
【脱敏后】…138****5678…110101********1234…
[复检] 脱敏后残留: 0 处  ✅ 已全部清除
[结果] 本次已脱敏 5 处敏感信息 🛡️

⑥ 边界与坑(务必知悉)

🛑 ① 自由文本只有 5 种。 姓名 / 地址 / QQ / 微信 / 车牌号在正文里不会被自动识别;其中仅姓名、地址可在 JSON 字段名命中后被通用 * 占位,QQ / 微信 / 车牌号在任何模式下都不支持。

⚠️ ② 子串匹配误伤。 字段名匹配是子串 + 大小写不敏感:name 会顺带命中 usernamefilenameaddress 命中 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 自动清理)。