js智能识别收货地址
时隔接近一年的时间没更新过博客了,今天来更新下~
前段时间做了些前端内容,最近在整理一些稍微有点用的内容。比如智能解析地址,用户只需要输入:张三13800138000广东省深圳市南山区南海大道3688号,就能够解析出姓名、电话、省市区、地址信息了。是不是很方便?
实现原理纯JavaScript,无需JQuery,轻量级的js包,可以参考以下代码:
// 定义所有省级名称
const provinces = ["北京", "天津", "河北", "山西", "内蒙古", "辽宁", "吉林", "黑龙江", "上海", "江苏", "浙江", "安徽", "福建", "江西", "山东", "河南", "湖北", "湖南", "广东", "广西", "海南", "重庆", "四川", "贵州", "云南", "西藏", "陕西", "甘肃", "青海", "宁夏", "新疆", "台湾", "香港", "澳门", "国外"];
// 定义所有省级可能出现的后缀
const provinceKey = ['特别行政区', '维吾尔自治区', '壮族自治区', '回族自治区', '自治区', '省省直辖', '省', '市'];
// 定义所有地级市可能出现的后缀
const cityKey = ['布依族苗族自治州', '苗族侗族自治州', '自治州', '行政单位', '市', '盟', '地区', '县'];
// 定义所有县级可能出现的后缀
const areaKey = ['县', '旗', '海域', '岛', '市', '区'];
// 定义详细地址可能出现的后缀
const addrKey = ['室', '楼', '单元', '元', '号', '幢', '门', '户', '米', '北', '南', '东', '西', '路口', '路', '处', '街道', '街'];
// 自定义去除关键字,可自行添加
const search = ['地址', '收货地址', '收货人', '收件人', '收货', '邮编', '电话', ':', ':', ';', ';', ',', ',', '。', ' '];
// 整理电话格式
const mobileRegexs = [
/(\d{3})-(\d{4})-(\d{4})/g,
/(\d{3}) (\d{4}) (\d{4})/g,
];
const mobileReg = /(86-[1][0-9]{10})|(86[1][0-9]{10})|([1][0-9]{10})/g;
// 直辖市
const municipalityDirectly = '北京|天津|重庆|上海';
/**
* 解析地址
* @param {Object} obj
* @param {String} obj.parseText 要解析的地址文本。
* @param {function({addr: '富康路姚家园3楼5单元3305室',area: '朝阳区',city: '北京市',mobile: '15000000000',name: '马云',province: '北京市',})=} obj.success
* @param {function(String)=} obj.fail
* @param {function({addr: '富康路姚家园3楼5单元3305室',area: '朝阳区',city: '北京市',mobile: '15000000000',name: '马云',province: '北京市',}|String)=} obj.complete
* @return {()=>void}
* @example parse({
* parseText: '北京市朝阳区富康路姚家园3楼5单元3305室马云150-0000-0000',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '北京市朝阳区富康路姚家园3号楼5单元3305室马云15000000000',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '北京市朝阳区富康路姚家园3号楼5单元3305室马云15000000000',success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '马云,1351111111,北京市朝阳区富康路姚家园3楼',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '马云1351111111北京市朝阳区富康路姚家园3楼',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '北京市朝阳区富康路姚家园3楼1351111111马云',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
* @example parse({
* parseText: '北京市朝阳区富康路姚家园3楼150-0000-0000马云',
* success(res) {},
* fail(res) {},
* complete(res) {}
* })
*/
function parse({parseText, success=function(){}, fail=function(){}, complete=function(){}}) {
try {
if (parseText.trim() === '') {
throw '无法识别';
}
let parse = {
addr: '',
area: '',
city: '',
mobile: '',
name: '',
province: '',
};
// 过滤关键字词
search.forEach(str => {
parseText = parseText.replace(new RegExp(str, 'g'), '')
});
// 先识别出手机或电话号码
mobileRegexs.forEach(regex => {
parseText = parseText.replace(regex, '$1$2$3')
});
let mobile = mobileReg.exec(parseText);
if (mobile) {
parse.mobile = mobile[0];
// 识别完电话手机号码,要把对应的号码从待识别里面去掉
parseText = parseText.replace(mobile[0], '')
}
// 地区地址
let address = parseText;
// 检测是哪个省份或直辖市
for (let i in provinces) {
let index = address.indexOf(provinces[i]);
if (index > -1) {
address = address.substring(index);
}
/**
* 如果地址是直辖市,如“北京市朝阳区”,则补全为“北京市北京市朝阳区”。否则下面的正则表达式匹配不到
* 但如果地址是“北京市北京市朝阳区”,则不能再修改了
*/
if (new RegExp(municipalityDirectly, 'g').test(address) && address.match(new RegExp(municipalityDirectly, 'g')).length === 1) {
let tmp = address.substring(0, 2) + '市' + address;
parseText = parseText.replace(new RegExp(address, 'g'), tmp);
address = tmp;
}
}
// 匹配地址的正则表达式。包含:省级、地级市级、县级、详细地址等四部分
let addrRegex = '(.*?)';
// 省级
addrRegex = addrRegex + '(?' ;
provinceKey.forEach(item=>{
addrRegex = addrRegex + '[^'+item+']+'+item+'|';
});
addrRegex = addrRegex.substring(0, addrRegex.length-1);
addrRegex = addrRegex + ')';
// 地级市级
addrRegex = addrRegex + '(?' ;
cityKey.forEach(item=>{
addrRegex = addrRegex + '[^'+item+']+'+item+'|';
});
addrRegex = addrRegex.substring(0, addrRegex.length-1);
addrRegex = addrRegex + ')';
// 县级
addrRegex = addrRegex + '(?' ;
areaKey.forEach(item=>{
addrRegex = addrRegex + '[^'+item+']+'+item+'|';
});
addrRegex = addrRegex.substring(0, addrRegex.length-1);
addrRegex = addrRegex + ')';
// 详细地址
addrRegex = addrRegex + '(?' ;
addrKey.forEach(item=>{
addrRegex = addrRegex + '[^'+item+']+'+item+'|';
});
addrRegex = addrRegex + '.*?';
addrRegex = addrRegex + ')';
// 地址的匹配结果
let addrRet = address.match(new RegExp(addrRegex));
if (new RegExp(addrRegex, 'g').test(address)) {
parse.province = addrRet.groups.province;
parse.city = addrRet.groups.city;
parse.area = addrRet.groups.county;
parse.addr = addrRet.groups.village;
// 去掉手机电话号码和地址之后,剩下的就是姓名了
parseText = parseText.replace(new RegExp(addrRet[0], 'g'), '');
}
// 姓名
parse.name = parseText;
let flag = false;
for (let i in parse) {
if (parse[i]) {
flag = true;
}
}
if (flag) {
complete && complete(parse);
success && success(parse);
} else {
throw '识别失败';
}
} catch (err) {
complete && complete(err);
fail && fail(err);
}
}
module.exports.parse = parse;
下面介绍部分使用实例:
微信小程序:
wxml:
<view class="address">
<view class="address-item address-item2 address-header">
<view class="address-label">智能识别view>
<view class="address-parse-btn" bindtap="identifyParseText">识别view>
view>
<view class="address-item address-item2">
<textarea cols="30" rows="5" class="address-input1" placeholder="智能填写,请粘贴文本" placeholder-class="address-input1_plaeholder" bindinput="changeParseText">textarea>
view>
view>
js:
const addressParse = require('/utils/address-parse.js');
Page({
identifyParseText() {
const that = this;
wx.showLoading({
title: '文本提取中',
});
let parseText = that.data.parseText;
addressParse.parse({
parseText: parseText,
complete: function () {
wx.hideLoading();
},
success: function (res) {
wx.showToast({
title: '识别成功',
icon: 'none',
});
console.log('识别结果:', res);
},
fail: function (res) {
console.log(res);
if (typeof res === 'string') {
wx.showToast({
title: res,
icon: 'none',
})
}
},
})
},
});
使用起来非常方便,容错率也相对比较高。
到此这篇关于js识别地址智能解析的文章就介绍到这里啦~