有这样的需求,人员信息是存在mongodb中,需要存放人员的身份证、性别、出生日期、籍贯等信息。通过脚本导入这些信息,但是只导入了身份证号码,其他信息空缺。现在需要补全其他信息。

  其实身份证信息就包含了性别、出生日期、籍贯信息。公民身份号码是特征组合码,由前十七位数字本体码和最后一位数字校验码组成。排列顺序从左至右依次为六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码

  地址码: 表示编码对象常住户口所在县(市、旗、区)的行政区划代码。

  出生日期码:表示编码对象出生的年、月、日,年、月、日代码之间不用分隔符,格式为YYYYMMDD,如19880328。

  顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

  校验码: 根据本体码,通过采用ISO 7064:1983,MOD 11-2校验码系统计算出校验码。前面有提到数字校验码,我们知道校验码也有X的,实质上为罗马字符X,相当于10.

  实现思路很简单了,就是得到所有有身份证号码等纪录,解析身份证号码,获取性别、出生日期、籍贯信息,再更新mongodb。

想到了两种技术方案解决:python脚本和JavaScript。

1、python脚本

  python需要使用pymongo,用于操作mongodb,需要引入。python代码直接在终端执行就行。python test.py

 # encoding=utf-8

 '''
Created on 2017年12月22日
mongodb中存放人像信息,有身份证号码,无性别、籍贯、出生日期,需要根据mongodb中身份证字段,获取性别、籍贯、出生日期,更新到mongodb中 @author: tim
''' import re
from pymongo import MongoClient #需要引入pymongo,用于连接mongodb
from datetime import datetime logPath = "/Users/tim/updatemongo/log/log.txt" #日志 #身份证前两位代表的省市,作为籍贯
area = {"":"北京", "":"天津", "":"河北", "":"山西", "":"内蒙古", "":"辽宁", "":"吉林", "":"黑龙江", "":"上海", "":"江苏", "":"浙江", "":"安徽", "":"福建", "":"江西", "":"山东", "":"河南", "":"湖北", "":"湖南", "":"广东", "":"广西", "":"海南", "":"重庆", "":"四川", "":"贵州", "":"云南", "":"西藏", "":"陕西", "":"甘肃", "":"青海", "":"宁夏", "":"新疆", "":"台湾", "":"香港", "":"澳门", "":"国外"} # 身份证有效性校验
def checkIdcard(idcard):
Messages = ['验证通过!', '身份证号码位数不对!', '身份证号码出生日期超出范围或含有非法字符!', '身份证号码校验错误!', '身份证地区非法!'] idcard = str(idcard) #身份证号码转成字符串
idcard = idcard.strip() #移除字符串头尾指定的字符(默认为空格)
idcard_list = list(idcard) #转成列表 # 地区校验
if(not area[(idcard)[0:2]]):
return Messages[4] # 15位身份号码检测
if(len(idcard) == 15):
if((int(idcard[6:8]) + 1900) % 4 == 0 or((int(idcard[6:8]) + 1900) % 100 == 0 and (int(idcard[6:8]) + 1900) % 4 == 0)):
ereg = re.compile('[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$')
else:
ereg = re.compile('[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$') # 测试出生日期的合法性
if(re.match(ereg, idcard)):
return Messages[0]
else:
return Messages[2] # 18位身份号码检测
elif(len(idcard) == 18):
# 出生日期的合法性检查
# 闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
# 平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
if(int(idcard[6:10]) % 4 == 0 or (int(idcard[6:10]) % 100 == 0 and int(idcard[6:10]) % 4 == 0)):
ereg = re.compile('[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$') # //闰年出生日期的合法性正则表达式
else:
ereg = re.compile('[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$') # //平年出生日期的合法性正则表达式 # 测试出生日期的合法性
if(re.match(ereg, idcard)):
# 计算校验位
S = (int(idcard_list[0]) + int(idcard_list[10])) * 7 + (int(idcard_list[1]) + int(idcard_list[11])) * 9 + (int(idcard_list[2]) + int(idcard_list[12])) * 10 + (int(idcard_list[3]) + int(idcard_list[13])) * 5 + (int(idcard_list[4]) + int(idcard_list[14])) * 8 + (int(idcard_list[5]) + int(idcard_list[15])) * 4 + (int(idcard_list[6]) + int(idcard_list[16])) * 2 + int(idcard_list[7]) * 1 + int(idcard_list[8]) * 6 + int(idcard_list[9]) * 3
Y = S % 11
M = "F"
JYM = "10X98765432"
M = JYM[Y] # 判断校验位
if(M == idcard_list[17]): # 检测ID的校验位
return Messages[0]
else:
return Messages[3]
else:
return Messages[2]
else:
return Messages[1] # 获取身份证信息
def getIdInfo(idcard):
checkresult = checkIdcard(idcard)
if checkresult == '验证通过!':
idcard = str(idcard)
idcard = idcard.strip()
ID_address = (idcard)[0:2] # 前两位是籍贯
ID_sex = idcard[14:17] # 14位之后表示性别 if(len(idcard) == 15):
ID_birth = '' + idcard[6:12] # 获取15位身份证出生年月日,补全19
else:
ID_birth = idcard[6:14] # 获取18位身份证出生年月日 strAddress = area[ID_address] # 籍贯
strGender = 'male' # 性别 year = ID_birth[0:4]
moon = ID_birth[4:6]
day = ID_birth[6:8]
strBirthDate = year + '-' + moon + '-' + day # 出生日期 if int(ID_sex) % 2 == 0:
strGender = 'female'
else:
strGender = 'male' # print '籍贯', strAddress
# print '性别', strGender
# print '出生日期', strBirthDate idInfo = [strAddress, strGender, strBirthDate] return idInfo
else:
writeLog("异常:"+idcard+checkresult) print idcard, checkresult
return 0; # 读取mongodb身份证信息,更新mongodb
# serverIp mongodb服务器IP
# port mongodb服务器端口
# dbName 要连接的数据库名称
# collectionName 数据库集合名称
def updateMongoInfo(serverIp, port, dbName, collectionName):
client = MongoClient(serverIp, port) # 连接mongodb数据库
db = client[dbName] # 指定数据库名称
collection = db[collectionName] # 获取集合名 log = open(logPath, 'a')
log.writelines([datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",开始更新……", "\n"])
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",开始更新……", "\n" # 查找身份证号码不为空的记录,才执行
for i in collection.find({'id_card':{"$ne":""}}):
result = getIdInfo(i['id_card'])
if(result != 0):
log.writelines([datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",更新,", i['idcard'], result[0], result[1], result[2], "\n"])
print i['id_card'], result
collection.update({"id_card":i['id_card']}, {"$set":{"address":result[0], "gender":result[1], "birth_date":result[2]}}) log.writelines([datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",更新结束……", "\n"])
log.close()
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",更新结束……", "\n" # 写日志
def writeLog(content):
with open(logPath, 'w+') as log:
log.writelines([datetime.now().strftime('%Y-%m-%d %H:%M:%S'), " ", content, "\n"]) # 入口函数
def start(logPath,serverIp, port, dbName, collectionName):
logPath=logPath
updateMongoInfo(serverIp, port, dbName, collectionName) # 测试
start('/Users/tim/updatemongo/log/log.txt','127.0.0.1', 27017, 'tim', 'person')

2、javascript代码

  mongodb是支持Javascript代码的,见我的另一篇博客:Mongodb常用操作

 //----------------------------------------------------------
// 功能:检查身份证号码
// 参数:idcard
// 返回值:检验信息
//----------------------------------------------------------
function checkIdCard(idcard){
  var Errors=new Array(
    "验证通过!",
    "身份证号码位数不对!",
    "身份证号码出生日期超出范围或含有非法字符!",
    "身份证号码校验错误!",
    "身份证地区非法!"
  );   var area={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江",
      31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",
      41:"河南",42:"湖北",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏",
      61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外"};   var idcard,Y,JYM;
  var S,M;
  var idcard_array = new Array();
  idcard_array = idcard.split("");
  //地区检验
  if(area[parseInt(idcard.substr(0,2))]==null) return Errors[4];
  //身份号码位数及格式检验
  switch(idcard.length){
    case 15:
      if ( (parseInt(idcard.substr(6,2))+1900) % 4 == 0 || ((parseInt(idcard.substr(6,2))+1900) % 100 == 0 &&
          (parseInt(idcard.substr(6,2))+1900) % 4 == 0 )){
        ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$/;//测试出生日期的合法性
      } else {
        ereg=/^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$/;//测试出生日期的合法性
      }
      if(ereg.test(idcard)) return Errors[0];
      else return Errors[2];       break;
    case 18:
  //18位身份号码检测
  //出生日期的合法性检查
  //闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
  //平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
      if ( parseInt(idcard.substr(6,4)) % 4 == 0 || (parseInt(idcard.substr(6,4)) % 100 == 0 &&
          parseInt(idcard.substr(6,4))%4 == 0 )){
        ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$/;//闰年出生日期的合法性正则表达式
      } else {
        ereg=/^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$/;//平年出生日期的合法性正则表达式
      }
      if(ereg.test(idcard)){//测试出生日期的合法性
      //计算校验位
      S = (parseInt(idcard_array[0]) + parseInt(idcard_array[10])) * 7
        + (parseInt(idcard_array[1]) + parseInt(idcard_array[11])) * 9
        + (parseInt(idcard_array[2]) + parseInt(idcard_array[12])) * 10
        + (parseInt(idcard_array[3]) + parseInt(idcard_array[13])) * 5
        + (parseInt(idcard_array[4]) + parseInt(idcard_array[14])) * 8
        + (parseInt(idcard_array[5]) + parseInt(idcard_array[15])) * 4
        + (parseInt(idcard_array[6]) + parseInt(idcard_array[16])) * 2
        + parseInt(idcard_array[7]) * 1
        + parseInt(idcard_array[8]) * 6
        + parseInt(idcard_array[9]) * 3 ;
        Y = S % 11;
        M = "F";
        JYM = "10X98765432";
        M = JYM.substr(Y,1);//判断校验位
      if(M == idcard_array[17]) return Errors[0]; //检测ID的校验位
      else return Errors[3];
    }
    else return Errors[2];
    break;
    default:
    return Errors[1];
    break;
  } } //----------------------------------------------------------
// 功能:根据身份证号获得出生日期
// 参数:身份证号 psidno
// 返回值:出生日期
//----------------------------------------------------------
function getBirthday(psidno){
var birthdayno,birthdaytemp;
if(psidno.length==18){
birthdayno=psidno.substring(6,14);
}else if(psidno.length==15){
birthdaytemp=psidno.substring(6,12);
birthdayno="19"+birthdaytemp;
}else{
print("错误的身份证号码,请核对!");
return false;
} var birthday=birthdayno.substring(0,4)+"-"+birthdayno.substring(4,6)+"-"+birthdayno.substring(6,8);
return birthday;
} //----------------------------------------------------------
// 功能:根据身份证号获得性别
// 参数:身份证号 psidno
// 返回值:性别
//----------------------------------------------------------
function getGender(psidno){
var sexno,sex;
if(psidno.length==18){
sexno=psidno.substring(16,17);
}else if(psidno.length==15){
sexno=psidno.substring(14,15);
}else{
print(psidno+"错误的身份证号码,请核对!");
return false;
}
var tempid=sexno%2;
if(tempid==0){
sex='female';
}else{
sex='male';
} return sex;
} //----------------------------------------------------------
// 功能:获取籍贯
// 参数:身份证号 psidno
// 返回值:籍贯
function getProvinceNameByIdNo(idcard) {
var area = { 11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古",
21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏",
33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东", 41: "河南", 42: "湖北",
43: "湖南", 44: "广东", 45: "广西",
46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南", 54: "西藏", 61: "陕西",
62: "甘肃", 63: "青海", 64: "宁夏",
65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外"
}; var provinceName = "";
var provinceNo = idcard.substr(0, 2);
if (area[parseInt(provinceNo)] != null) {
provinceName = area[parseInt(provinceNo)];
} return provinceName;
} //去掉空格
function trim(s) {
return s.replace(/^\s+|\s+$/g, "");
} //入口函数
//查询mongodb,根据身份证号码,先检验身份证,再提取性别、出生日期、籍贯,再更新mongodb
function start(collectionName){
var cursor = db.getCollection(collectionName).find({'id_card':{'$ne':''}});//查询身份证号码不为空的集合
while (cursor.hasNext()) {
var strCardId=cursor.next()["id_card"];
var card_id=trim(strCardId);//去掉空格后 if (card_id.length > 0) {
var checkResult=checkIdCard(card_id);
if (checkResult!='验证通过!') {
print(strCardId+checkResult);
continue;
}
else {
var birthday = getBirthday(card_id);
var provinceName = getProvinceNameByIdNo(card_id);
var gender=getGender(card_id);
print(strCardId+":"+birthday+","+provinceName+","+gender); //更新mongodb
//这里的id_card使用原始的,避免原始的身份证号码带空格,update找不到记录
db.getCollection(collectionName).updateMany({"id_card":strCardId}, {"$set":{"address":provinceName, "gender":gender, "birth_date":birthday}});
}
}
}
} //入口,传入集合名称
start('person');

从身份证号码中获取性别、出生日期、籍贯,并更新mongodb的更多相关文章

  1. js从身份证号中获取出生日期和性别

    今天,在做移动端的项目中,按照设计稿的要求,是可以让用户自己输入出生日期的,我还很认真的用了刚刚知道的html5表单的日期类型,本想着终于不用日期插件就可以实现用户选择自己的出生日期了,可结果老大说, ...

  2. PHP提取身份证号码中的生日并验证是否成年的函数

    php 提取身份证号码中的生日日期以及确定是否成年的一个函数.可以同时确定15位和18位的身份证,经本人亲测,非常好用,分享函数代码如下: <?php //用php从身份证中提取生日,包括15位 ...

  3. php提取身份证号码中的生日日期以及验证是否为未成年人的函数

    php 提取身份证号码中的生日日期以及确定是否成年的一个函数.可以同时确定15位和18位的身份证,经本人亲测,非常好用,分享函数代码如下: <?php //用php从身份证中提取生日,包括15位 ...

  4. GCD多线程 在子线程中获取网络图片 在主线程更新

    子线程中得所有数据都可以直接拿到主线程中使用 //当触摸屏幕的时候,从网络上下载一张图片到控制器的view上显示 -(void)touchesBegan:(NSSet *)touches withEv ...

  5. php 身份证号码获取星座和生肖

    发布:thatboy   来源:Net     [大 中 小] 本文介绍下,php用身份证号码获取星座和生肖的方法,一个简单的php实例,从身份证号码中取得星座与生肖信息,有兴趣的朋友参考研究下吧.本 ...

  6. JAVA通过身份证号码获取出生日期、年龄、性别

    JAVA验证身份证号码是否正确:https://www.cnblogs.com/pxblog/p/12038278.html /** * 通过身份证号码获取出生日期(birthday).年龄(age) ...

  7. PHP根据身份证号码验证、获取星座、生肖和性别函数

    首先介绍一下身份证含义 新的18位身份证号码各位的含义:1-2位省.自治区.直辖市代码:3-4位地级市.盟.自治州代码:5-6位县.县级市.区代码:7-14位出生年月日,比如19670401代表196 ...

  8. python实现获取身份证号码的方法

    记录瞬间 1.号码的结构 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成.排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码.2.地址码 表示编码 ...

  9. SQL 根据身份证号码获取年龄的函数

    在数据库的运用过程中,我们时常会碰到根据身份证号码来获取当前的年龄,今天我在这里写了一个函数,就是关于获取年龄的 create or replace function FUNC_COMPARE_SFZ ...

随机推荐

  1. 调试器GDB的基本使用方法

    GDB调试的三种方式: 1. 目标板直接使用GDB进行调试. 2. 目标板使用gdbserver,主机使用xxx-linux-gdb作为客户端. 3. 目标板使用ulimit -c unlimited ...

  2. Scala--模式匹配和样例类

    模式匹配应用场景:switch语句,类型查询,析构,样例类 一.更好的switch val ch :Char = '+' val sign = ch match{ case '+' => 1 c ...

  3. Luogu4916 魔力环 莫比乌斯反演、组合、生成函数

    传送门 先不考虑循环同构的限制,那么对于一个满足条件的序列,如果它的循环节长度为\(d\),那么与它同构的环在答案中就会贡献\(d\)次. 所以如果设\(f_i\)表示循环节长度恰好为\(i\)的满足 ...

  4. 波音,自动驾驶bug未修复,致346人丧生!5个月内两次坠毁!其中,包括8名中国公民

    一,波音737 MAX再次坠毁 继2018年10月29日,印尼波音737MAX飞机坠入爪哇海,导致178名乘客不幸遇难后,时隔不足5月,上周日,埃塞俄比亚航空公司一架波音737MAX客机在飞往肯尼亚途 ...

  5. Pytest+Allure定制报告

    前言: 最近在研究接口自动化的框架,好的测试报告在整个测试框架起到至关重要的部分.终于被我发现一个超好用的报告框架,不仅报告美观,而且方便CI集成. 就是它,就是它:Allure Test Repor ...

  6. Python-类的继承与派生

    python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1( ...

  7. Mysql的使用,常用的SQL语句

    一.启动mysql服务 启动mysql服务: systemctl start mysqld.service root用户登录mysql: 修改root 密码: alter user 'root'@'l ...

  8. Java参数是值传递还是引用传递?

    先来看看参数是如何传递的. 一.参数的传递 1.基本类型的参数传递 public static void main(String[] args) { int a = 1; fun(a); } priv ...

  9. bat 文本合并

    小工具—把多个TXT文件合成一个 - TTXS_RS的博客 - CSDN博客https://blog.csdn.net/TTXS_RS/article/details/79743384 把所有文本文件 ...

  10. C#复习笔记(3)--C#2:解决C#1的问题(结束C#2的内容:最后一些特性)

    结束C#2的内容:最后一些新性 这是本章要讲的内容: 分部类型:可以在多个源文件中为 一个类型编写代码. 特别适用于部分代码是自动生成, 而其他部分的代码为手写的类型. 静态类:对工具类进行整理, 以 ...