轉自:
https://blog.csdn.net/warrah/article/details/69338912
https://blog.csdn.net/qq_37142340/article/details/80695187
https://blog.csdn.net/u013361668/article/details/51595169
https://blog.csdn.net/feiyunw/article/details/83190319
import re class UnifiedSocialCreditIdentifier(object): ''' 統一社會信用代碼 + 組織結構代碼校驗 ''' def __init__(self): ''' Constructor ''' # 統一社會信用代碼中不使用I,O,S,V,Z # ''.join([str(i) for i in range(10)]) # import string # string.ascii_uppercase # ascii_lowercase | ascii_letters # dict([i for i in zip(list(self.string), range(len(self.string)))]) # dict(enumerate(self.string)) # list(d.keys())[list(d.values()).index(10)] # chr(97) --> 'a' self.string1 = '0123456789ABCDEFGHJKLMNPQRTUWXY' self.SOCIAL_CREDIT_CHECK_CODE_DICT = { '0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9, 'A':10,'B':11,'C':12, 'D':13, 'E':14, 'F':15, 'G':16, 'H':17, 'J':18, 'K':19, 'L':20, 'M':21, 'N':22, 'P':23, 'Q':24, 'R':25, 'T':26, 'U':27, 'W':28, 'X':29, 'Y':30} # 第i位置上的加權因子 self.social_credit_weighting_factor = [1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28] # GB11714-1997全國組織機構代碼編制規則中代碼字符集 self.string2 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' self.ORGANIZATION_CHECK_CODE_DICT = { '0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9, 'A':10,'B':11,'C':12, 'D':13, 'E':14, 'F':15, 'G':16, 'H':17,'I':18, 'J':19, 'K':20, 'L':21, 'M':22, 'N':23, 'O':24,'P':25, 'Q':26, 'R':27,'S':28, 'T':29, 'U':30,'V':31, 'W':32, 'X':33, 'Y':34,'Z':35} # 第i位置上的加權因子 self.organization_weighting_factor = [3,7,9,10,5,8,4,2] def check_social_credit_code(self, code): ''' 統一社會信用代碼校驗 國家標准GB32100—2015:18位統一社會信用代碼從2015年10月1日正式實行, 標准規定統一社會信用代碼用18位阿拉伯數字或大寫英文字母(不使用I、O、Z、S、V)表示, 分別是1位登記管理部門代碼、1位機構類別代碼、6位登記管理機關行政區划碼、9位主體標識碼(組織機構代碼)、1位校驗碼 稅號 = 6位行政區划碼 + 9位組織機構代碼 計算校驗碼公式: C18 = 31-mod(sum(Ci*Wi),31) 其中Ci為組織機構代碼的第i位字符,Wi為第i位置的加權因子,C18為校驗碼 c18=30, Y; c18=31, 0 ''' # 主要是避免缺失值亂入 #if type(code) != str: return False # 轉大寫 code = code.upper() # 1. 長度限制 if len(code) != 18: print('{} -- 統一社會信用代碼長度不等18!'.format(code)) return False # 2. 不含IOSVZ -- 組成限制, 非字典表給個非常大的數, 不超過15000 '''lst = list('IOSVZ') for s in lst: if s in code: print('包含非組成字符:%s' % (s)) return False''' # 2. 組成限制 # 登記管理部門:1=機構編制; 5=民政; 9=工商; Y=其他 # 機構類別代碼: ''' 機構編制=1:1=機關 | 2=事業單位 | 3=中央編辦直接管理機構編制的群眾團體 | 9=其他 民政=5:1=社會團體 | 2=民辦非企業單位 | 3=基金會 | 9=其他 工商=9:1=企業 | 2=個體工商戶 | 3=農民專業合作社 其他=Y:1=其他 ''' reg = r'^(11|12|13|19|51|52|53|59|91|92|93|Y1)\d{6}\w{9}\w$' if not re.match(reg, code): print('{} -- 組成錯誤!'.format(code)) return False # 3. 校驗碼驗證 # 本體代碼 ontology_code = code[:17] # 校驗碼 check_code = code[17] # 計算校驗碼 tmp_check_code = self.gen_check_code(self.social_credit_weighting_factor, ontology_code, 31, self.SOCIAL_CREDIT_CHECK_CODE_DICT) if tmp_check_code == -1: print('{} -- 包含非組成字符!'.format(code)) return False tmp_check_code = (0 if tmp_check_code==31 else tmp_check_code) if self.string1[tmp_check_code] == check_code: #print('{} -- 統一社會信用代碼校驗正確!'.format(code)) return True else: print('{} -- 統一社會信用代碼校驗錯誤!'.format(code)) return False def check_organization_code(self, code): ''' 組織機構代碼校驗 該規則按照GB 11714編制:統一社會信用代碼的第9~17位為主體標識碼(組織機構代碼),共九位字符 計算校驗碼公式: C9 = 11-mod(sum(Ci*Wi),11) 其中Ci為組織機構代碼的第i位字符,Wi為第i位置的加權因子,C9為校驗碼 C9=10, X; C9=11, 0 @param code: 統一社會信用代碼 / 組織機構代碼 ''' # 主要是避免缺失值亂入 #if type(code) != str: return False # 1. 長度限制 if len(code) != 9: print('{} -- 組織機構代碼長度不等9!'.format(code)) return False # 2. 組成限制 reg = r'^\w{9}$' if not re.match(reg, code): print('{} -- 組成錯誤!'.format(code)) return False # 3. 校驗碼驗證 # 本體代碼 ontology_code = code[:8] # 校驗碼 check_code = code[8] # 計算校驗碼 tmp_check_code = self.gen_check_code(self.organization_weighting_factor, ontology_code, 11, self.ORGANIZATION_CHECK_CODE_DICT) if tmp_check_code == -1: print('{} -- 包含非組成字符!'.format(code)) return False tmp_check_code = (0 if tmp_check_code==11 else (33 if tmp_check_code==10 else tmp_check_code)) if self.string2[tmp_check_code] == check_code: #print('{} -- 組織機構代碼校驗正確!'.format(code)) return True else: print('{} -- 組織機構代碼校驗錯誤!'.format(code)) return False def check_code(self, code, code_type='sc'): '''Series類型 @code_type {org, sc}''' #try: if type(code) != str: return False if code_type == 'sc': return self.check_social_credit_code(code) elif code_type == 'org': return self.check_organization_code(code) else: if len(code)==18: return self.check_social_credit_code(code) else: return self.check_organization_code(code) if len(code)==9 else False #except Exception as err: # print(err) # print('code:', code) def gen_check_code(self, weighting_factor, ontology_code, modulus, check_code_dict): ''' @param weighting_factor: 加權因子 @param ontology_code:本體代碼 @param modulus: 模數(求余用) @param check_code_dict: 字符字典 ''' total = 0 for i in range(len(ontology_code)): if ontology_code[i].isdigit(): #print(ontology_code[i], weighting_factor[i]) total += int(ontology_code[i]) * weighting_factor[i] else: num = check_code_dict.get(ontology_code[i], -1) if num < 0: return -1 total += num * weighting_factor[i] diff = modulus - total % modulus #print(diff) return diff if __name__ == '__main__': # 統一社會信用代碼及組織機構代碼校驗 u = UnifiedSocialCreditIdentifier() print(u.check_social_credit_code(code='91330382575324831A')) print(u.check_organization_code(code='575324831'))