[求教] 如何在一串字符中识别出身份证号码 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
shaobo76
V2EX    Python

[求教] 如何在一串字符中识别出身份证号码

  •  
  •   shaobo76 2017-05-11 18:17:21 +08:00 7739 次点击
    这是一个创建于 3080 天前的主题,其中的信息可能已经有所发展或是发生改变。

    情况是有多条记录,每条记录由一串数字构成,在不确定的位置上出现身份证号码,身份证号只会出现一次且没有其他类似身份证号的数字串。如何通过编程的方法自动识别出身份证号的位置,用 r 或者 python 实现的话要用到什么包,请各位大侠指点,多谢。

    24 条回复    2017-05-12 15:15:35 +08:00
    okKO
        1
    okKO  
       2017-05-11 18:19:50 +08:00 via Android
    正则表达式处理这个没难度吧~
    grimpil
        2
    grimpil  
       2017-05-11 18:20:13 +08:00
    正则表达式吧
    shaobo76
        3
    shaobo76  
    OP
       2017-05-11 18:26:28 +08:00
    @okKO
    @grimpil
    正则表达式不太熟,能不能再提示一下
    zjqzxc
        4
    zjqzxc  
       2017-05-11 18:27:15 +08:00
    正则匹配 18/17 位(必要时候还需要考虑 15 位)数字

    如果不放心是否会出现干扰字符串的话,取出来的结果检验一下最后一位的校验位
    shaobo76
        5
    shaobo76  
    OP
       2017-05-11 18:34:48 +08:00 via Android
    @zjqzxc 假设这个数字串有 100 个数字构成,怎么匹配 18 位数字呢,那不是会命中很多个?
    oh
        6
    oh  
       2017-05-11 18:37:33 +08:00   6
    根据身份证号码的含义,第 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]

    简单测试了一下,可能考虑不周。
    oh
        7
    oh  
       2017-05-11 18:39:24 +08:00
    @shaobo76

    如果是在 100 个数字串里面去找 18 位身份证号码,那根据上面提取之后,最好是用身份证号码校验公式校验一次(身份证第 18 位是校验符,以此检测身份证号码的合法性),网上搜一下就有计算公式。
    kaneg
        8
    kaneg  
       2017-05-11 18:40:52 +08:00 via iPhone
    先用正则缩小范围,比如在 n 个字符串里找到 m 个候选项,然后再用程序严格的分析,比如最后的检验位是否匹配
    ynyounuo
        9
    ynyounuo  
       2017-05-11 18:45:15 +08:00
    @shaobo76
    /([1-8][0-9])\d{4}(19|20)\d{6,9}[\dXx]/
    maxmilia
        10
    maxmilia  
       2017-05-11 18:51:07 +08:00
    匹配 18 个数字,按验证的算法算算验证位合法不,哈哈哈哈哈
    maxmilia
        11
    maxmilia  
       2017-05-11 18:52:10 +08:00
    哦 不对 还有 x
    ynyounuo
        12
    ynyounuo  
       2017-05-11 18:52:10 +08:00   1
    @ynyounuo 根据 #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]/
    shaobo76
        13
    shaobo76  
    OP
       2017-05-11 19:07:27 +08:00 via Android
    谢谢大家,我去尝试一下()
    zhihaofans
        14
    zhihaofans  
       2017-05-11 20:03:24 +08:00   2
    tool.oschina.net 找到正则测试,右边有身份证的例子
    dream7758522
        15
    dream7758522  
       2017-05-11 20:11:06 +08:00 via Android
    很简单,不过我这方法可能效率不高。首先读前 18 个字符串,判断是否是身份证,然后从字符串第二位开始读 18 位字符串,判断。如此循环。文件不是很大的话,应该很简单方便。写正则的话可能还要多次验证正则表达式写的是否正确,很花时间的,与其浪费自己的时间,还不如浪费电脑的时间。
    mingyun
        16
    mingyun  
       2017-05-12 00:02:09 +08:00
    @oh nice
    geelaw
        17
    geelaw  
       2017-05-12 00:59:03 +08:00
    首先前 6 位和出生地 /户籍有关,只有有限种可能,找到这个表;
    然后是 8 位或 6 位生日,可以用求余数的方法判断年份是否是闰年,然后判断月、日的组合是否 valid ;
    然后是 3 位任意的数;
    最后是校验位,这位也可以通过前面的算出来,而且很容易(因为是前面几位线性组合求余数)。

    于是你可以画一个 NFA,然后再把它转换为正则表达式。
    JerryV2
        18
    JerryV2  
       2017-05-12 09:12:10 +08:00
    @dream7758522 正则是值得花时间练习的,不是浪费时间啊兄弟
    AyoCross
        19
    AyoCross  
       2017-05-12 09:19:34 +08:00
    +1,正则这东西需要经常练练手,否则时间长了规则就忘了
    springz
        20
    springz  
       2017-05-12 10:58:05 +08:00
    身份证号有特殊规则,正则取出符合格式的字符串,再走一遍效验就可以了
    billgreen1
        22
    billgreen1  
       2017-05-12 11:50:11 +08:00
    @geelaw 我和你想的一样,现在很多正则表达式,把一些不是身份证的也给匹配出来了
    killerv
        23
    killerv  
       2017-05-12 12:26:14 +08:00
    根据身份证号码的规则写个正则,应该没问题
    as463419014
        24
    as463419014  
       2017-05-12 15:15:35 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     934 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 19:38 PVG 03:38 LAX 12:38 JFK 15:38
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86