---
type: article
title: "智能自动脱敏工具 · 全景指南（规则 / 边界 / 流程 / 图像）"
date: 2026-07-23 16:02:00 +0800
tags: [workbuddy, image-text-desensitization, desensitize, privacy, security, python, regex, ocr, opencv]
---

> **技能**：`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` 闭环：

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

### 终端输出样例
```text
[检测] 原文敏感信息: 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
```jsonc
// 输入
{"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 直接调用技能
```python
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`（随本工作区提供）
```bash
# 文本
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` 自动清理）。
