中国的居民身份证有18位。其中前17位是信息码,最后1位是校验码。每位信息码可以是0-9的数字,而校验码可以是0-9或X,其中X表示10。
身份证校验码算法:
设18位身份证号序列从左到右为:
引用
a[0], a[1], a[2], a[3], ..., a[16], a[17]
其中a[i]表示第i位数字,i=0,1,2,...,17,如果最后一位(校验位)是X,则a[17]=10
每一位被赋予一个“权值”,其中,第i位的权值w[i]的计算方法是:
引用
w[i] = 2**(17-i) % 11
其中,i=0,1,2,3,...,17,运算符按Python惯例:x**y表示x的y次方,x%y表示x除以y的余数。
如果一个身份证号是正确的,那么:
引用
(a[0]*w[0] + a[1]*w[1] + a[2]*w[2] + ... + a[16]*w[16] + a[17]*w[17]) % 11 == 1
实际上,校验位a[17]的计算方法,就是巧妙地选择一个值使得上式成立。
根据上述算法,下面是一个验证身份证号正确性的程序。
初学者————代码没有什么依照编写规范,流水账的模式。还有两个功能没有实现:
1、依照身份证号码的区域代码解析所在区域;
2、将身份证校验码的校验作为前置判断,如果错误就不再解析其他内容,汗,我还不会;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
ID = input ( '请输入十八位身份证号码: ' )
if len ( ID ) = = 18 :
print ( "你的身份证号码是 " + ID )
else :
print ( "错误的身份证号码" )
ID_add = ID [ 0 : 6 ]
ID_birth = ID [ 6 : 14 ]
ID_sex = ID [ 14 : 17 ]
ID_check = ID [ 17 ]
#ID_add是身份证中的区域代码,如果有一个行政区划代码字典,就可以用获取大致地址#
year = ID_birth[ 0 : 4 ]
moon = ID_birth[ 4 : 6 ]
day = ID_birth[ 6 : 8 ]
print ( "生日: " + year + '年' + moon + '月' + day + '日' )
if int (ID_sex) % 2 = = 0 :
print ( '性别:女' )
else :
print ( '性别:男' )
#此部分应为错误判断,如果错误就不应有上面的输出,如何实现?#
W = [ 7 , 9 , 10 , 5 , 8 , 4 , 2 , 1 , 6 , 3 , 7 , 9 , 10 , 5 , 8 , 4 , 2 ]
ID_num = [ 18 , 17 , 16 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 ]
ID_CHECK = [ '1' , '0' , 'X' , '9' , '8' , '7' , '6' , '5' , '4' , '3' , '2' ]
ID_aXw = 0
for i in range ( len (W)):
ID_aXw = ID_aXw + int ( ID [i]) * W[i]
ID_Check = ID_aXw % 11
if ID_check = = ID_CHECK[ID_Check]:
print ( '正确的身份证号码' )
else :
print ( '错误的身份证号码' )
|
我们再来看一个更加完善些的示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
import re
#Errors=['验证通过!','身份证号码位数不对!','身份证号码出生日期超出范围或含有非法字符!','身份证号码校验错误!','身份证地区非法!']
def checkIdcard(idcard):
Errors = [ '验证通过!' , '身份证号码位数不对!' , '身份证号码出生日期超出范围或含有非法字符!' , '身份证号码校验错误!' , '身份证地区非法!' ]
area = { "11" : "北京" , "12" : "天津" , "13" : "河北" , "14" : "山西" , "15" : "内蒙古" , "21" : "辽宁" , "22" : "吉林" , "23" : "黑龙江" , "31" : "上海" , "32" : "江苏" , "33" : "浙江" , "34" : "安徽" , "35" : "福建" , "36" : "江西" , "37" : "山东" , "41" : "河南" , "42" : "湖北" , "43" : "湖南" , "44" : "广东" , "45" : "广西" , "46" : "海南" , "50" : "重庆" , "51" : "四川" , "52" : "贵州" , "53" : "云南" , "54" : "*" , "61" : "陕西" , "62" : "甘肃" , "63" : "青海" , "64" : "宁夏" , "65" : "*" , "71" : "*" , "81" : "香港" , "82" : "澳门" , "91" : "国外" }
idcard = str (idcard)
idcard = idcard.strip()
idcard_list = list (idcard)
#地区校验
if ( not area[(idcard)[ 0 : 2 ]]):
print Errors[ 4 ]
#15位身份号码检测
if ( len (idcard) = = 15 ):
if (( int (idcard[ 6 : 8 ]) + 1900 ) % 4 = = 0 or (( int (idcard[ 6 : 8 ]) + 1900 ) % 100 = = 0 and ( int (idcard[ 6 : 8 ]) + 1900 ) % 4 = = 0 )):
erg = re. compile ( '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$' ) #//测试出生日期的合法性
else :
ereg = re. compile ( '[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$' ) #//测试出生日期的合法性
if (re.match(ereg,idcard)):
print Errors[ 0 ]
else :
print Errors[ 2 ]
#18位身份号码检测
elif ( len (idcard) = = 18 ):
#出生日期的合法性检查
#闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
#平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if ( int (idcard[ 6 : 10 ]) % 4 = = 0 or ( int (idcard[ 6 : 10 ]) % 100 = = 0 and int (idcard[ 6 : 10 ]) % 4 = = 0 )):
ereg = re. compile ( '[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$' ) #//闰年出生日期的合法性正则表达式
else :
ereg = re. compile ( '[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$' ) #//平年出生日期的合法性正则表达式
#//测试出生日期的合法性
if (re.match(ereg,idcard)):
#//计算校验位
S = ( int (idcard_list[ 0 ]) + int (idcard_list[ 10 ])) * 7 + ( int (idcard_list[ 1 ]) + int (idcard_list[ 11 ])) * 9 + ( int (idcard_list[ 2 ]) + int (idcard_list[ 12 ])) * 10 + ( int (idcard_list[ 3 ]) + int (idcard_list[ 13 ])) * 5 + ( int (idcard_list[ 4 ]) + int (idcard_list[ 14 ])) * 8 + ( int (idcard_list[ 5 ]) + int (idcard_list[ 15 ])) * 4 + ( int (idcard_list[ 6 ]) + int (idcard_list[ 16 ])) * 2 + int (idcard_list[ 7 ]) * 1 + int (idcard_list[ 8 ]) * 6 + int (idcard_list[ 9 ]) * 3
Y = S % 11
M = "F"
JYM = "10X98765432"
M = JYM[Y] #判断校验位
if (M = = idcard_list[ 17 ]): #检测ID的校验位
print Errors[ 0 ]
else :
print Errors[ 3 ]
else :
print Errors[ 2 ]
else :
print Errors[ 1 ]
|
可以通过命令行输入。第一个命令行参数是身份证号。输出Valid或Invalid。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
USAGE = """\
USAGE: python shenfenzheng.py shenfenzhenghao
"""
chmap = {
'0' : 0 , '1' : 1 , '2' : 2 , '3' : 3 , '4' : 4 , '5' : 5 , '6' : 6 , '7' : 7 , '8' : 8 , '9' : 9 ,
'x' : 10 , 'X' : 10
}
def ch_to_num(ch):
return chmap[ch]
def verify_string(s):
char_list = list (s)
num_list = [ch_to_num(ch) for ch in char_list]
return verify_list(num_list)
def verify_list(l):
sum = 0
for ii,n in enumerate (l):
i = 18 - ii
weight = 2 * * (i - 1 ) % 11
sum = ( sum + n * weight) % 11
# print "i=%d,weight=%d,n=%d,sum=%d"%(i,weight,n,sum)
# print sum
return sum = = 1
if __name__ = = '__main__' :
import sys
if len (sys.argv)! = 2 :
print USAGE
sys.exit( 1 )
result = verify_string(sys.argv[ 1 ])
if result:
print "Valid"
else :
print "Invalid"
|
命令行使用举例:
引用
1
|
$ python shenfenzheng.py 320105198209275127
|