⽇常练习-利⽤python的random模块模拟⾝份证号码
前段时间做了⼀个数据库的课设,其中初始⾝份证号码数据的导⼊引起了我的思考,于是下⾯的⾝份证号⽣成代码便诞⽣了: 1import csv
2import os
3import random
4
5
7# 2、第3、4位数字代表所城市代码;
8# 3、第5、6位数字代表所区县代码;
9# 4、第7~14位数字代表的是第7,8,9,10位为出⽣年份,第11.12位代表出⽣⽉份,第13,14位代表出⽣⽇期;
10# 5、第15~17位是顺序码。同⼀地址码所标识的区域范围内,对同年、⽉、⽇出⽣的⼈员编定的顺序号。其中第⼗七位奇数分给男性,偶数分给⼥性。
11# 6、第18位数字为校检码:校检码0~9数字,10⽤X表⽰。这是根据前⾯⼗七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。 12# ISO 7064:1983.MOD 11-2校验码的例⼦:
13# 假设某⼀17位数字是
14# 17位数字 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
15# 加权因⼦ 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
16# 计算17位数字各位数字与对应的加权因⼦的乘积的和S:1×7+2×9+3×10+4×5+5×8+6×4+7×2+8×1+9×6+0×3+1×7+2×9+3×10+4×5+5×8+6×4+7×2=368;
17# 计算S÷11的余数T:368 mod 11=5;
18# (( 余数0-10对应校验码为[1, 0, X , 9, 8, 7, 6, 5, 4, 3, 2],算法如下 ))
19# 计算(12-T)÷11的余数R,如果R=10,校验码为字母“X”;如果R≠10,校验码为数字“R”:(12-5)mod 11=7。
20# 该17位数字的校验码就是7,聚合在⼀为123456789012345677。
21
22# 假设职⼯的⽣⽇在1990.1.1——2000.1.1
23
24class CreateIdCardNumber:
25"""⽣成⾝份证号码"""
26
27def__init__(self, numbers=200):
28# ⽤来存放要⽣成的⾝份证号的数量
29 self.numbers = numbers
30# ⽤来存放⽣成的⾝份证号码
31 self.id_card_numbers = []
32
33 @staticmethod
34def get_administrative_division_code():
36# 拼接⽂件的地址
37 filename = os.path.dirname(
38 alpath(__file__)) + '/⾏政区划代码.csv'
39# 读取⾏政区划编码的csv⽂件
40 with open(filename, 'r', encoding='UTF-8') as f:
41 reader = ader(f)
42# 存放⾏政区划编码
43 administrative_division_codes = []
44# 逐⼀遍历,不存在就跳过,存在就加⼊
45for row in reader:
46try:
47 number = row[0]
48except ValueError:
49print(f"Missing data {row[1]}")
50else:
51 administrative_division_codes.append(number)
52# 将⾏政区划编码列表返回去
53return administrative_division_codes[1:]
54
55 @staticmethod
56def year_month_day():
57# ⽤来存放⽣成的年⽉⽇
58 year_month_day = []
59# ⽣成500个⽇期
60 number = 500
61while number != 0:
62# 随机⽣成年⽉
63 year = str(random.randint(1990, 2000))
64 month = str(random.randint(1, 12)).zfill(2)
65# 根据⽉份确定天的随机数
66if month in ['01', '03', '05', '07', '08', '10', '12']:
67 day = str(random.randint(1, 31)).zfill(2)
68elif month in ['04', '06', '09', '11']:
69 day = str(random.randint(1, 30)).zfill(2)
70else:
71 day = str(random.randint(1, 29)).zfill(2)
72# 临时存放⽣成的年⽉⽇,好⽤于后⾯的判断
73 result = year + month + day
74if result not in year_month_day:
75 year_month_day.append(result)
76 number -= 1
77# 将年⽉⽇列表返回
78return year_month_day
79
80 @staticmethod
81def sequence_code():
82# ⽤来存放⽣成的顺序码
83 sequence_code = []
84# ⽣成500个顺序码
85 number = 500
86while number != 0:
87# 直接对1000进⾏取随机值
88# 临时存放随机值,好⽤于后⾯的判断
89 result = str(random.randint(0, 1000)).zfill(3)
90if result not in sequence_code:
91 sequence_code.append(result)
92 number -= 1
93# 将⽣成的顺序码返回
94return sequence_code
95
96def check_code(self):
97# 通过调⽤前⾯的函数⽣成17个字符的字符串
98 digits = random._administrative_division_code())[0] + \
99 random.choices(
100 ar_month_day())[0] + \
101 random.choices(self.sequence_code())[0]
102# 根据ISO 7064:1983.MOD 11-2校验码算法
103# 要⽤不⾜补0,应为可能为空
104try:
105 temporary_check_code = (12 - (
106 int(digits[0:1].zfill(1)) * 7 + int(
107 digits[1:2].zfill(1)) * 9 + int(
108 digits[2:3].zfill(1)) * 10 + int(
109 digits[3:4].zfill(1)) * 5 + int(
110 digits[4:5].zfill(1)) * 8 + int(
111 digits[5:6].zfill(1)) * 4 + int(
112 digits[6:7].zfill(1)) * 2 + int(
113 digits[7:8].zfill(1)) * 1 + int(
114 digits[8:9].zfill(1)) * 6 + int(
115 digits[9:10].zfill(1)) * 3 + int(
116 digits[10:11].zfill(1)) * 7 + int(
117 digits[11:12].zfill(1)) * 9 + int(
118 digits[12:13].zfill(1)) * 10 + int(
119 digits[13:14].zfill(1)) * 5 + int(
120 digits[14:15].zfill(1)) * 8 + int(
121 digits[15:16].zfill(1)) * 4 + int(
122 digits[16:17].zfill(1)) * 2) % 11) % 11
123except Exception as f:
124# 出错了就将错误信息打印出来
125print(f)
126else:
127# 如果校验码是10就转换为x,其他的就去其数值
128 check_code = str(
129 temporary_check_code) if temporary_check_code != 10 else'x' 130# 将⽣成的以为校验码返回
131return check_code
132
133def create_id_card_number(self):
134"""⽣成⾝份证号码"""
135# 在给定的数内循环
136while self.numbers != 0:
137# 临时存放⽣成的⾝份证号码,好⽤于后⾯的判断
138 result = random._administrative_division_code())[ 139 0] + random.ar_month_day())[0] + \
140 random.choices(
141 self.sequence_code())[0] + self.check_code()
142# 判断,存在就跳过,否者就加⼊
143if result not in self.id_card_numbers:
144 self.id_card_numbers.append(result)
145 self.numbers -= 1
146# 将⽣成的⾝份证号码返回
147return self.id_card_numbers
148
149
150if__name__ == '__main__':
151print(CreateIdCardNumber(100).create_id_card_number())