
用Python搞定身份证号码校验从PTA真题到实际数据清洗的完整指南在数据驱动的时代身份证号码作为个人身份的核心标识其准确性直接影响着各类系统的数据质量。无论是学生时代的PTA编程题还是职场中的Excel表格处理身份证校验都是绕不开的实用技能。本文将带你从一道经典的PTA算法题出发逐步构建可用于真实业务场景的Python数据清洗工具。1. 身份证校验算法原理解析身份证号码的最后一位校验码并非随机生成而是通过前17位数字计算得出的。这套算法源自国家标准GB 11643-1999其核心逻辑可分为三个关键步骤权重分配前17位数字分别对应固定的权重系数WEIGHTS [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]加权求和将每位数字与其对应权重相乘后累加total sum(int(digit) * weight for digit, weight in zip(id_number[:17], WEIGHTS))校验码匹配根据模11结果对应特定校验字符CHECK_CODES [1, 0, X, 9, 8, 7, 6, 5, 4, 3, 2]表权重系数与位置对应关系示例位置索引12345678权重系数791058421注意当模11结果为2时校验码应为大写字母X这是校验规则中唯一的非数字字符2. Python实现基础校验函数相比PTA原题的C语言实现Python版本可以更加简洁优雅。我们先实现一个基础验证函数def validate_id_number(id_str): if len(id_str) ! 18: return False weights [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] check_codes [1, 0, X, 9, 8, 7, 6, 5, 4, 3, 2] try: total sum(int(id_str[i]) * weights[i] for i in range(17)) return check_codes[total % 11] id_str[-1].upper() except ValueError: return False这个函数已经可以处理以下常见问题长度不足18位的情况前17位包含非数字字符的异常校验码大小写不一致的问题典型测试用例print(validate_id_number(11010519491231002X)) # True print(validate_id_number(110105194912310021)) # False print(validate_id_number(12345678901234567)) # False (长度不足) print(validate_id_number(11010519491231002x)) # True (大小写不敏感)3. 批量处理与文件操作实战实际业务中我们往往需要处理成百上千条记录。下面展示如何扩展基础函数来处理CSV文件import csv def batch_validate_ids(input_file, output_file): with open(input_file, r, encodingutf-8) as f_in, \ open(output_file, w, newline, encodingutf-8) as f_out: reader csv.reader(f_in) writer csv.writer(f_out) writer.writerow([原始身份证号, 校验结果, 错误类型]) for row in reader: id_number row[0] if not id_number.isdigit() and not id_number[:-1].isdigit(): writer.writerow([id_number, 失败, 包含非数字字符]) elif len(id_number) ! 18: writer.writerow([id_number, 失败, 长度不符]) elif not validate_id_number(id_number): writer.writerow([id_number, 失败, 校验码错误]) else: writer.writerow([id_number, 成功, ])表输出文件示例原始身份证号校验结果错误类型320124198808240056成功12010X198901011234失败包含非数字字符110108196711301866失败校验码错误提示对于大型数据集可以考虑使用pandas库提升处理效率特别是当数据量超过10万条时4. 异常处理与性能优化真实数据往往比PTA题目复杂得多。以下是几个常见问题及解决方案4.1 混合格式处理有些系统导出的数据可能包含空格、横线等特殊字符def clean_id_number(raw_id): return raw_id.strip().replace(-, ).replace( , )4.2 性能优化技巧当处理百万级数据时可以使用生成器避免内存溢出采用多进程处理适用于CPU密集型任务from multiprocessing import Pool def parallel_validate(ids_list): with Pool(processes4) as pool: return pool.map(validate_id_number, ids_list)4.3 日志记录添加详细的日志记录有助于后期分析import logging logging.basicConfig(filenameid_validation.log, levellogging.INFO) def validate_with_logging(id_str): try: result validate_id_number(id_str) logging.info(f{id_str}: {Valid if result else Invalid}) return result except Exception as e: logging.error(fError validating {id_str}: {str(e)}) return False5. 集成到实际业务系统将校验功能封装成可复用的组件可以方便地集成到各种系统中5.1 Django模型验证器from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ def validate_chinese_id(value): if not validate_id_number(value): raise ValidationError( _(%(value)s 不是有效的身份证号码), params{value: value}, )5.2 Flask API端点from flask import Flask, request, jsonify app Flask(__name__) app.route(/validate-id, methods[POST]) def validate_id_api(): data request.get_json() id_number data.get(id_number, ) return jsonify({ valid: validate_id_number(id_number), normalized: clean_id_number(id_number) })5.3 Excel插件开发使用xlwings库为Excel添加校验功能import xlwings as xw xw.func def validate_excel_id(id_cell): return 有效 if validate_id_number(str(id_cell)) else 无效在实际项目中我发现最常出现的问题不是校验算法本身而是数据录入时的各种意外情况。比如有一次处理用户提交数据时发现有人误将字母O当作数字0输入这类特殊情况就需要在基础校验之外添加额外的规则检查。