前段時間做了一個數據庫的課設,其中初始身份證號碼數據的導入引起了我的思考,於是下面的身份證號生成代碼便誕生了:
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