1. 程式人生 > 程式設計 >JS寄快遞地址智慧解析的實現程式碼

JS寄快遞地址智慧解析的實現程式碼

去年做了些前端內容,最近在整理一些稍微有點用的內容,比如智慧解析地址,使用者只要輸入:張三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,name: string,_area: string,addr: string}}
 */
function detail_parse(address,{
 ignoreArea = false
} = {}) {
 const parse = {
 province: '',_area: '',};
 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('市',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寄快遞地址智慧解析的文章就介紹到這了,更多相關js 寄快遞內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!