JS寄快遞地址智能解析

来源:https://www.cnblogs.com/sexy-programmer/archive/2020/07/15/13308152.html
-Advertisement-
Play Games

JS寄快遞地址智能解析——2020年7月15日 去年做了些前端內容,最近在整理一些稍微有點用的內容,比如智能解析地址,用戶只要輸入:張三1351111111江蘇省揚州市廣陵區XX小區X樓xxx室,就能解析出 姓名、電話、省市區、地址信息了。是不是很方便? 項目地址暫時沒有放,大家可以關註我的個人碼雲 ...


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;*/
View Code

 

下麵介紹部分使用實例:

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); }

 

使用起來非常方便,容錯率也高。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • DruidDataSource配置相容DBCP,但個別配置的語意有所區別。 配置 預設值 說明 name 配置這個屬性的意義在於,如果存在多個數據源,監控的時候可以通過名字來區分開來。如果沒有配置,將會生成一個名字,格式是:"DataSource-" + System.identityHashCod ...
  • mongodb的安裝非常簡單,官網有提供安裝版和綠色版的下載(外網,速度慢的一批,網速跟不上的同志建議從其他渠道下載),我本地裝的是安裝版的,目錄為預設目錄。再此不細聊如何安裝,直接進入主題,首先是如何啟動。 啟動步驟:方法1:命令行參數方式啟動服務 1.在mongodb安裝目錄下,與bin同級的目 ...
  • 一、InnoDB 體系架構 InnoDB 存儲引擎有多個記憶體塊,可以認為這些記憶體塊組成了一個大的記憶體池,負責如下工作: 維護所有進程/線程需要訪問的多個內部數據結構。 緩存磁碟上的數據,方便快速的讀取,同時對磁碟文件的數據修改之前在這裡進行緩存。 重做日誌(redo log)緩衝。 後臺線程的主要作 ...
  • 1 #標識列 2 /* 3 又稱為自增長列 4 含義:可以不用手動的插入值,系統提供預設的序列值 5 6 7 特點: 8 1、標識列必須和主鍵搭配嗎?不一定,但要求是一個key 9 2、一個表可以有幾個標識列?至多一個! 10 3、標識列的類型只能是數值型 11 4、標識列可以通過 SET auto ...
  • 1 #常見約束 2 3 /* 4 5 6 含義:一種限制,用於限製表中的數據,為了保證表中的數據的準確和可靠性 7 8 9 分類:六大約束 10 NOT NULL:非空,用於保證該欄位的值不能為空 11 比如姓名、學號等 12 DEFAULT:預設,用於保證該欄位有預設值 13 比如性別 14 PR ...
  • 本文更新於2020-04-05,使用MySQL 5.7,操作系統為Deepin 15.4。 安裝 MySQL Utilities需單獨安裝,如使用apt-get命令: apt-get install mysql-utilities 分類 MySQL工具根據用途可以分為如下幾類: 審計日誌管理:mys ...
  • 參考博客:https://blog.csdn.net/harvic880925/article/details/40660137 EventBus簡介 EventBus有哪些優點 Demo案例分享及問題解決 一、什麼是EventBus 由greenboot組織貢獻(該組織還貢獻了greenDAO), ...
  • 教程 必讀 | 深入理解佈局約束 插件 elastic-widgets Set of Flutter widgets built using physics based animations. timeago.dart A library useful for creating fuzzy time ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...