Python中如何在一串字符中识别出身份证号码
情况是有多条记录,每条记录由一串数字构成,在不确定的位置上出现身份证号码,身份证号只会出现一次且没有其他类似身份证号的数字串。如何通过编程的方法自动识别出身份证号的位置,用 r 或者 python 实现的话要用到什么包,请各位大侠指点,多谢。
Python中如何在一串字符中识别出身份证号码
正则表达式处理这个没难度吧~
要在一串字符里识别身份证号码,可以用正则表达式。身份证号码有18位和15位两种格式,18位的最后一位可能是数字或X。下面这个正则能匹配两种格式,并且会检查前6位(地址码)、中间8位(出生日期,对18位)或6位(对15位)、顺序码和校验位(对18位)。
import re
def extract_id_numbers(text):
"""
从文本中提取身份证号码。
参数:
text (str): 输入的文本字符串
返回:
list: 找到的所有身份证号码列表
"""
# 匹配18位身份证号码,最后一位可以是数字或X(大小写均可)
pattern_18 = r'\b[1-9]\d{5}(?:19|20)\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{3}[\dXx]\b'
# 匹配15位身份证号码
pattern_15 = r'\b[1-9]\d{7}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])\d{2}\b'
# 合并两个模式
pattern = f'({pattern_18})|({pattern_15})'
# 查找所有匹配
matches = re.findall(pattern, text)
# 处理匹配结果(findall返回的是元组列表)
id_numbers = []
for match in matches:
# match是元组,包含两个组:18位和15位
id_num = match[0] or match[1]
if id_num:
id_numbers.append(id_num.upper()) # 统一转为大写
return id_numbers
# 测试示例
if __name__ == "__main__":
test_text = """
我的身份证是110101199003077516,我朋友的旧身份证是110101900307751。
另一个号码是440524188001010014X,还有乱入的123456789012345678。
测试15位:330102800101123,18位带x:11010119900307751X。
"""
ids = extract_id_numbers(test_text)
print("找到的身份证号码:")
for id_num in ids:
print(f"- {id_num}")
这个正则做了这些事:
\b匹配单词边界,避免匹配到更长的数字串[1-9]\d{5}匹配6位地址码,首位不能是0(?:19|20)\d{2}匹配年份(1900-2099)(?:0[1-9]|1[0-2])匹配月份(01-12)(?:0[1-9]|[12]\d|3[01])匹配日期(01-31)\d{3}[\dXx]匹配3位顺序码+1位校验码(数字或X)- 15位的模式类似,只是少了年份的"19"和最后一位校验码
注意这只能做格式校验,真要严格验证还得算校验码。不过日常文本里找身份证号这够用了。
总结:用正则匹配身份证格式就行。
正则表达式吧
正则表达式不太熟,能不能再提示一下
正则匹配 18/17 位(必要时候还需要考虑 15 位)数字
如果不放心是否会出现干扰字符串的话,取出来的结果检验一下最后一位的校验位
假设这个数字串有 100 个数字构成,怎么匹配 18 位数字呢,那不是会命中很多个?
根据身份证号码的含义,第 7-14 是生日,那基本可以确定:
- 第 7 位要么是 1 要么是 2 ( 1xxx 年 - 2xxx 年);
- 第 11 位要么是 0 要么是 1 ( 0x 月 - 1x 月);
- 第 13 位的范围是 0 - 3 ( 0x 日 - 3x 日);
- 第 18 位除了是数字还有可能是 X ;
有了这几个限定位,很大程度上可以避免干扰了(当然要根据具体的内容而定,如果是几百几千个数字里面去找出 18 位身份证,那就不成立了)。
正则大概可以写为: \d{6}[1-2]\d{3}[0-1]\d[0-3]\d{4}[0-9xX]
简单测试了一下,可能考虑不周。
如果是在 100 个数字串里面去找 18 位身份证号码,那根据上面提取之后,最好是用身份证号码校验公式校验一次(身份证第 18 位是校验符,以此检测身份证号码的合法性),网上搜一下就有计算公式。
先用正则缩小范围,比如在 n 个字符串里找到 m 个候选项,然后再用程序严格的分析,比如最后的检验位是否匹配
/([1-8][0-9])\d{4}(19|20)\d{6,9}[\dXx]/
匹配 18 个数字,按验证的算法算算验证位合法不,哈哈哈哈哈
哦 不对 还有 x
根据 #6 改了一下
/([1-8][0-9])\d{4}(19|20)(\d{2})(0?[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])(\d{3})[\dXx]/
谢谢大家,我去尝试一下(•̀⌄•́)
tool.oschina.net 找到正则测试,右边有身份证的例子
很简单,不过我这方法可能效率不高。首先读前 18 个字符串,判断是否是身份证,然后从字符串第二位开始读 18 位字符串,判断。如此循环。文件不是很大的话,应该很简单方便。写正则的话可能还要多次验证正则表达式写的是否正确,很花时间的,与其浪费自己的时间,还不如浪费电脑的时间。
nice
首先前 6 位和出生地 /户籍有关,只有有限种可能,找到这个表;
然后是 8 位或 6 位生日,可以用求余数的方法判断年份是否是闰年,然后判断月、日的组合是否 valid ;
然后是 3 位任意的数;
最后是校验位,这位也可以通过前面的算出来,而且很容易(因为是前面几位线性组合求余数)。
于是你可以画一个 NFA,然后再把它转换为正则表达式。
正则是值得花时间练习的,不是浪费时间啊兄弟
+1,正则这东西需要经常练练手,否则时间长了规则就忘了
身份证号有特殊规则,正则取出符合格式的字符串,再走一遍效验就可以了
我和你想的一样,现在很多正则表达式,把一些不是身份证的也给匹配出来了
根据身份证号码的规则写个正则,应该没问题


