解析身份z号码(Python版)

解析身份z号码(Python版),第1张

解析身份z号码(Python版)

解析身份z号码(Python版)
  • 简单分析
    • 结构
      • 六位数字地址码
      • 八位数字出生日期码
      • 三位数字顺序码
      • 一位数字校验码
  • 代码实现
    • 获取身份z号里的信息
    • 获取身份z中的省份
    • 计算身份z校验位
    • 验证并提取信息

简单分析 结构

我国的居民身份z号码是特征组合码,由十七位数字本体码和一位校验码组成。
排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

六位数字地址码

第一、二位表示省级行政区。
第一位数字是以前的大区制代码。第二位是大区所在省市编码。

  1. 华北三省二市
  2. 东北三省
  3. 华东六省一市
  4. 华南六省
  5. 西南四省一市
  6. 西北五省
  7. 台湾省
  8. 香港澳门

具体省(直辖市,自治区,特别行政区)编码如下

  • 11~15 京津冀晋蒙
  • 21~23 辽吉黑
  • 31~37 沪苏浙皖闽赣鲁
  • 41~46 豫鄂湘粤桂琼
  • 50~54 渝川贵云藏
  • 61~65 陕甘青宁新
  • 71 台湾
  • 81~82 港澳

记不住省份简称的可以跳过去看看
https://blog.csdn.net/qq_55342245/article/details/113815397

第三、四位表示地级行政区。01一般表示本省省会

就像车牌,A表示本省省会,B一般是本省的二线城市
辽A是沈阳 辽B是大连,黑A是哈尔滨 黑B是齐齐哈尔,川A是成都 川B是绵阳,云A是昆明 云南没有B的牌照

第五、六位表示县级行政区。01一般表示本市市辖区

210101辽宁省沈阳市市辖区 210201辽宁省大连市市辖区
230101黑龙江省哈尔滨市市辖区 230201黑龙江省齐齐哈尔市市辖区
510101四川省成都市市辖区 510701四川省绵阳市市辖区

八位数字出生日期码

(身份z号码第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

三位数字顺序码

(身份z号码第十五位到十七位)表示在同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。(我国古代,奇数为阳,偶数为阴)

一位数字校验码

根据前面十七位数字码,按按一定规则计算出来。
公式:最后一位 = ( 12 − ∑ i = 2 18 a i w i m o d 11 ) m o d 11 = ( 12- sum_{i=2}^{18}a_{i}w_{i} mod 11) mod11 =(12−∑i=218​ai​wi​mod11)mod11

mod 是取余数的意思。 例(36 mod 5)=1, (46 mod 8)=6
ai 是从右往左数第i位,加权因子wi = 2(i-1) mod 11
身份z是18位,所以a2是倒数第二位,正数第17位

因为最后一位是除以11取余数得到,就有0~10这十一种情况,那么就得用X(X是罗马数字的10)来代替10,因为如果用10做尾号,那么此人的身份z就变成了19位,而19位的号码违反了国家标准。

十八位身份z还可以用这个公式验证: ∑ i = 1 18 a i w i ≡ 1 ( m o d 11 ) sum_{i=1}^{18}a_{i}w_{i} equiv 1 ( mod 11) ∑i=118​ai​wi​≡1(mod11)

“ ≡ equiv ≡ ”是同余符号。
例:
16 ≡ equiv ≡ 11 ( mod 5) 16除以5=3…1 11除以5=2…1 余数都是1
25 ≡ equiv ≡ 3 ( mod 11) 25除以11=2…3 3除以11=0…3 余数都是3

这个公式的另一种写法是: ( ∑ i = 1 18 a i w i ) m o d 11 = 1 ( sum_{i=1}^{18}a_{i}w_{i}) mod 11 = 1 (∑i=118​ai​wi​)mod11=1

安利几个千年难遇的身份z号(虽然合法,但不一定真实存在。如有冒犯请评论删除)
这些身份z是有意义的。但形成这样的身份z号,必须是公安机关分配给你的顺序码由0和2组成,而且0和2的还得有一个正确的搭配顺序
有兴趣的还可以自己多找几个
220202200002022002 吉林省吉林市昌邑区2000年2月2日出生的女孩
220202200002200200 吉林省吉林市昌邑区2000年2月20日出生的女孩
220202202002020022 吉林省吉林市昌邑区2020年2月2日出生的女孩
220202202002022220 吉林省吉林市昌邑区2020年2月2日出生的女孩
220202202002202002 吉林省吉林市昌邑区2020年2月20日出生的女孩

def doVerify(id):
    sum = 0
    # 身份z的前十七位分别乘以相应的加权因子
    wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    for i in range(17):
        sum += int(id[i]) * wi[i]
    j = sum%11
    # 根据余数去匹配对应的数字
    rem = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
    # print("校验码是:" + rem[j])
    if id[17]==rem[j]:
        return True
    else:
        return False

li = []

area = '220202'
year = ['2000','2002','2020','2022']
month = '02'
day = ['02','20','22']
num = ['002','020','022','200','202','220','222']
mo = ['0','2']

for y in year:
    for d in day:
        for n in num:
            for m in mo:
                id = area + y + month + d + n + m
                if doVerify(id):
                    li.append(id)

print(li)
print(len(li))
代码实现 获取身份z号里的信息
def getInfo(s):
    area = s[0:6]
    year = s[6:10]
    month = s[10:12]
    day = s[12:14]
    num = s[14:17]
    checkCode = s[17]

    print("地区码:" + area)
    print(f"出生日期:{year}年{month}月{day}日")
    print("顺序码:" + num)
    print("校验码:" + checkCode)
    print("性别:女") if int(num) % 2 == 0 else print("性别:男")


id = '510107199806186520'
getInfo(id)
获取身份z中的省份
def getArea(s):
    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":"澳门特别行政区"}

    if s[0:2] in area.keys():
        print(area[s[0:2]])
    else:
        print('地区码无效')

id = '510107199806186520'
getArea(id)
计算身份z校验位

简单的

# (简单)
def doVerify(id):
    sum = 0
    # 身份z的前十七位分别乘以相应的加权因子
    wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    # 根据余数去匹配对应的数字
    rem = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']

    for i in range(17):
        sum += int(id[i]) * wi[i]
    print("校验码是:" + rem[sum%11] )

id = '11223223239811110'
doVerify(id)

专业的
公式: a 1 = ( 12 − ∑ i = 2 18 m o d 11 ) m o d 11 a_{1}= ( 12- sum_{i=2}^{18} mod 11) mod11 a1​=(12−∑i=218​mod11)mod11

def Judge(id):
    sum = 0
    for i in range(17):
        # 加权因子wi = 2^(i-1) mod 11  i从右往左数
        # 也就是w1 = (2^17) % 11,w2 = (2^16) % 11,w17 = (2^1) % 11
        wi = 1
        wi <<= 17-i # 左移,这里相当于乘以2的(17-i)次方
        wi %= 11    # 计算得到最终的加权因子

        sum += int(id[i]) * wi
    print(f"校验码是:{(12-sum%11)%11}")

id = '9153455276589485465110'
Judge(id)

验证并提取信息
import datetime
now = datetime.datetime.now()
now = str(now)


# 判断身份z号检验码
def Judge(id):
    sum = 0
    for i in range(17):
        # 加权因子wi = 2^(i-1) mod 11  i从右往左数
        # 也就是w1 = (2^17) % 11,w2 = (2^16) % 11,w17 = (2^1) % 11
        wi = 1
        wi <<= 17-i # 左移,这里相当于乘以2的(17-i)次方
        wi %= 11    # 计算得到最终的加权因子
        sum += int(id[i]) * wi
    mo = (12-sum%11)%11
    if id[17] == str(mo) or ((id[17]=='x' or id[17]=='X') and mo==10):
        return True


# 判断身份证号地区码
def Area(id):
    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":"澳门特别行政区"}
    if id[0:2] in area.keys():
        return area[id[0:2]]
    else:
        return ''


# 判断时间是否合法
def Year(id):
    y = int(id[6:10])
    if y>=1840 and y<=int(now[0:4]):
        return True
    else:
        return False

def Month(id):
    m = int(id[10:12])
    if m>=1 and m<=12:
        return True
    else:
        return False

def Day(id):
    y = int(id[6:10])
    m = int(id[10:12])
    d = int(id[12:14])
    if m >= 1 and m <= 12:
        if m in [1,3,5,7,8,10,12]:
            if d>=1 and d<=31:
                return True
        if m in [4,6,9,11]:
            if d>=1 and d<=30:
                return True
        if m==2:
            if y%4==0 and y%100!=0 or y%400==0:
                if d>=1 and d<=29:
                    return True
            else:
                if d>=1 and d<=28:
                    return True
    else:
        return False


if __name__ == '__main__':
    id = '220202200002022002'
    id = '220202202002022220'
    area = Area(id)
    if len(id)==18 and id[:17].isdigit() and Judge(id) and len(area)!=0 and Year(id) and Month(id) and Day(id):
        print("身份证号有效")
        print(f"地区码:{id[0:6]},属于{area}")
        print(f"出生日期:{id[6:10]}年{id[10:12]}月{id[12:14]}日")
        print("顺序码:" + id[14:17])
        print("校验码:" + id[17])
        print("性别:女") if int(id[16]) % 2 == 0 else print("性别:男")
    else:
        print('输入有误,该身份证不合法。。。')

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5521830.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-13
下一篇2022-12-13

发表评论

登录后才能评论

评论列表(0条)

    保存