HR和行政收上来的报名表、报销表里,身份证号是出错重灾区。常见问题有五类,肉眼看不出来,程序一扫就现形:
| 错误类型 | 例子 | 肉眼能发现吗 |
|---|---|---|
| 位数不够 | 330102199001013 | 数一数可以,但几百行呢? |
| 生日段非法 | …194913310021(13月) | 几乎发现不了 |
| 校验位错 | 末位应为X写成了1 | 完全发现不了 |
| 小写x | …002x | 系统比对时才算错 |
| 首尾空格 | "110105…002X " | 完全隐形 |
身份证第18位是校验码:前17位分别乘系数 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2,求和后对11取模,映射到 10X98765432。所以任何一位抄错,末位基本对不上——这就是能自动查错的原因。
import csv, re
W = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
M = '10X98765432'
def check(id18):
id18 = id18.strip().upper() # 防空格 + 小写x
if not re.fullmatch(r'\d{17}[\dX]', id18):
return '格式错误'
y, m, d = int(id18[6:10]), int(id18[10:12]), int(id18[12:14])
if not (1900 <= y <= 2026) or not (1 <= m <= 12) or not (1 <= d <= 31):
return '日期非法'
s = sum(int(a)*b for a, b in zip(id18[:17], W))
return 'OK' if M[s % 11] == id18[17] else f'校验位应为{M[s % 11]}'
with open('名单.csv', encoding='utf-8-sig') as f: # utf-8-sig 防 Excel 导出的 BOM 头
for row in csv.reader(f):
name, idno = row[0], row[1]
r = check(idno)
if r != 'OK':
print(name, idno, '->', r)
本站实测输出:
李四 110105194912310021 -> 校验位应为X 王五 330102199001013 -> 格式错误 赵六 110105194913310021 -> 日期非法
utf-8 读,第一行的姓名会带个看不见的 \ufeff,变成"张三"。务必 encoding='utf-8-sig'。datetime,但对收表场景粗查性价比更高)。说明:校验位通过≠号码真实存在,只是排除"抄错/编错"的情况,核验真伪仍需官方渠道。
虚拟服务交付后不退款;未达承诺免费重做。