基于Python实现身份证号码验证

摘要: 该设计主要使用python语言来实现身份证号验证程序。它运用 tkinter模块生成GUI界面。当用户输入身份证号,按下检查按钮,即可判断身份证号是否正确。该程序简洁,灵活,执行效率高。
关键词: 身份证号; python;tkinter

1 概述

1.1背景

中华人民共和国居民身份证是国家法定的证明公民个人身份的有效证件。在当今社会,有一些不法分子为了躲避法律追捕,伪造身份证的现象也是很普遍的,为了验证公民的身份证号码是否符合国家标准,设计一个身份证号码校验系统是有必要的。

1.2身份证号码编码规则

(1)前六位表示编码对象常住户口所在县(市、镇、区)的行政区划代码。1-2位省、自治区、直辖市代码; 3-4位地级市、盟、自治州代码; 5-6位县、县级市、区代码。
(2)第七位到第十四位表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
(3)第十五位到十七位地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。
(4)18位为校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。如果某人的尾号是0-9,就不会出现X,但如果尾号是10,那么就得用X来代替,X是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。最后一位校验码的计算方法:首先将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2,接下来将这17位数字和系数相乘的结果相加,然后用加出来的和除以11,看余数,余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X -9-8-7-6-5-4-3-2。通过上述方法可以计算一个人的身份证号是否合法。

1.3身份证号验证内容

(1)前六位是否是已有的归属地的号码。
(2)第七位到第十四位,年份是否在1900到2000中,月份是否在01到12中间,对应月份的天数是否符合(平年2月只有28天)。
(3)第18位检验位是否符合要求。

2 系统设计

2.1.功能模块设计

该系统的主要功能是实现身份证号码的验证,当输入身份证号码时,检测身份证是否正确。

django python 身份 python身份证验证_python

2.1.1 GUI界面设计

Tkinter 是使用 python 进行窗口视窗设计的模块。Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口。作为python 特定的GUI界面,是一个图像的窗口,tkinter是python 自带的,可以编辑的GUI界面,我们可以用GUI 实现很多直观的功能。

Button:一个简单的按钮,用来执行一个命令或别的操作。

Entry:文本输入域。

Label:显示一个文本或图象。

Text:格式化文本显示。允许你用不同的样式和属性来显示和编辑文本。同时支持内嵌图象和窗口。

GUI界面设计如图所示:

django python 身份 python身份证验证_检验位_02

2.1.2 身份证号验证

1.前六位验证:前六已位有确定的归属地号码,我们将这些已有的号码建立一个名为area列表。提取要检测号码的前六位,用if语句判断是否属于列表中?如果属于,再判断后几位;如果不属于,则输出“身份证地区非法,错误的身份证号码”。如图3所示。

django python 身份 python身份证验证_python_03


2.中间8位验证:用if语句先行判断是否为闰年,然后用re模块进行判断年月日是否正确。正确,则继续判断最后一位;如果不正确则输出“身份证号出生日期超出范围或者含有非法字符,错误的身份证号”。如图所示。

django python 身份 python身份证验证_Python_04


闰年出生日期合法性判断表达式:[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]$

闰年出生日期合法性判断表达式:[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-8]))’’[0-9]{3}[0-9Xx]$3.最后一位检验位验证: 采用逐位加权求和得出前17位分别与系数成绩的之和。然后除以11取余数,与相应的检验位对比,如果相等则输出“正确的身份证号”;如果不相等,则输出“身份证号码校验错误,错误的身份证号”。如图6和图5。

django python 身份 python身份证验证_Python_05

django python 身份 python身份证验证_Python_06

2.2 数据结构设计

本节将加权系数定义为名为W = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]的列表;对应身份证检验位定名为IDcard_CHECK = [‘1’, ‘0’, ‘X’, ‘9’, ‘8’, ‘7’, ‘6’, ‘5’, ‘4’, ‘3’, ‘2’]的列表,采用逐位加权求和,简化程序,优化算法,如图7所示:

django python 身份 python身份证验证_python_07

2.3 函数功能描述

省份证验证主程序:def check(),当点击按钮“检查”,将执行此程序。删除上一个身份证号的输出结果,显示本次输入的身份证号检查结果,并删除本次输入框身份证号。方便快捷,节省时间。

3 程序实现

import tkinter as tk  # 使用Tkinter前需要先导入
import re

# 第1步,实例化object,建立窗口window
window = tk.Tk()

# 第2步,给窗口的可视化起名字
window.title('Chris')

# 第3步,设定窗口的大小(长 * 宽)
window.geometry('700x500')

# 第4步,在图形界面上设定标签
l = tk.Label(window, text='身份证号验证', font=('宋体', 30), width=40, height=2)
l1 = tk.Label(window, text='身份证号:', font=('Arial', 16), width=40, height=2)

# 第5步,放置标签
l.place(x=-80, y=0, anchor='nw')
l1.place(x=-100, y=80, anchor='nw')

# 第4步,在图形界面上设定输入框控件entry框并放置
e = tk.Entry(window, show=None, font=('Arial', 20),)
e.place(x=200, y=90, anchor='nw')


# 第5步,定义两个触发事件时的函数check和delete
def check():        # 按钮‘检查’对应的函数
    t.delete(1.0, 'end')
    IDcard = e.get()
    if len(IDcard) != 18:
        var = '号码:' + IDcard + "\n身份证号码位数不对!\n错误的身份证号码.\n请重新输入!\n"
    else:
        IDcard_add = IDcard[0:6]     # 身份证前6位,对应归属地
        IDcard_birth = IDcard[6:14]  # 身份证中间8位,对应出生日期
        IDcard_sex = IDcard[14:17]   # 身份证15,,16,17位,对应性别

        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": "国外"}

        # 地区校验
        if IDcard[0:2] not in area.keys():
            var = '号码:' + IDcard + '\n身份证地区非法!\n错误的身份证号码\n'
        else:
            year = IDcard_birth[0:4]   # 出生年份
            month = IDcard_birth[4:6]  # 出生月份
            day = IDcard_birth[6:8]    # 出生日

            # 出生日期的合法性检查
            # 闰年月日:((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(year) % 4 == 0 or (int(year) % 100 == 0 and int(year) % 4 == 0)):
                ereg = re.compile('[1-9][0-9]{5}((19[0-9]{2})|(20[0-1][0-8]))((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})|(20[0-1][0-8]))((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)):
                IDcard_check = IDcard[17]  # 身份证最后一位
                W = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]   # 逐位权数
                IDcard_CHECK = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']  # 身份证检验位
                IDcard_sum = 0                                              # 定义累加和
                for i in range(0, 17):
                    IDcard_sum = IDcard_sum + int(IDcard[i]) * W[i]         # 逐位加权求和
                IDcard_Check = IDcard_sum % 11  # 取余数
                if IDcard_check != IDcard_CHECK[IDcard_Check]:              # 和检验位对比
                    var = '号码:' + IDcard + '\n身份证号码校验错误!\n错误的身份证号码\n'
                else:
                    if int(IDcard_sex) % 2 == 0:
                        var = "正确的身份证号码! \n" + '号码:' + IDcard + '\n地区:' + area[IDcard[0: 2]] + \
                              '\n生日:' + year + '年' + month + '月' + day + '日' + "\n 性别:女\n"
                    else:

                        var = "正确的身份证号码! \n" + '号码:' + IDcard + '\n地区:' + area[IDcard[0: 2]] + \
                              "\n生日: " + year + '年' + month + '月' + day + '日' + "\n性别:男 \n"
            else:
                var = '号码:' + IDcard + '\n身份证号码出生日期超出范围或含有非法字符!\n错误的身份证号码\n'
    t.insert('insert', var)       # 显示输出
    e.delete(0, 'end')

# 第6步,创建并放置两个按钮分别触发两种情况
b1 = tk.Button(window, text='检查', width=10, height=2, command = check)
b1.place(x=550, y=80, anchor='nw')

# 第7步,创建并放置一个多行文本框text用以显示
t = tk.Text(window, font=('宋体', 20), width=38, height=8)
t.place(x=100, y=210, anchor='nw')

# 第8步,主窗口循环显示
window.mainloop()

4 小结

该设计是一个身份证号验证系统,通过输入身份证号,即可检测出身份证号真假,并显示出来。且每次自动删除输入框省份证号和上次的输出结果,可重复检测多个身份证号,主要设计的工作可概括如下:
1.初期对身份证号码进行详细分析,查阅有关资料并翻阅文献,了解了身份证号每一位数字所对应的含义,然后进行数据分析,找出最佳算法。通过python实现了基本的功能。
2.在实现基本功能后,通过查找资料,在Python中用thinter函数实现了GUI界面,使我们更直观的看出身份证所显示的信息。

参考文献

[1] Eric Matthes,Python编程从入门到实践[M].北京: 人名邮电出版社,2012.8.
[2] 严蔚敏,吴伟民,数据结构[M].北京: 清华大学出版社,2004.1.
[3] 身份证上的号码代表啥[J].时代主人,2016(03):29.
[4] 文丰,陈景胜.身份证号里为什么有X[J].应用写作,2013(01):27.
[5] 新一代身份证小知识[J].湖南农机,2012(10):39.
[6] 闫治良,王宇晨.利用Excel函数判断学生身份证信息的准确性[J].电脑编程技巧与维护,2016(03):47-48.