【python】身份证号码有效性校验
1. 前言
中华人民共和国国家标准GB 11643-1999《公民身份号码》中规定:公民身份号码是特征组合码,由17位数字本体码和1位校验码组成。
18位数字组合的方式是:
其中,最后一位是校验码,它是由前17位数字按照某种计算方式计算出来的。校验码为一位数,但如果最后采用校验码系统计算的校验码是“10”,碍于身份证号码为18位的规定,则以“X”代替校验码“10”。
计算方式如下:
- 将身份证号码从左至右标记为 a 1 , a 2 , ⋯ , a 18 \displaystyle a_{1},a_{2},\cdots ,a_{18} a1,a2,⋯,a18; a 18 \displaystyle a_{18} a18即为校验码;
- 计算权重系数 W i = 2 18 − i m o d 11 \displaystyle W_{i}=2^{18-i}\ {\bmod {\ }}{11} Wi=218−i mod 11;其中 m o d \displaystyle \ \bmod {\ } mod 表示求余数。
i i i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
W i W_{i} Wi | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 |
- 计算 S = ∑ i = 1 17 a i ⋅ W i \displaystyle S=\sum _{i=1}^{17}a_{i}\cdot W_{i} S=i=1∑17ai⋅Wi
- a 18 = ( 12 − ( S m o d 1 1 ) ) m o d 1 1 \displaystyle a_{18}=(12-(S\ {\bmod {1}}1)){\bmod {1}}1 a18=(12−(S mod11))mod11
2. 代码
def main(id):
sum = 0
for index, item in enumerate(id[:-1]):
sum += 2**(17-index) % 11*int(item)
num = (12 - sum % 11) % 11
if num < 10:
return '校验通过' if id[-1] == str(num) else f'校验失败,正确尾号应为:{num}'
else:
return '校验通过' if id[-1] == 'X' else f'校验失败,正确尾号应为:{num}'
if __name__ == '__main__':
test_id_1 = '532527195503267352'
test_id_2 = '53252719550326735X'
print(main(test_id_1))
print(main(test_id_2))
'''输出
校验通过
校验失败,正确尾号应为:2
'''
3. 注意
正确的校验码是身份证号码有效性的必要条件,而非充分条件。要保证身份证号码的有效性,其它条件也要满足,比如号码位数必须为18位,地址码要符合中华人民共和国关于行政区划代码的规定,还有就是出身日期码也要合法等等。有兴趣的话,你可以自己编程实现。当然,这里也提供一个已经封装好的python第三方库id-validator。
3.1. 安装
pip install id-validator
3.2. 使用
3.2.1. 验证身份证号合法性
验证身份证号是否合法,合法返回 True,不合法返回 False:
>>> from id_validator import validator
>>> validator.is_valid('440308199901101512')
True
>>> validator.is_valid('44030819990110151X')
False
3.2.2. 获取身份证号信息
当身份证号合法时,返回分析信息(地区、出生日期、星座、生肖、性别、校验位),不合法返回 False:
>>> from id_validator import validator
>>> validator.get_info('440308199901101512')
{
"address_code": "440308",
"abandoned": 0,
"address": "广东省深圳市盐田区",
"address_tree": [
"广东省",
"深圳市",
"盐田区"
],
"age": 22,
"birthday_code": "1999-01-10",
"constellation": "摩羯座",
"chinese_zodiac": "卯兔",
"sex": 1,
"length": 18,
"check_bit": "2"
}
3.2.3. 生成可通过校验的假数据
伪造符合校验的身份证:
>>> from id_validator import validator
>>> validator.fake_id()
'410704200302268552'
4. 参考
https://zh.wikipedia.org/wiki/中华人民共和国公民身份号码
https://github.com/jxlwqq/id-validator.py