日常练习-利用python的random模块模拟身份证号码

前段时间做了一个数据库的课设,其中初始身份证号码数据的导入引起了我的思考,于是下面的身份证号生成代码便诞生了:

  1 import csv
  2 import os
  3 import random
  4 
  5 
  6 # 1、前1、2位数字代表所省份代码;
  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 
 24 class CreateIdCardNumber:
 25     """生成身份证号码"""
 26 
 27     def __init__(self, numbers=200):
 28         # 用来存放要生成的身份证号的数量
 29         self.numbers = numbers
 30         # 用来存放生成的身份证号码
 31         self.id_card_numbers = []
 32 
 33     @staticmethod
 34     def get_administrative_division_code():
 35         """获取行政区划编码"""
 36         # 拼接文件的地址
 37         filename = os.path.dirname(
 38             os.path.realpath(__file__)) + '/行政区划代码.csv'
 39         # 读取行政区划编码的csv文件
 40         with open(filename, 'r', encoding='UTF-8') as f:
 41             reader = csv.reader(f)
 42             # 存放行政区划编码
 43             administrative_division_codes = []
 44             # 逐一遍历,不存在就跳过,存在就加入
 45             for row in reader:
 46                 try:
 47                     number = row[0]
 48                 except ValueError:
 49                     print(f"Missing data {row[1]}")
 50                 else:
 51                     administrative_division_codes.append(number)
 52         # 将行政区划编码列表返回去
 53         return administrative_division_codes[1:]
 54 
 55     @staticmethod
 56     def year_month_day():
 57         # 用来存放生成的年月日
 58         year_month_day = []
 59         # 生成500个日期
 60         number = 500
 61         while number != 0:
 62             # 随机生成年月
 63             year = str(random.randint(1990, 2000))
 64             month = str(random.randint(1, 12)).zfill(2)
 65             # 根据月份确定天的随机数
 66             if month in ['01', '03', '05', '07', '08', '10', '12']:
 67                 day = str(random.randint(1, 31)).zfill(2)
 68             elif month in ['04', '06', '09', '11']:
 69                 day = str(random.randint(1, 30)).zfill(2)
 70             else:
 71                 day = str(random.randint(1, 29)).zfill(2)
 72             # 临时存放生成的年月日,好用于后面的判断
 73             result = year + month + day
 74             if result not in year_month_day:
 75                 year_month_day.append(result)
 76                 number -= 1
 77         # 将年月日列表返回
 78         return year_month_day
 79 
 80     @staticmethod
 81     def sequence_code():
 82         # 用来存放生成的顺序码
 83         sequence_code = []
 84         # 生成500个顺序码
 85         number = 500
 86         while number != 0:
 87             # 直接对1000进行取随机值
 88             # 临时存放随机值,好用于后面的判断
 89             result = str(random.randint(0, 1000)).zfill(3)
 90             if result not in sequence_code:
 91                 sequence_code.append(result)
 92                 number -= 1
 93         # 将生成的顺序码返回
 94         return sequence_code
 95 
 96     def check_code(self):
 97         # 通过调用前面的函数生成17个字符的字符串
 98         digits = random.choices(self.get_administrative_division_code())[0] + 
 99                  random.choices(
100                      self.year_month_day())[0] + 
101                  random.choices(self.sequence_code())[0]
102         # 根据ISO 7064:1983.MOD 11-2校验码算法
103         # 要用不足补0,应为可能为空
104         try:
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
123         except Exception as f:
124             # 出错了就将错误信息打印出来
125             print(f)
126         else:
127             # 如果校验码是10就转换为x,其他的就去其数值
128             check_code = str(
129                 temporary_check_code) if temporary_check_code != 10 else 'x'
130             # 将生成的以为校验码返回
131             return check_code
132 
133     def create_id_card_number(self):
134         """生成身份证号码"""
135         # 在给定的数内循环
136         while self.numbers != 0:
137             # 临时存放生成的身份证号码,好用于后面的判断
138             result = random.choices(self.get_administrative_division_code())[
139                          0] + random.choices(self.year_month_day())[0] + 
140                      random.choices(
141                          self.sequence_code())[0] + self.check_code()
142             # 判断,存在就跳过,否者就加入
143             if result not in self.id_card_numbers:
144                 self.id_card_numbers.append(result)
145                 self.numbers -= 1
146         # 将生成的身份证号码返回
147         return self.id_card_numbers
148 
149 
150 if __name__ == '__main__':
151     print(CreateIdCardNumber(100).create_id_card_number())

行政区划代码:https://files.cnblogs.com/files/wz46265381/%E8%A1%8C%E6%94%BF%E5%8C%BA%E5%88%92%E4%BB%A3%E7%A0%81.7z

原文地址:https://www.cnblogs.com/wz46265381/p/15339542.html