JS寄快递地址智能解析——2020年7月15日

去年做了些前端内容,最近在整理一些稍微有点用的内容,比如智能解析地址,用户只要输入:张三1351111111江苏省扬州市广陵区XX小区X楼xxx室,就能解析出 姓名、电话、省市区、地址信息了。是不是很方便?

项目地址暂时没有放,大家可以关注我的个人码云地址https://gitee.com/w9

纯JavaScript,无需Jquery,轻量级的JS包。可参考以下代码:

let defaultData = [];

const mCity = {};

const mArea = {};

/**
* 处理原始地址数据转换成专用数据
* @param list 原始数据
* @param init 是否初始化 如传空 已转换过不会再次转换
* @returns {boolean}
*/
function parseArea(list, init) {
if (!init && defaultData.length) {
return true;
}
defaultData = list;
defaultData.forEach(province => {
if (province.city) {
province.city.forEach(city => {
if (city.name !== '其他') {
if (!mCity[city.name]) {
mCity[city.name] = [];
}
mCity[city.name].push({
p: province.name,
c: city.name,
a: city.area || []
});
}
if (city.area) {
city.area.forEach(area => {
if (area !== '其他') {
if (!mArea[area]) {
mArea[area] = [];
}
mArea[area].push({
p: province.name,
c: city.name
})
}
})
}
})
}
});
}
/**
* 解析邮编
* @param
* @returns <array>
*/
function zipCodeFormat() {
let list = []
zipCode.forEach((el) => {
if (el.child) {
el.child.forEach((event) => {
if (event.child) {
event.child.forEach(element => {
list.push(element.zipcode)
})
} })
}
})
return list;
} //专用数据处理 let zipCodeList = zipCodeFormat();//邮编
parseArea(areaList);//地址 /**
* 解析
* @param address 任意地址字符串
* @returns {{name: string, mobile: string, detail: string, zip_code: string, phone: string}}
*/
function parse(address) {
address = address || '';
const parse = {
name: '',
mobile: '',
detail: '',
zip_code: '',
phone: ''
}; //去除空格...
address = address.replace(/\r\n/g, ' ').replace(/\n/g, ' ').replace(/\t/g, ' ');
address = address.replace(/\s+/g, "");
//自定义去除关键字,可自行添加
const search = ['地址', '收货地址', '收货人', '收件人', '收货', '邮编', '电话', ':', ':', ';', ';', ',', ',', '。', ];
search.forEach(str => {
address = address.replace(new RegExp(str, 'g'), ' ')
});
//多个空格replace为一个
address = address.replace(/ {2,}/g, ' ');
//整理电话格式
address = address.replace(/(\d{3})-(\d{4})-(\d{4})/g, '$1$2$3'); address = address.replace(/(\d{3}) (\d{4}) (\d{4})/g, '$1$2$3'); const mobileReg = /(86-[1][0-9]{10})|(86[1][0-9]{10})|([1][0-9]{10})/g;
const mobile = mobileReg.exec(address);
if (mobile) {
parse.mobile = mobile[0];
address = address.replace(mobile[0], ' ')
}
//电话
const phoneReg = /(([0-9]{3,4}-)[0-9]{7,8})|([0-9]{12})|([0-9]{11})|([0-9]{10})|([0-9]{9})|([0-9]{8})|([0-9]{7})/g;
const phone = phoneReg.exec(address);
if (phone) {
parse.phone = phone[0];
address = address.replace(phone[0], ' ')
} //邮编(加入门牌号;考虑到重复邮编问题;去除之前简单的六位数字校验) for (let index = 0; index < zipCodeList.length; index++) {
if (address.indexOf(zipCodeList[index]) != -1) {
let num = address.indexOf(zipCodeList[index]);
let code = address.slice(num, num + 6);
parse.zip_code = code;
address = address.replace(code, '')
}
} /* 废弃
const zipReg = /([0-9]{6})/g;
const zip = zipReg.exec(address);
if (zip) {
parse.zip_code = zip[0];
address = address.replace(zip[0], '')
}
*/ address = address.replace(/ {2,}/, ' ');
//console.log(address) let detail = detail_parse_forward(address.trim());
if (!detail.city) {
detail = detail_parse(address.trim());
if (detail.area && !detail.city) {
detail = detail_parse(address.trim(), {
ignoreArea: true
});
console.log('smart_parse->ignoreArea(忽略区)');
} else {
// console.log('smart_parse');
}
//这个待完善
const list = address.replace(detail.province, '').replace(detail.city, '').replace(detail.area, '').split(' ').filter(str => str);
//详细住址划分关键字
//注意:只需要填写关键字最后一位即可:比如单元填写元即可!
const address_detail_list = ['室', '楼', '元', '号', '幢', '门', '户'];
if (list.length > 1) {
list.forEach(str => {
if (!parse.name || str && str.length < parse.name.length) {
parse.name = str.trim()
}
});
if (parse.name) {
detail.addr = detail.addr.replace(parse.name, '').trim()
}
} else {//若名字写在详细地址后面,根据address_detail_list进行分割;
let key = [];
address_detail_list.forEach((el) => {
key.push(detail.addr.indexOf(el))
})
var max = key.sort(function (a, b) {
return b - a;
})[0];
if (max != -1) {
let addrBuild = detail.addr.slice(0, max + 1);
let addrNum = detail.addr.replace(addrBuild, '').replace(/[^0-9]+/g, '');
let userName = detail.addr.replace(addrBuild + addrNum, '')
detail.addr = addrBuild + addrNum
parse.name = userName
}
}
} else {
if (detail.name) {
parse.name = detail.name
} else {
const list = detail.addr.split(' ').filter(str => str);
if (list.length > 1) {
parse.name = list[list.length - 1]
}
if (parse.name) {
detail.addr = detail.addr.replace(parse.name, '').trim()
}
}
}
parse.province = detail.province;
parse.city = detail.city;
parse.area = detail.area;
parse.addr = detail.addr;
parse.result = detail.result;
return parse;
} /**
* 正向解析模式
* 从前到后按 province city addr 逐级筛选
* 有city的值即可说明解析成功
* 此模式对地址顺序有要求
* @param address
* @returns {{province: string, city: string, area: string, addr: string}}
*/
function detail_parse_forward(address) {
const parse = {
province: '',
city: '',
area: '',
addr: '',
name: '',
}; const provinceKey = ['特别行政区', '古自治区', '维吾尔自治区', '壮族自治区', '回族自治区', '自治区', '省省直辖', '省', '市'];
const cityKey = ['布依族苗族自治州', '苗族侗族自治州', '自治州', '州', '市', '县']; for (let i in defaultData) {
const province = defaultData[i];
let index = address.indexOf(province.name);
if (index > -1) {
if (index > 0) {
//省份不是在第一位,在省份之前的字段识别为名称
parse.name = address.substr(0, index).trim();
}
parse.province = province.name;
address = address.substr(index + province.name.length);
for (let k in provinceKey) {
if (address.indexOf(provinceKey[k]) === 0) {
address = address.substr(provinceKey[k].length);
}
}
for (let j in province.city) {
const city = province.city[j];
index = address.indexOf(city.name);
if (index > -1 && index < 3) {
parse.city = city.name;
address = address.substr(index + parse.city.length);
for (let k in cityKey) {
if (address.indexOf(cityKey[k]) === 0) {
address = address.substr(cityKey[k].length);
}
}
if (city.area) {
for (let k in city.area) {
const area = city.area[k];
index = address.indexOf(area);
if (index > -1 && index < 3) {
parse.area = area;
address = address.substr(index + parse.area.length);
break;
}
}
}
break;
}
}
parse.addr = address.trim();
break;
}
}
return parse;
} /**
* 逆向解析 从后【县,区,旗】往前解析
* 有地区就能大概返回地址了
* @param address
* @param ignoreArea 是否忽视区 因为地址中含有区容易导致匹配错误 例:山东省蓬莱市黄海花园东区西门宝威学堂 曲荣声收15753572456
* @returns {{province: string, city: string, area: string, name: string, _area: string, addr: string}}
*/
function detail_parse(address, {
ignoreArea = false
} = {}) {
const parse = {
province: '',
city: '',
area: '',
name: '',
_area: '',
addr: '',
};
let areaIndex = -1,
cityIndex = -1; address = address.replace(' ', ' '); if (!ignoreArea && address.indexOf('县') > -1 || !ignoreArea && address.indexOf('区') > -1 || !ignoreArea && address.indexOf('旗') > -1) {
if (address.indexOf('旗') > -1) {
areaIndex = address.indexOf('旗');
parse.area = address.substr(areaIndex - 1, 2);
}
if (address.indexOf('区') > -1) {
areaIndex = address.indexOf('区');
if (address.lastIndexOf('市', areaIndex) > -1) {
cityIndex = address.lastIndexOf('市', areaIndex);
parse.area = address.substr(cityIndex + 1, areaIndex - cityIndex);
} else {
parse.area = address.substr(areaIndex - 2, 3);
}
}
if (address.indexOf('县') > -1) {
areaIndex = address.lastIndexOf('县');
if (address.lastIndexOf('市', areaIndex) > -1) {
cityIndex = address.lastIndexOf('市', areaIndex);
parse.area = address.substr(cityIndex + 1, areaIndex - cityIndex);
} else {
parse.area = address.substr(areaIndex - 2, 3);
}
}
parse.addr = address.substr(areaIndex + 1); } else {
if (address.indexOf('市') > -1) {
areaIndex = address.indexOf('市');
parse.area = address.substr(areaIndex - 2, 3);
parse.addr = address.substr(areaIndex + 1);
} else {
parse.addr = address
}
} if (address.indexOf('市') > -1 || address.indexOf('盟') > -1 || address.indexOf('州') > -1) {
if (address.indexOf('市') > -1) {
parse._area = address.substr(address.indexOf('市') - 2, 2);
}
if (address.indexOf('盟') > -1 && !mCity[parse._area]) {
parse._area = address.substr(address.indexOf('盟') - 2, 2);
}
if (address.indexOf('州') > -1 && !mCity[parse._area]) {
parse._area = address.substr(address.indexOf('州') - 2, 2);
}
} parse.area = parse.area.trim(); if (parse.area && mArea[parse.area]) {
if (mArea[parse.area].length === 1) {
parse.province = mArea[parse.area][0].p;
parse.city = mArea[parse.area][0].c
} else {
parse._area = parse._area.trim();
const addr = address.substr(0, areaIndex);
const d = mArea[parse.area].find(item => {
return item.p.indexOf(addr) > -1 || item.c === parse._area;
});
if (d) {
parse.province = d.p;
parse.city = d.c
} else {
parse.result = mArea[parse.area];
}
}
} else {
if (parse._area) {
const city = mCity[parse._area];
if (city) {
parse.province = city[0].p;
parse.city = city[0].c;
parse.addr = address.substr(address.indexOf(parse.city) + parse.city.length + 1);
parse.area = '';
for (let i in city[0].a) {
if (parse.addr.indexOf(city[0].a[i]) === 0) {
parse.area = city[0].a[i];
parse.addr = parse.addr.replace(city[0].a[i], '');
break;
}
}
}
} else {
parse.area = '';
}
}
parse.addr = parse.addr.trim();
return parse
} /*export {parseArea} export default parse;*/

下面介绍部分使用实例:

Html

<textarea class="weui-textarea sj_textarea" onchange="smart_parse2()" placeholder="[智能填写] 例如:张三1351111111江苏省扬州市广陵区XX小区X楼xxx室" rows="2"></textarea>

JavaScript

        //智能识别地址
function smart_parse2() {
var value = $('.sj_textarea').val();
console.log(parse(value));//这里可以看一下解析出来的内容
var html = '';
for (var key in parse(value)) {
if (parse(value)[key]) {
html += `<p>` + key + `:` + parse(value)[key] + `</p>`
}
}
//把解析的内容在赋值到页面元素中(这儿业务使用的Jq,实际上不需要)
$('#sj_name').val(parse(value).name);
$('#sj_phone').val(parse(value).phone);
$('#city-picker2').val(parse(value).province + ' ' + parse(value).city + ' ' + parse(value).area);
$('#sj_addr').val(parse(value).addr);
}

使用起来非常方便,容错率也高。

JS寄快递地址智能解析的更多相关文章

  1. 基于PHP的地址智能解析案例-快宝开放平台

    快宝地址智能解析,批量录入收件人.发件人最好的解决方案,广泛应用于快递行业,电商行业,ERP应用等. 一.对接前准备 注册快宝开放平台,获得开发者账号,查看如何注册. 二.对接联调 快宝开放平台支持多 ...

  2. 批量录入快递地址-快宝地址服务(PHP代码示例)

    快递地址写错了怎么办?快递地址写的不详细怎么办?怎么皮批量录入收件人地址?微商怎么批量录入发件人地址?快宝地址清洗,有效的解决了寄送快递时,批量录入收件人信息.发件人信息时,纠正地址数据,不完整地址识 ...

  3. 快速录入快递地址API接口实现

    电商.ERP等行业下单环节极其重要,如何提高下单的效率已经成为首要问题.快速下单对于客户来说,为提前发货争取了时间:对于卖家来说,提高了库存周转率及利用率.快速下单的接口实现,需要解决如下几个问题:1 ...

  4. 如何实现CDN的ns智能解析和动手验证Akamai的实现

    1.什么是ns智能解析 通常CDN业务中,智能解析域名,是根据请求方ip的不同给出不同的A记录. 而ns智能解析,是根据请求方ip的不同让他去不同的ns上解析域名,把ns推向离用户更近的边缘节点来缩短 ...

  5. DNS智能解析的搭建与配置

    分类: LINUX 原文地址:DNS智能解析的搭建与配置 作者:十年梦生  9月份整整忙了一个月,都抽不出时间来写篇文章,这几天趁着10.1终于有时间来写些东西了,将9月份所做的一些东西来做下总结. ...

  6. DNS服务器原理简述、搭建主/从DNS服务器并实现智能解析

    1. TLD:Top Level Domain 顶级域名 组织域:.com, .net, .org, .gov, .edu, .mil 国家域:.iq, .tw, .hk, .jp, .cn, ... ...

  7. js中取得当前加载的js的src地址

    在很多js框架中看到过,如果要动态加载框架内部的其他js,加载的时候加载的地址经常是一个相对的地址,只能是这样了哦,因为框架根本不知道用此框架的用户,将框架js文件放的具体目录,所以框架中一般会采用如 ...

  8. JS中将JSON的字符串解析成JSON数据格式《转》

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery的ea ...

  9. js获取IP地址方法总结_转

    js代码获取IP地址的方法,如何在js中取得客户端的IP地址.原文地址:js获取IP地址的三种方法 http://www.jbxue.com/article/11338.html 1,js取得IP地址 ...

随机推荐

  1. Vue基础(五)---- 前端路由

    基本结构: ◆ 1.路由的基本概念与原理 ◆ 2.vue-router的基本使用 ◆ 3.vue-router嵌套路由 ◆ 4.vue-router动态路由匹配 ◆ 5.vue-router命名路由 ...

  2. Mysql探索之索引详解,又能和面试官互扯了~

    前言 索引是什么?有什么利弊?一旦在面试中被问道,对于新入门的小白可能是个棘手的问题. 本篇文章将会详细讲述什么是索引.索引的优缺点.数据结构等等常见的知识. 什么是索引 索引就是一种的数据结构,存储 ...

  3. windows环境安装vue-cli及webpack并创建vueJs项目

    1. 安装node.js 2. 如果安装的是旧版本的 npm,可以通过 npm 命令来进行版本升级,命令如下: npm install npm -g npm网站服务器位于国外,所以经常下载缓慢或出现异 ...

  4. 一张图对比React、Angular、Vue.js

    文章原文地址:https://baijiahao.baidu.com/s?id=1609374985643812253&wfr=spider&for=pc

  5. Photon PUN 一 介绍

    有句话说的好 , 官网永远是最好的学习地方 . 虽然国内的资料不多 , 但是官网的资料还是很充足 , 这就带着英汉词典就着作阅读理解的劲头去官网学习吧 https://doc.photonengine ...

  6. 入门的艰难——关于LR的使用

    这年头做一件事真是TM不容易啊.做测试也很纠结,不是都说商业工具很强大么,我去,这个不支持那个不支持的,这还有什么搞头,还非要按照你说的这个版本的才行,高一点的就crash了,结果连最初级的录制脚本都 ...

  7. Lua 5.3注册C++类相关API

    int luaL_newmetatable (lua_State *L, const char *tname); 如果注册表中不存在名为tname的表,则在注册表中创建一个名为tname的表,并将这个 ...

  8. 基于Celery在多台云服务器上实现分布式

    起源 最近参加公司里的一个比赛,比赛内容里有一项是尽量使用分布式实现项目.因为项目最终会跑在jetsonnano,一个贼卡的开发板,性能及其垃圾.而且要求使用python? 找了很多博客,讲的真的是模 ...

  9. 不支持原子性的 Redis 事务也叫事务吗?

    文章收录在 GitHub JavaKeeper ,N线互联网开发必备技能兵器谱 假设现在有这样一个业务,用户获取的某些数据来自第三方接口信息,为避免频繁请求第三方接口,我们往往会加一层缓存,缓存肯定要 ...

  10. Vue-router的用法与使用步骤

    Vue-router的使用步骤: Vue Router的使用步骤还是比较清晰的,按照步骤一步一步就能完成路由操作 A.导入js文件 B.添加路由链接 C.添加路由占位符(最后路由展示的组件就会在占位符 ...