一个非常不错的验证身份证号码的函数
环境
python 3
具体代码
基础版
def validate_idcard(idcard):
# 1. 基础格式校验
if len(idcard) != 18:
return False, "长度错误"
# 正则匹配(允许最后一位为X/x)
pattern = r'^\d{17}[\dXx]$'
if not re.match(pattern, idcard):
return False, "格式错误"
# 2. 出生日期校验
try:
birth_date = datetime.strptime(idcard[6:14], "%Y%m%d")
if birth_date > datetime.now(): # 排除未来日期
return False, "出生日期在未来"
except ValueError:
return False, "无效出生日期"
# 3. 校验码计算
weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check_codes = "10X98765432"
total = sum(int(idcard[i]) * weights[i] for i in range(17))
expected_check = check_codes[total % 11]
if idcard[-1].upper() != expected_check:
return False, f"校验码错误(应为{expected_check})"
return True, "有效身份证号"
错误定位增强版
def detailed_validate(idcard):
errors = []
# 长度校验
if len(idcard) != 18:
errors.append("长度必须为18位")
# 格式校验
if not re.match(r'^\d{17}[\dXx]$', idcard):
errors.append("包含非法字符(仅允许数字和末位X/x)")
# 地区码校验(需扩展地区码库)
# area_code = idcard[:6]
# if area_code not in valid_area_codes:
# errors.append("无效地区编码")
# 出生日期校验
try:
birth_date = datetime.strptime(idcard[6:14], "%Y%m%d")
if birth_date > datetime.now():
errors.append("出生日期在未来")
except ValueError:
errors.append("出生日期格式错误(应为YYYYMMDD)")
# 校验码校验
weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
check_codes = "10X98765432"
total = sum(int(idcard[i])*weights[i] for i in range(17))
expected = check_codes[total%11]
if idcard[-1].upper() != expected:
errors.append(f"校验码错误(应为{expected},实际为{[1](@ref)})")
return len(errors) == 0, errors
性能优化版(批量处理)
def detailed_validate(idcard):
errors = []
# 长度校验
if len(idcard) != 18:
errors.append("长度必须为18位")
# 格式校验
if not re.match(r'^\d{17}[\dXx]$', idcard):
errors.append("包含非法字符(仅允许数字和末位X/x)")
# 地区码校验(需扩展地区码库)
# area_code = idcard[:6]
# if area_code not in valid_area_codes:
# errors.append("无效地区编码")
# 出生日期校验
try:
birth_date = datetime.strptime(idcard[6:14], "%Y%m%d")
if birth_date > datetime.now():
errors.append("出生日期在未来")
except ValueError:
errors.append("出生日期格式错误(应为YYYYMMDD)")
# 校验码校验
weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
check_codes = "10X98765432"
total = sum(int(idcard[i])*weights[i] for i in range(17))
expected = check_codes[total%11]
if idcard[-1].upper() != expected:
errors.append(f"校验码错误(应为{expected},实际为{[1](@ref)})")
return len(errors) == 0, errors