中国的居民身份证有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 |