本文目录导读:

这是一个非常实用的问题,在数据处理和展示中,保护个人隐私(如身份证号)是必须遵守的准则。
在Python中隐藏身份证信息,核心思路就是*只保留部分关键字符(如生日或首尾几位),其余用星号()替代**,下面介绍几种常用的实现方法,从简单到灵活。
字符串切片 + 拼接(最常用)
这个方法最直观,适合格式统一(18位)的身份证号。
通常规则是:显示前6位和后4位,中间隐藏(出生日期和顺序码)。
def mask_id_card(id_number):
"""
隐藏身份证号,保留前6位和后4位,中间用4个星号代替。
格式: 110101 **** 1234
"""
if not id_number or len(id_number) != 18:
return "无效的身份证号"
# 提取前6位,后4位
start = id_number[:6]
end = id_number[-4:]
# 拼接
masked = start + "****" + end
return masked
# 示例
id_card = "110101199001011234"
print(mask_id_card(id_card)) # 输出: 110101****1234
使用正则表达式(re模块)
当数据中包含多个身份证号,或者需要从一段文本中自动识别并隐藏时,正则表达式非常有用。
import re
def mask_id_card_regex(text):
"""
在文本中查找并隐藏身份证号。
匹配规则:18位数字(简单匹配),保留前6后4,中间替换为4个星号。
"""
# 匹配18位数字(更严谨可加入校验位判断,但这里做简化)
pattern = r'\b(\d{6})\d{8}(\d{4})\b' # 分组:前6位,后4位
# 替换函数:用前6位 + **** + 后4位 替换匹配到的完整数字
replacement = r'\1****\2'
masked_text = re.sub(pattern, replacement, text)
return masked_text
# 示例
text = "用户A的身份证是110101199001011234,用户B的是440106198609056789。"
print(mask_id_card_regex(text))
# 输出: 用户A的身份证是110101****1234,用户B的是440106****6789。
注意:如果身份证末尾有X(大小写),需要调整正则:
pattern = r'\b(\d{6})\d{8}(\d{3}[0-9Xx])\b'
隐藏出生日期部分(中间8位)
有些场景不想要固定的前6后4,而是隐藏中间8位(出生年月日),规则稍有不同。
def mask_id_card_birth(id_number):
"""
隐藏出生日期,保留前6位和后4位。
"""
if not id_number or len(id_number) != 18:
return "无效的身份证号"
start = id_number[:6]
# 隐藏中间8位(第7到第14位)
middle = "********" # 8个星号
end = id_number[-4:]
return start + middle + end
# 示例
print(mask_id_card_birth("110101199001011234")) # 输出: 110101********1234
灵活的函数(可自定义隐藏位置和长度)
如果需要更灵活的配置(比如不同业务要求隐藏不同段位),可以写一个通用函数。
def mask_center(s, start_keep=6, end_keep=4, mask_char='*'):
"""
隐藏字符串中间的字符。
:param s: 原字符串(如身份证号)
:param start_keep: 开头保留的字符数
:param end_keep: 结尾保留的字符数
:param mask_char: 用于隐藏的字符(默认为*)
"""
if not s or len(s) <= start_keep + end_keep:
return s # 太短则直接返回
# 计算需要隐藏的中间部分的长度
hidden_len = len(s) - start_keep - end_keep
# 构建掩码字符串
masked_part = mask_char * hidden_len
# 拼接
return s[:start_keep] + masked_part + s[-end_keep:]
# 示例
print(mask_center("110101199001011234")) # 默认: 110101****1234
print(mask_center("110101199001011234", 4, 4)) # 保留前4后4: 1101****1234
print(mask_center("110101199001011234", 6, 6)) # 保留前6后6: 110101****011234
print(mask_center("ABCD1234EFGH", 4, 4, '#')) # 自定义掩码字符: ABCD####EFGH
处理不同位数(15位或18位)的身份证
旧版身份证是15位,如果系统中有15位,需要兼容处理。
def mask_id_card_v2(id_number):
"""
兼容15位和18位身份证的隐藏函数。
15位:保留前6位和后3位(旧版身份证最后几位是顺序码+校验码)
18位:保留前6位和后4位
"""
if not id_number:
return ""
length = len(id_number)
if length == 15:
return id_number[:6] + "******" # 中间6位用星号
elif length == 18:
return id_number[:6] + "****" + id_number[-4:]
else:
return id_number # 非标准格式,原样返回或报错
# 示例
print(mask_id_card_v2("110101900101123")) # 15位: 110101******
print(mask_id_card_v2("110101199001011234")) # 18位: 110101****1234
总结建议
| 方法 | 适用场景 | 代码复杂度 |
|---|---|---|
| 字符串切片拼接 | 少量、固定格式的数据处理 | 低 |
| 正则表达式 | 从日志、文本等杂乱数据中批量替换 | 中 |
| 自定义函数 | 业务需求变化频繁,需要灵活控制 | 低到中 |
| 兼容性函数 | 系统同时存在15位和18位身份证 | 中 |
最佳实践:
- 在显示或导出数据时立即脱敏,不要在数据库中存储明文。
- 如果是前端显示,建议后端做好脱敏再输出。
- 可以使用像
pandas的apply函数对整列数据进行脱敏。
如果有其他具体场景(如Excel文件、数据库查询结果等),可以进一步优化实现。