鱼C论坛

 找回密码
 立即注册
查看: 1956|回复: 0

[技术交流] 使用Python进行身份证输入校验

[复制链接]
发表于 2022-11-8 20:20:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 hynet1024 于 2022-11-8 20:39 编辑

在日常应用中,经常需要输入身份证号,因为号码较长容易录错,因此需要进行实时校验,以尽可能保证输入正确。以下以Python为例,浅聊身份证号码校验的方法。

        首先我们需要了解身份证号各个号段的意义。身份证号共18位,其中前6位是行政区划编码,7--14位是出生日期(格式为xxxx年xx月xx日),15--17位是顺序编码(其中第17位是性别编码,奇数代表男,偶数代表女),最后第18位则是校验码。前17位都是数字,最后一位校验码共11个,分别是0,1,2,3,4,5,6,7,8,9,Ⅹ(不是字母X,是罗马数字的10,也可以当做数字理解)。

        校验码是如何生成的呢?是根据前17位进行系数运算得来的。

        系数运算又是怎么回事呢?其实很简单,请记住10个系数和他们的循环顺序,依次是: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对应即为校验码。

        如果你还有点晕,那么看看下面的实例就会明白了。

        如有身份证号为:42058219721014003?(这里先隐去校验码),共17位,将第1位4乘以7得到28,第2位2乘以9得到18,第3位0乘以10得到0,.....第17位3乘以2得到6,将17个乘积相加,各个乘积累加值为245。见图1

        将累加值除以11,余数为3,按图2对应表得知,余数3对应的校验码为9,因此该身份码末位校验码就是9,即完整的身份证号为420582197210140039。

        好了,基本理论弄明白了,下面来分析下代码该做些什么。其实代码很低简单,只是要考虑的问题多一点,整理如下:
        1、身份证长度必须为18位长,前17位必须为数字(最后一位如果是X,也可以当做数字处理,为方便本例只处理前17位)
        2、出生日期必须是合法的日历格式(包括判断是否闰年)
        3、出生年份应介于1900年--当前年份之间(含)
        4、出生日期不能晚于当天
        5、检查校验码是否正确

        若以上规则校验通过,则提示身份证号校验无误,并根据第17位判断出性别予以提示。

        好了,最后直接上代码。本人也是初学者,出于兴趣聊做此文,在代码上未能做到尽善尽美,欢迎点评完善,期待各位高人指点。

import time
import datetime

#系数:
coeff = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
#检验码
check = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]

while True:
    ID = input('请输入身份证号:')
    if ID != 'Q':
        if len(ID) == 18:        #身份证号长度是否为18位
            if ID[0:17].isdigit():        #前17位是否为数字
                id17 = list(map(int, list(ID[0:17])))        #将前17位转换为数字列表
                if int(ID[6:10]) in range(1900, int(datetime.datetime.now().strftime('%Y')) + 1):        #判断出生年份是否在1900~当前年份之间
                    if int(ID[6:14]) <= int(datetime.datetime.now().strftime("%Y%m%d")):        #判断出生日期是否晚于当前日期
                        try:
                            time.strptime(ID[6:14], "%Y%m%d")        #判断出生日期是否为合法的日期
                            mod = sum(list(map(lambda x, y : x * y, id17, coeff))) % 11        #将身份证间17位与系数相乘后累加,最后阶以11,得到余数
                            if str(check[mod]) == ID[-1]:                #判断余数与对应的校验码是否匹配
                                print(f'\t***身份证号校验无误,性别为[{"女" if int(ID[-2]) % 2 == 0 else "男"}]***')
                            else:
                                print(f'\t身份证末位校验码不正确(应为[{check[mod]}])')                     
                        except:
                            print(f'\t出生日期[{ID[6:10]}年{ID[10:12]}月{ID[12:14]}日]不是合法的日期')
                    else:
                        print(f'\t出生日期[{ID[6:14]}]不应晚于当前日期[{datetime.datetime.now().strftime("%Y%m%d")}]')
                else:
                    print(f'\t出生年份{ID[6:10]}错误,应介于[1900--{datetime.datetime.now().strftime("%Y")}]年之间')
            else:
                print('\t身份证前17位应全部为数字')
        else:
            print('\t身份证长度应为18位')
    else:
        print('谢谢使用,再见!')
        break
    print()


QQ图片20221108202606.png
QQ图片20221108202625.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-25 17:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表