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