← 返回免费工具清单 | 付费服务

收表必看:批量核验身份证号是否有效

HR和行政收上来的报名表、报销表里,身份证号是出错重灾区。常见问题有五类,肉眼看不出来,程序一扫就现形:

错误类型例子肉眼能发现吗
位数不够330102199001013数一数可以,但几百行呢?
生日段非法…194913310021(13月)几乎发现不了
校验位错末位应为X写成了1完全发现不了
小写x…002x系统比对时才算错
首尾空格"110105…002X "完全隐形

原理:第18位是算出来的

身份证第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 -> 日期非法

四个实际踩过的坑

  1. Excel 存的 CSV 带 BOM:用默认 utf-8 读,第一行的姓名会带个看不见的 \ufeff,变成"张三"。务必 encoding='utf-8-sig'。
  2. 只报"格式错误"不够:像"校验位应为X"这种提示能直接告诉收表人怎么改,来回沟通少一轮。
  3. 先 strip 再校验:Excel 里复制出来的号码尾部常带空格,不 strip 全部误报格式错误。
  4. 日期范围别写死到当年之后:出生年份上限用当前年即可,月份日期先粗查 1–12 / 1–31,够拦住绝大多数手滑(精确历法校验可用 datetime,但对收表场景粗查性价比更高)。

说明:校验位通过≠号码真实存在,只是排除"抄错/编错"的情况,核验真伪仍需官方渠道。

不想自己跑脚本?把表格发给我们,几分钟替你扫完全表并标出每一行的错误原因。查看服务与下单 →(更多免费脚本清单)

虚拟服务交付后不退款;未达承诺免费重做。