用 python 制作全国身份证号验证及查询系统

​大家好哇,又是一个愉快的周末,今天本鸟给大家分享1个有趣的实战项目,用python制作“全国身份证号验证及查询系统”,成品界面如下图:

本系统可以实现身份证号真伪验证,年龄、性别及发证地查询,看起来是不是很高大上,其实做起来不是很复杂,涉及知识主要有python字符串处理、表格读写和Gui制作,适合有一定python基础的朋友练手,下面一起来看看怎么实现的吧!

第一步:身份证号解析

身份证号一般由18位号码组成,前6位为地址码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。6位地址码为编码对象户口所在县(市、区)的行政区划代码;8位出生日期码为出生年月日;3位顺序码为县(市、区)所辖派出所的分配码,顺序码的奇数分配给男性,偶数分配给女性;1位校验码是按统一公式计算出来的。

第二步:归类整理地址码与区县对应关系

这个网上比较常见,随便搜索1个身份证号都会返回所在的区县地址,我们要做的是把所有的对应关系都找到,恰巧网上已经有现成的了,不过要稍加整理,大家可以去网上找一下,但是要擦亮眼睛啊,有一个版本是错的,实在找不到的可以联系我,我已经整理好存入表格中

第三步:验证身份证号真伪

身份证最后一位校验码算法如下:
①将身份证号码前17位数分别乘以不同的系数,从第1位到第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这些个数字,其对应的身份证最后一位校验码为1 0 X 9 8 7 6 5 4 3 2。
代码实现如下:

第四步:查询地区

规则参考第一步,python两行代码就搞定了

不得不说,python就是简单方便

第五步:计算出年龄及性别

规则同样参考第一步,代码如下:

到此为止,项目的主体功能已经实现,下面要想办法用GUI界面实现。

第六步:制作GUI界面

本步骤主要用PyQt5实现,下面我把核心代码贴出来:

首先是以网格方式对标签及文本框进行布局,并用setStyleSheet对文本框进行修饰

然后是设置查询按钮并布局,再与check函数(信号)绑定

接着是在check函数中将查询到的结果在文本框中显示出来

最后设置主窗口图片背景

到此为止,本项目就大功告成了,你学会了吗?

但是要声明一下,本文所介绍的查询功能均为正向查询,即在已知身份证号的前提下,解析原则来源于网络,不敢保证100%准确,更不能反向推算出个人身份证号,所以不涉及侵犯隐私问题。

本文所涉及的代码、表格已经上传,请在公众号[python的爬虫与数据分析之路]后台输入“20200329”获取。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 1
Jason990420

我也写了一个, 地区码第一次上网爬, 后存成 json 档, 下回就用 json 档内容.

不加说明了.

Tool.py

"""
公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
排列顺序从左至右依次为:
  - 六位数字地址码
  - 八位数字出生日期码
  - 三位数字顺序码 (顺序码的奇数分配给男性,偶数分配给女性)
  - 一位数字校验码。
"""
from Tool import Read_URL, Save_File, Read_File
from bs4 import BeautifulSoup
import PySimpleGUI as sg
from pathlib import Path

def show(field, message, color='white'):
    window.find_element(field).update(value=message, text_color=color)

def verify(number):
    product = sum(map(int.__mul__, map(int, number[:-1]), factor))
    result = (12- product%11) % 11
    return v_code[result] == number[-1]

def load_database():
    if Path(filename1).is_file():
        area_code = Read_File(filename1)
    else:
        response, html = Read_URL(url1)
        if html == None:
            print('地址码资料库无法载入 !')
            quit()
        soup = BeautifulSoup(html, features='html.parser')
        tags = soup.findAll('tr')
        result = []
        for tag in tags:
            first = tag.findAll('td', {"class":"xl7030721"})
            second = tag.findAll('td', {"class":"xl7130721"})
            if first != []:
                level = 1
                code = first[0].text.strip()
                name = first[1].text.strip()
                if first[1].find('span') != None:
                    level = 2
            elif second != []:
                level = 3
                code = second[0].text.strip()
                name = second[1].text.strip()
            result.append([level, code, name])
        area_code = {}
        province, city, county = '', '', ''
        for item in result:
            if item[0] == 1:
                province, city, county = item[2], '', ''
            elif item[0] == 2:
                city, county = item[2], ''
            else:
                county = item[2]
            area_code[item[1]] =[province, city, county]
        Save_File(filename1, area_code)

def Button(text, key):
    return sg.Button(text, font=font, size=(10,1), key=key, enable_events=True)

def Input(key):
    return sg.Input('', font=font2, size=(18, 1), key=key)

def Text(text, key):
    return sg.Text(text, font=font, size=(60, 1), relief='raised', key=key)

url1 = 'http://www.mca.gov.cn/article/sj/xzqh/2020/2020/202003301019.html'
filename1 = 'China Area Code.json'
v_code = '10X98765432'
factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
gender = ['女', '男']

font, font2 = ('Courier', 16, 'bold'), ('Courier', 23, 'bold')
layout = [[sg.Text('请输入身份证号码', font=font)],
          [Input('INPUT'),Button('检查','CHECK'),Button('离开系统','QUIT')],
          [Text('性  別: ', 'GEND')],
          [Text('地  区: ', 'AREA')],
          [Text('出生日期: ', 'DATE')],
          [Text('验证结果: ', 'CODE')]]
window = sg.Window('身份证号码检查系统', layout=layout, finalize=True)

while True:

    event, values = window.read()

    if event in [None, 'QUIT']:
        break

    elif event == 'CHECK':
        number = values['INPUT'].strip()
        if not number.isdecimal():
            show('CODE', '验证结果: 输入非数字错误', 'blue')
        elif len(number) != 18:
            show('CODE', f'验证结果: 长度{len(number)}错误, 应为18位', 'blue')
        else:
            area = number[:6]
            birth = number[6:14]
            birth = f'{birth[:4]}/{birth[4:6]}/{birth[6:]}'
            try:
                birthday = datetime.strptime(birth, '%Y/%m/%d')
                show('DATE', f'出生日期: {birth}')
            except:
                show('DATE', f'出生日期: {birth}日期內容错误', 'blue')
            show('GEND', f'性  別: {gender[int(number[16])%2]}性')
            if area in area_code:
                show('AREA', f"地  区: {''.join(area_code[area])}")
            else:
                show('AREA', '地  区: 地址码错误', 'blue')
            if verify(number):
                show('CODE', '验证结果: 编码正确')
            else:
                show('CODE', '验证结果: 编码错误', 'blue')
    window.find_element('INPUT').update(select=True)

window.close()
4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!