合并选择器和地址解析
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<select
|
||||
v-model="province"
|
||||
placeholder="请选择省/市"
|
||||
@change="checkProvince"
|
||||
>
|
||||
<option
|
||||
v-for="(province, p_i) in provinceJson"
|
||||
:key="p_i"
|
||||
:value="province.name"
|
||||
>
|
||||
{{ province.name }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<select v-model="city" placeholder="请选择市/区" @change="checkCity">
|
||||
<option v-for="(city, c_i) in cityJson" :key="c_i" :value="city.name">
|
||||
{{ city.name }}
|
||||
</option>
|
||||
</select>
|
||||
<select v-model="area" placeholder="请选择区/县">
|
||||
<option v-for="(area, a_i) in areaJson" :key="a_i" :value="area.name">
|
||||
{{ area.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddressJson from "./lib/address-json";
|
||||
console.log(AddressJson);
|
||||
export default {
|
||||
name: "v-distpicker",
|
||||
props: {
|
||||
// province: { type: [String, Number], default: "" },
|
||||
// city: { type: [String, Number], default: "" },
|
||||
// area: { type: [String, Number], default: "" },
|
||||
// type: { type: String, default: "" },
|
||||
// hideArea: { type: Boolean, default: false },
|
||||
// onlyProvince: { type: Boolean, default: false },
|
||||
// staticPlaceholder: { type: Boolean, default: false },
|
||||
// placeholders: {
|
||||
// type: Object,
|
||||
// default() {
|
||||
// return {
|
||||
// province: "省",
|
||||
// city: "市",
|
||||
// area: "区",
|
||||
// };
|
||||
// },
|
||||
// },
|
||||
// districts: {
|
||||
// type: [Array, Object],
|
||||
// default() {
|
||||
// return DISTRICTS;
|
||||
// },
|
||||
// },
|
||||
// disabled: { type: Boolean, default: false },
|
||||
// provinceDisabled: { type: Boolean, default: false },
|
||||
// cityDisabled: { type: Boolean, default: false },
|
||||
// areaDisabled: { type: Boolean, default: false },
|
||||
// addressHeader: { type: String, default: "address-header" },
|
||||
// addressContainer: { type: String, default: "address-container" },
|
||||
// wrapper: { type: String, default: "distpicker-address-wrapper" },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
provinceJson: AddressJson,
|
||||
cityJson: [],
|
||||
areaJson: [],
|
||||
codes: [],
|
||||
province: "",
|
||||
city: "",
|
||||
area: "",
|
||||
// tab: 1,
|
||||
// showCityTab: false,
|
||||
// showAreaTab: false,
|
||||
// provinces: [],
|
||||
// cities: [],
|
||||
// areas: [],
|
||||
// currentProvince:
|
||||
// this.determineType(this.province) || this.placeholders.province,
|
||||
// currentCity: this.determineType(this.city) || this.placeholders.city,
|
||||
// currentArea: this.determineType(this.area) || this.placeholders.area,
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
watch: {},
|
||||
methods: {
|
||||
// 选择省
|
||||
checkProvince(e, a) {
|
||||
console.log(e, a);
|
||||
console.log(this.province);
|
||||
this.provinceJson.forEach((element) => {
|
||||
if (element.name == this.province) {
|
||||
this.cityJson = element.children;
|
||||
this.areaJson = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选择市
|
||||
checkCity(e, a) {
|
||||
console.log(e, a);
|
||||
console.log(this.city);
|
||||
this.cityJson.forEach((element) => {
|
||||
if (element.name == this.city) {
|
||||
this.areaJson = element.children;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
+4599
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
import VDistpicker from './Distpicker'
|
||||
import AddressParse from './lib/address-parse'
|
||||
import AddressJson from './lib/address-json'
|
||||
|
||||
export default {VDistpicker,AddressParse,AddressJson}
|
||||
@@ -0,0 +1,18 @@
|
||||
// import zhCnNames from './names'
|
||||
// import addressJson from './provinceList'
|
||||
|
||||
const AddressJson=require('./provinceList.json')
|
||||
const filterCity = ['行政区划']
|
||||
AddressJson.forEach(item => {
|
||||
if (item.children) {
|
||||
item.children.forEach((city, cityIndex) => {
|
||||
const index = ~filterCity.findIndex(filter => ~city.name.indexOf(filter))
|
||||
if (index) {
|
||||
item.children = item.children.concat(city.children || [])
|
||||
item.children.splice(cityIndex, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export default AddressJson
|
||||
@@ -0,0 +1,544 @@
|
||||
// import zhCnNames from './names'
|
||||
// import addressJson from './provinceList'
|
||||
|
||||
const zhCnNames=require('./names.json')
|
||||
const addressJson=require('./provinceList.json')
|
||||
const log = (...infos) => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log(...infos)
|
||||
}
|
||||
}
|
||||
|
||||
const filterCity = ['行政区划']
|
||||
addressJson.forEach(item => {
|
||||
if (item.children) {
|
||||
item.children.forEach((city, cityIndex) => {
|
||||
const index = ~filterCity.findIndex(filter => ~city.name.indexOf(filter))
|
||||
if (index) {
|
||||
item.children = item.children.concat(city.children || [])
|
||||
item.children.splice(cityIndex, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
log('完整的数据:', addressJson)
|
||||
const provinces = addressJson.reduce((per, cur) => {
|
||||
const {children, ...others} = cur
|
||||
console.log(children)
|
||||
return per.concat(others)
|
||||
}, [])
|
||||
|
||||
const cities = addressJson.reduce((per, cur) => {
|
||||
return per.concat(cur.children ? cur.children.map(({ ...others}) => ({...others, provinceCode: cur.code})) : [])
|
||||
}, [])
|
||||
|
||||
const areas = addressJson.reduce((per, cur) => {
|
||||
const provinceCode = cur.code
|
||||
return per.concat(cur.children ? cur.children.reduce((p, c) => {
|
||||
const cityCode = c.code
|
||||
return p.concat(c.children ? c.children.map(({ ...others}) => ({...others, cityCode, provinceCode,})) : [])
|
||||
}, []) : [])
|
||||
}, [])
|
||||
|
||||
|
||||
const provinceString = JSON.stringify(provinces)
|
||||
const cityString = JSON.stringify(cities)
|
||||
const areaString = JSON.stringify(areas)
|
||||
|
||||
log(provinces)
|
||||
log(cities)
|
||||
|
||||
log(provinces.length + cities.length + areas.length)
|
||||
|
||||
/**
|
||||
* 需要解析的地址,type是解析的方式,默认是正则匹配
|
||||
* @param address
|
||||
* @param options?:type: 0:正则,1:树查找, textFilter: 清洗的字段
|
||||
* @returns {{}|({area: Array, province: Array, phone: string, city: Array, name: string, detail: Array} & {area: (*|string), province: (*|string), city: (*|string), detail: (Array|boolean|string|string)})}
|
||||
* @constructor
|
||||
*/
|
||||
const AddressParse = (address, options) => {
|
||||
const { type = 0, textFilter = [], nameMaxLength = 4 } = typeof options === 'object' ? options : (typeof options === 'number' ? { type: options } : {})
|
||||
|
||||
if (!address) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const parseResult = {
|
||||
phone: '',
|
||||
province: [],
|
||||
city: [],
|
||||
area: [],
|
||||
detail: [],
|
||||
name: '',
|
||||
}
|
||||
address = cleanAddress(address, textFilter)
|
||||
log('清洗后address --->', address)
|
||||
|
||||
// 识别手机号
|
||||
const resultPhone = filterPhone(address)
|
||||
address = resultPhone.address
|
||||
parseResult.phone = resultPhone.phone
|
||||
log('获取电话的结果 --->', address)
|
||||
|
||||
const resultCode = filterPostalCode(address)
|
||||
address = resultCode.address
|
||||
parseResult.postalCode = resultCode.postalCode
|
||||
log('获取邮编的结果 --->', address)
|
||||
|
||||
// 地址分割,排序
|
||||
let splitAddress = address.split(' ').filter(item => item).map(item => item.trim())
|
||||
// 这里先不排序了,排序可能出现问题,比如:北京 北京市
|
||||
splitAddress = sortAddress(splitAddress)
|
||||
log('分割地址 --->', splitAddress)
|
||||
|
||||
const d1 = new Date().getTime()
|
||||
|
||||
// 找省市区和详细地址
|
||||
splitAddress.forEach((item) => {
|
||||
// 识别地址
|
||||
if (!parseResult.province[0] || !parseResult.city[0] || !parseResult.area[0]) {
|
||||
// 两个方法都可以解析,正则和树查找
|
||||
let parse = {}
|
||||
type === 1 && (parse = parseRegion(item, parseResult))
|
||||
type === 0 && (parse = parseRegionWithRegexp(item, parseResult))
|
||||
const {province, city, area, detail} = parse
|
||||
parseResult.province = province || []
|
||||
parseResult.area = area || []
|
||||
parseResult.city = city || []
|
||||
parseResult.detail = parseResult.detail.concat(detail || [])
|
||||
} else {
|
||||
parseResult.detail.push(item)
|
||||
}
|
||||
})
|
||||
|
||||
log('--->', splitAddress)
|
||||
|
||||
const d2 = new Date().getTime()
|
||||
|
||||
log('解析耗时--->', d2 - d1)
|
||||
|
||||
const province = parseResult.province[0]
|
||||
const city = parseResult.city[0]
|
||||
const area = parseResult.area[0]
|
||||
let detail = parseResult.detail
|
||||
|
||||
detail = detail.map(item => item.replace(new RegExp(`${province && province.name}|${city && city.name}|${area && area.name}`, 'g'), ''))
|
||||
detail = Array.from(new Set(detail))
|
||||
log('去重后--->', detail)
|
||||
|
||||
// 地址都解析完了,姓名应该是在详细地址里面
|
||||
if (detail && detail.length > 0) {
|
||||
const copyDetail = [...detail].filter(item => !!item)
|
||||
copyDetail.sort((a, b) => a.length - b.length)
|
||||
log('copyDetail --->', copyDetail)
|
||||
// 排序后从最短的开始找名字,没找到的话就看第一个是不是咯
|
||||
const index = copyDetail.findIndex(item => judgeFragmentIsName(item, nameMaxLength))
|
||||
let name = ''
|
||||
if (~index) {
|
||||
name = copyDetail[index]
|
||||
} else if (copyDetail[0].length <= nameMaxLength && /[\u4E00-\u9FA5]/.test(copyDetail[0])) {
|
||||
name = copyDetail[0]
|
||||
}
|
||||
|
||||
// 找到了名字就从详细地址里面删除它
|
||||
if (name) {
|
||||
parseResult.name = name
|
||||
detail.splice(detail.findIndex(item => item === name), 1)
|
||||
}
|
||||
}
|
||||
|
||||
log(JSON.stringify(parseResult))
|
||||
|
||||
const provinceName = province && province.name
|
||||
let cityName = city && city.name
|
||||
if (~['市辖区', '区', '县', '镇'].indexOf(cityName)) {
|
||||
cityName = provinceName
|
||||
}
|
||||
return Object.assign(parseResult, {
|
||||
province: provinceName || '',
|
||||
city: cityName || '',
|
||||
area: (area && area.name) || '',
|
||||
detail: (detail && detail.length > 0 && detail.join('')) || ''
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 按照省市区县镇排序
|
||||
* @param splitAddress
|
||||
* @returns {*[]}
|
||||
*/
|
||||
const sortAddress = (splitAddress) => {
|
||||
const result = []
|
||||
const getIndex = (str) => {
|
||||
return splitAddress.findIndex(item => ~item.indexOf(str))
|
||||
}
|
||||
['省', '市', '区', '县', '镇'].forEach(item => {
|
||||
let index = getIndex(item)
|
||||
if (~index) {
|
||||
result.push(splitAddress.splice(index, 1)[0])
|
||||
}
|
||||
})
|
||||
|
||||
return [...result, ...splitAddress]
|
||||
}
|
||||
|
||||
/**
|
||||
* 利用正则表达式解析
|
||||
* @param fragment
|
||||
* @param hasParseResult
|
||||
* @returns {{area: (Array|*|string), province: (Array|*|string), city: (Array|*|string|string), detail: (*|Array)}}
|
||||
*/
|
||||
const parseRegionWithRegexp = (fragment, hasParseResult) => {
|
||||
log('----- 当前使用正则匹配模式 -----')
|
||||
let province = hasParseResult.province || [], city = hasParseResult.city || [], area = hasParseResult.area || [],
|
||||
detail = []
|
||||
|
||||
let matchStr = ''
|
||||
if (province.length === 0) {
|
||||
for (let i = 1; i < fragment.length; i++) {
|
||||
const str = fragment.substring(0, i + 1)
|
||||
const regexProvince = new RegExp(`\{\"code\":\"[0-9]{1,6}\",\"name\":\"${str}[\u4E00-\u9FA5]*?\"}`, 'g')
|
||||
const matchProvince = provinceString.match(regexProvince)
|
||||
if (matchProvince) {
|
||||
const provinceObj = JSON.parse(matchProvince[0])
|
||||
if (matchProvince.length === 1) {
|
||||
province = []
|
||||
matchStr = str
|
||||
province.push(provinceObj)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (province[0]) {
|
||||
fragment = fragment.replace(new RegExp(matchStr, 'g'), '')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (city.length === 0) {
|
||||
for (let i = 1; i < fragment.length; i++) {
|
||||
const str = fragment.substring(0, i + 1)
|
||||
const regexCity = new RegExp(`\{\"code\":\"[0-9]{1,6}\",\"name\":\"${str}[\u4E00-\u9FA5]*?\",\"provinceCode\":\"${province[0] ? `${province[0].code}` : '[0-9]{1,6}'}\"\}`, 'g')
|
||||
const matchCity = cityString.match(regexCity)
|
||||
if (matchCity) {
|
||||
const cityObj = JSON.parse(matchCity[0])
|
||||
if (matchCity.length === 1) {
|
||||
city = []
|
||||
matchStr = str
|
||||
city.push(cityObj)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (city[0]) {
|
||||
const {provinceCode} = city[0]
|
||||
fragment = fragment.replace(new RegExp(matchStr, 'g'), '')
|
||||
if (province.length === 0) {
|
||||
const regexProvince = new RegExp(`\{\"code\":\"${provinceCode}\",\"name\":\"[\u4E00-\u9FA5]+?\"}`, 'g')
|
||||
const matchProvince = provinceString.match(regexProvince)
|
||||
province.push(JSON.parse(matchProvince[0]))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (area.length === 0) {
|
||||
for (let i = 1; i < fragment.length; i++) {
|
||||
const str = fragment.substring(0, i + 1)
|
||||
const regexArea = new RegExp(`\{\"code\":\"[0-9]{1,9}\",\"name\":\"${str}[\u4E00-\u9FA5]*?\",\"cityCode\":\"${city[0] ? city[0].code : '[0-9]{1,6}'}\",\"provinceCode\":\"${province[0] ? `${province[0].code}` : '[0-9]{1,6}'}\"\}`, 'g')
|
||||
const matchArea = areaString.match(regexArea)
|
||||
if (matchArea) {
|
||||
const areaObj = JSON.parse(matchArea[0])
|
||||
if (matchArea.length === 1) {
|
||||
area = []
|
||||
matchStr = str
|
||||
area.push(areaObj)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (area[0]) {
|
||||
const {provinceCode, cityCode} = area[0]
|
||||
fragment = fragment.replace(matchStr, '')
|
||||
if (province.length === 0) {
|
||||
const regexProvince = new RegExp(`\{\"code\":\"${provinceCode}\",\"name\":\"[\u4E00-\u9FA5]+?\"}`, 'g')
|
||||
const matchProvince = provinceString.match(regexProvince)
|
||||
province.push(JSON.parse(matchProvince[0]))
|
||||
}
|
||||
if (city.length === 0) {
|
||||
const regexCity = new RegExp(`\{\"code\":\"${cityCode}\",\"name\":\"[\u4E00-\u9FA5]+?\",\"provinceCode\":\"${provinceCode}\"\}`, 'g')
|
||||
const matchCity = cityString.match(regexCity)
|
||||
city.push(JSON.parse(matchCity[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 解析完省市区如果还存在地址,则默认为详细地址
|
||||
if (fragment.length > 0) {
|
||||
detail.push(fragment)
|
||||
}
|
||||
|
||||
return {
|
||||
province,
|
||||
city,
|
||||
area,
|
||||
detail,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 利用树向下查找解析
|
||||
* @param fragment
|
||||
* @param hasParseResult
|
||||
* @returns {{area: Array, province: Array, city: Array, detail: Array}}
|
||||
*/
|
||||
const parseRegion = (fragment, hasParseResult) => {
|
||||
log('----- 当前使用树查找模式 -----')
|
||||
let province = [], city = [], area = [], detail = []
|
||||
|
||||
if (hasParseResult.province[0]) {
|
||||
province = hasParseResult.province
|
||||
} else {
|
||||
// 从省开始查找
|
||||
for (const tempProvince of provinces) {
|
||||
const {name} = tempProvince
|
||||
let replaceName = ''
|
||||
for (let i = name.length; i > 1; i--) {
|
||||
const temp = name.substring(0, i)
|
||||
if (fragment.indexOf(temp) === 0) {
|
||||
replaceName = temp
|
||||
break
|
||||
}
|
||||
}
|
||||
if (replaceName) {
|
||||
province.push(tempProvince)
|
||||
fragment = fragment.replace(new RegExp(replaceName, 'g'), '')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasParseResult.city[0]) {
|
||||
city = hasParseResult.city
|
||||
} else {
|
||||
// 从市区开始查找
|
||||
for (const tempCity of cities) {
|
||||
const {name, provinceCode} = tempCity
|
||||
const currentProvince = province[0]
|
||||
// 有省
|
||||
if (currentProvince) {
|
||||
if (currentProvince.code === provinceCode) {
|
||||
let replaceName = ''
|
||||
for (let i = name.length; i > 1; i--) {
|
||||
const temp = name.substring(0, i)
|
||||
if (fragment.indexOf(temp) === 0) {
|
||||
replaceName = temp
|
||||
break
|
||||
}
|
||||
}
|
||||
if (replaceName) {
|
||||
city.push(tempCity)
|
||||
fragment = fragment.replace(new RegExp(replaceName, 'g'), '')
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有省,市不可能重名
|
||||
for (let i = name.length; i > 1; i--) {
|
||||
const replaceName = name.substring(0, i)
|
||||
if (fragment.indexOf(replaceName) === 0) {
|
||||
city.push(tempCity)
|
||||
province.push(provinces.find(item => item.code === provinceCode))
|
||||
fragment = fragment.replace(replaceName, '')
|
||||
break
|
||||
}
|
||||
}
|
||||
if (city.length > 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 从区市县开始查找
|
||||
for (const tempArea of areas) {
|
||||
const {name, provinceCode, cityCode} = tempArea
|
||||
const currentProvince = province[0]
|
||||
const currentCity = city[0]
|
||||
|
||||
// 有省或者市
|
||||
if (currentProvince || currentCity) {
|
||||
if ((currentProvince && currentProvince.code === provinceCode)
|
||||
|| (currentCity && currentCity.code) === cityCode) {
|
||||
let replaceName = ''
|
||||
for (let i = name.length; i > 1; i--) {
|
||||
const temp = name.substring(0, i)
|
||||
if (fragment.indexOf(temp) === 0) {
|
||||
replaceName = temp
|
||||
break
|
||||
}
|
||||
}
|
||||
if (replaceName) {
|
||||
area.push(tempArea)
|
||||
!currentCity && city.push(cities.find(item => item.code === cityCode))
|
||||
!currentProvince && province.push(provinces.find(item => item.code === provinceCode))
|
||||
fragment = fragment.replace(replaceName, '')
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 没有省市,区县市有可能重名,这里暂时不处理,因为概率极低,可以根据添加市解决
|
||||
for (let i = name.length; i > 1; i--) {
|
||||
const replaceName = name.substring(0, i)
|
||||
if (fragment.indexOf(replaceName) === 0) {
|
||||
area.push(tempArea)
|
||||
city.push(cities.find(item => item.code === cityCode))
|
||||
province.push(provinces.find(item => item.code === provinceCode))
|
||||
fragment = fragment.replace(replaceName, '')
|
||||
break
|
||||
}
|
||||
}
|
||||
if (area.length > 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 解析完省市区如果还存在地址,则默认为详细地址
|
||||
if (fragment.length > 0) {
|
||||
detail.push(fragment)
|
||||
}
|
||||
|
||||
return {
|
||||
province,
|
||||
city,
|
||||
area,
|
||||
detail,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是名字
|
||||
* @param fragment
|
||||
* @returns {string}
|
||||
*/
|
||||
const judgeFragmentIsName = (fragment, nameMaxLength) => {
|
||||
if (!fragment || !/[\u4E00-\u9FA5]/.test(fragment)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// 如果包含下列称呼,则认为是名字,可自行添加
|
||||
const nameCall = ['先生', '小姐', '同志', '哥哥', '姐姐', '妹妹', '弟弟', '妈妈', '爸爸', '爷爷', '奶奶', '姑姑', '舅舅']
|
||||
if (nameCall.find(item => ~fragment.indexOf(item))) {
|
||||
return fragment
|
||||
}
|
||||
|
||||
const filters = ['街道', '乡镇', '镇', '乡']
|
||||
if (~filters.findIndex(item => ~fragment.indexOf(item))) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// 如果百家姓里面能找到这个姓,并且长度在1-5之间
|
||||
const nameFirst = fragment.substring(0, 1)
|
||||
if (fragment.length <= nameMaxLength && fragment.length > 1 && ~zhCnNames.indexOf(nameFirst)) {
|
||||
return fragment
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配电话
|
||||
* @param address
|
||||
* @returns {{address: *, phone: string}}
|
||||
*/
|
||||
const filterPhone = (address) => {
|
||||
let phone = ''
|
||||
// 整理电话格式
|
||||
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')
|
||||
address = address.replace(/(\d{4}) \d{4} \d{4}/g, '$1$2$3')
|
||||
address = address.replace(/(\d{4})/g, '$1')
|
||||
|
||||
const mobileReg = /(\d{7,12})|(\d{3,4}-\d{6,8})|(86-[1][0-9]{10})|(86[1][0-9]{10})|([1][0-9]{10})/g
|
||||
const mobile = mobileReg.exec(address)
|
||||
if (mobile) {
|
||||
phone = mobile[0]
|
||||
address = address.replace(mobile[0], ' ')
|
||||
}
|
||||
return {address, phone}
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配邮编
|
||||
* @param address
|
||||
* @returns {{address: *, postalCode: string}}
|
||||
*/
|
||||
const filterPostalCode = (address) => {
|
||||
let postalCode = ''
|
||||
const postalCodeReg = /\d{6}/g
|
||||
const code = postalCodeReg.exec(address)
|
||||
if (code) {
|
||||
postalCode = code[0]
|
||||
address = address.replace(code[0], ' ')
|
||||
}
|
||||
return {address, postalCode}
|
||||
}
|
||||
|
||||
/**
|
||||
* 地址清洗
|
||||
* @param address
|
||||
* @returns {*}
|
||||
*/
|
||||
const cleanAddress = (address, textFilter = []) => {
|
||||
// 去换行等
|
||||
address = address
|
||||
.replace(/\r\n/g, ' ')
|
||||
.replace(/\n/g, ' ')
|
||||
.replace(/\t/g, ' ')
|
||||
|
||||
// 自定义去除关键字,可自行添加
|
||||
const search = [
|
||||
'详细地址',
|
||||
'收货地址',
|
||||
'收件地址',
|
||||
'地址',
|
||||
'所在地区',
|
||||
'地区',
|
||||
'姓名',
|
||||
'收货人',
|
||||
'收件人',
|
||||
'联系人',
|
||||
'收',
|
||||
'邮编',
|
||||
'联系电话',
|
||||
'电话',
|
||||
'联系人手机号码',
|
||||
'手机号码',
|
||||
'手机号',
|
||||
'自治区直辖县级行政区划',
|
||||
'省直辖县级行政区划',
|
||||
].concat(textFilter)
|
||||
search.forEach(str => {
|
||||
address = address.replace(new RegExp(str, 'g'), ' ')
|
||||
})
|
||||
|
||||
const pattern = new RegExp('[`~!@#$^&*()=|{}\':;\',\\[\\]\.<>/?~!@#¥……&*()——|{}【】‘;:”“’。,、?]', 'g')
|
||||
address = address.replace(pattern, ' ')
|
||||
|
||||
// 多个空格replace为一个
|
||||
address = address.replace(/ {2,}/g, ' ')
|
||||
|
||||
return address
|
||||
}
|
||||
|
||||
export default AddressParse
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,185 @@
|
||||
import cheerio from 'cheerio'
|
||||
import http from 'http'
|
||||
import path from 'path'
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const Province = () => ({
|
||||
code: '',
|
||||
name: '',
|
||||
children: []
|
||||
})
|
||||
|
||||
const Area = () => ({
|
||||
code: '',
|
||||
name: '',
|
||||
})
|
||||
|
||||
const City = () => ({
|
||||
code: '',
|
||||
name: '',
|
||||
children: []
|
||||
})
|
||||
|
||||
class GetMcaGovData {
|
||||
sourceUrl = ''
|
||||
headerClass = ''
|
||||
cityClass = ''
|
||||
constructor(sourceUrl, headerClass, cityClass) {
|
||||
this.sourceUrl = sourceUrl
|
||||
this.headerClass = headerClass
|
||||
this.cityClass = cityClass
|
||||
}
|
||||
|
||||
loadData = () => {
|
||||
if (!this.sourceUrl) {
|
||||
throw new Error('not set the url of parser !')
|
||||
}
|
||||
if (!this.headerClass || !this.cityClass) {
|
||||
throw new Error('not set the city or header class of header !')
|
||||
}
|
||||
try {
|
||||
http.get(this.sourceUrl, (res) => {
|
||||
// 设置编码
|
||||
res.setEncoding('utf8');
|
||||
// 当接收到数据时,会触发 'data' 事件的执行
|
||||
let html = "";
|
||||
res.on('data', (data) => {
|
||||
html += data;
|
||||
});
|
||||
// 数据接收完毕,会触发 'end' 事件的执行
|
||||
res.on('end', () => {
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
// 去除里面的空格和空值
|
||||
let elementsArea = $('.' + this.cityClass)
|
||||
// 注意这里的filter用的是cheerio的filter不是es6的
|
||||
elementsArea = elementsArea.filter((index, item) => $(item).text().trim())
|
||||
|
||||
let elementsProAndCity = $('.' + this.headerClass)
|
||||
elementsProAndCity = elementsProAndCity.filter((index, item) => $(item).text().trim())
|
||||
|
||||
console.log('省市总计数量:' + elementsProAndCity.length / 2)
|
||||
console.log('区总计数量:' + elementsArea.length / 2)
|
||||
let total = (elementsArea.length + elementsProAndCity.length) / 2
|
||||
console.log('省市区总计数量:' + total)
|
||||
|
||||
const listProvince = []
|
||||
for(let i = 0; i <= elementsProAndCity.length; i += 2) {
|
||||
const codeOrName = $(elementsProAndCity[i]).text().trim()
|
||||
const next = $(elementsProAndCity[i + 1]).text().trim()
|
||||
if (/\d/.test(codeOrName)) {
|
||||
// 省份
|
||||
if (codeOrName.endsWith('0000')) {
|
||||
const province = new Province()
|
||||
province.name = next
|
||||
province.code = codeOrName
|
||||
province.children = province.children || []
|
||||
listProvince.push(province)
|
||||
} else { // 市
|
||||
const city = new City()
|
||||
city.name = next
|
||||
city.code = codeOrName
|
||||
city.children = city.children || []
|
||||
|
||||
// 省份前缀
|
||||
const prefixProvinceCode = codeOrName.substring(0, 2)
|
||||
// 市区前缀
|
||||
const prefixCityCode = codeOrName.substring(2, 4)
|
||||
const provinceRegexp = new RegExp(`^${prefixProvinceCode}`)
|
||||
// 市前缀匹配,加入到省份里面
|
||||
const province = listProvince.find(item => {
|
||||
return provinceRegexp.test(item.code)
|
||||
})
|
||||
province && province.children.push(city)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理区和县
|
||||
listProvince.forEach(item => {
|
||||
// 省份前缀
|
||||
const prefixProvinceCode = item.code.substring(0, 2)
|
||||
const cityList = item.children
|
||||
|
||||
// 对于区,一个个处理,处理一个删除一个
|
||||
do {
|
||||
let codeOrName = $(elementsArea[0]).text().trim()
|
||||
let next = $(elementsArea[1]).text().trim()
|
||||
|
||||
// 匹配省份
|
||||
let regExp = new RegExp(`^${prefixProvinceCode}`)
|
||||
if (/\d/.test(codeOrName)) {
|
||||
if (regExp.test(codeOrName)) {
|
||||
const area = new Area()
|
||||
area.code = codeOrName
|
||||
area.name = next
|
||||
|
||||
// 取区中间两位市的代号
|
||||
const prefixCityCode = codeOrName.substring(2, 4)
|
||||
regExp = new RegExp(`^${prefixProvinceCode}${prefixCityCode}`)
|
||||
|
||||
// 找出市,找到就加入到市里的下面的区
|
||||
const currentCity = cityList.find(cityItem => regExp.test(cityItem.code) && cityItem.code.endsWith('00'))
|
||||
if (cityList.length && currentCity) {
|
||||
currentCity.children.push(area)
|
||||
} else {
|
||||
// 解析直辖市下面的区和县
|
||||
if (cityList.length === 0) {
|
||||
const city = new City()
|
||||
city.name = item.name
|
||||
city.code = item.code
|
||||
city.children.push(area)
|
||||
cityList.push(city)
|
||||
} else {
|
||||
cityList[0].children.push(area)
|
||||
}
|
||||
}
|
||||
elementsArea.splice(0, 2)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
} while (elementsArea.length > 0)
|
||||
})
|
||||
|
||||
let i = 0
|
||||
listProvince.forEach(p => {
|
||||
i++
|
||||
p.children.forEach(c => {
|
||||
i++
|
||||
c.children && c.children.forEach(a => {
|
||||
i++
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// 多了4个直辖市
|
||||
const parseTotal = i - 4
|
||||
console.log('解析完成总计数量:' + parseTotal, total)
|
||||
console.log('解析数量是否相等:' + (parseTotal === total ? '相等' : '不相等'))
|
||||
|
||||
if (parseTotal === total) {
|
||||
fs.writeFile(path.join(__dirname, 'provinceList.json'), JSON.stringify(listProvince), function(err) {
|
||||
if (err)
|
||||
return;
|
||||
console.log('导出成功')
|
||||
});
|
||||
} else {
|
||||
throw new Error('解析前后数量不相等,解析失败!')
|
||||
}
|
||||
})
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error('parse with error !')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// headerClass和cityClass在统计局的官网查看css的class
|
||||
const data = new GetMcaGovData(
|
||||
'http://www.mca.gov.cn/article/sj/xzqh/2020/2020/2020112010001.html',
|
||||
'xl7014987',
|
||||
'xl7114987'
|
||||
)
|
||||
data.loadData()
|
||||
@@ -0,0 +1,506 @@
|
||||
[
|
||||
"赵",
|
||||
"钱",
|
||||
"孙",
|
||||
"李",
|
||||
"周",
|
||||
"吴",
|
||||
"郑",
|
||||
"王",
|
||||
"冯",
|
||||
"陈",
|
||||
"楮",
|
||||
"卫",
|
||||
"蒋",
|
||||
"沈",
|
||||
"韩",
|
||||
"杨",
|
||||
"朱",
|
||||
"秦",
|
||||
"尤",
|
||||
"许",
|
||||
"何",
|
||||
"吕",
|
||||
"施",
|
||||
"张",
|
||||
"孔",
|
||||
"曹",
|
||||
"严",
|
||||
"华",
|
||||
"金",
|
||||
"魏",
|
||||
"陶",
|
||||
"姜",
|
||||
"戚",
|
||||
"谢",
|
||||
"邹",
|
||||
"喻",
|
||||
"柏",
|
||||
"水",
|
||||
"窦",
|
||||
"章",
|
||||
"云",
|
||||
"苏",
|
||||
"潘",
|
||||
"葛",
|
||||
"奚",
|
||||
"范",
|
||||
"彭",
|
||||
"郎",
|
||||
"鲁",
|
||||
"韦",
|
||||
"昌",
|
||||
"马",
|
||||
"苗",
|
||||
"凤",
|
||||
"花",
|
||||
"方",
|
||||
"俞",
|
||||
"任",
|
||||
"袁",
|
||||
"柳",
|
||||
"酆",
|
||||
"鲍",
|
||||
"史",
|
||||
"唐",
|
||||
"费",
|
||||
"廉",
|
||||
"岑",
|
||||
"薛",
|
||||
"雷",
|
||||
"贺",
|
||||
"倪",
|
||||
"汤",
|
||||
"滕",
|
||||
"殷",
|
||||
"罗",
|
||||
"毕",
|
||||
"郝",
|
||||
"邬",
|
||||
"安",
|
||||
"常",
|
||||
"乐",
|
||||
"于",
|
||||
"时",
|
||||
"傅",
|
||||
"皮",
|
||||
"卞",
|
||||
"齐",
|
||||
"康",
|
||||
"伍",
|
||||
"余",
|
||||
"元",
|
||||
"卜",
|
||||
"顾",
|
||||
"孟",
|
||||
"平",
|
||||
"黄",
|
||||
"和",
|
||||
"穆",
|
||||
"萧",
|
||||
"尹",
|
||||
"姚",
|
||||
"邵",
|
||||
"湛",
|
||||
"汪",
|
||||
"祁",
|
||||
"毛",
|
||||
"禹",
|
||||
"狄",
|
||||
"米",
|
||||
"贝",
|
||||
"明",
|
||||
"臧",
|
||||
"计",
|
||||
"伏",
|
||||
"成",
|
||||
"戴",
|
||||
"谈",
|
||||
"宋",
|
||||
"茅",
|
||||
"庞",
|
||||
"熊",
|
||||
"纪",
|
||||
"舒",
|
||||
"屈",
|
||||
"项",
|
||||
"祝",
|
||||
"董",
|
||||
"梁",
|
||||
"杜",
|
||||
"阮",
|
||||
"蓝",
|
||||
"闽",
|
||||
"席",
|
||||
"季",
|
||||
"麻",
|
||||
"强",
|
||||
"贾",
|
||||
"路",
|
||||
"娄",
|
||||
"危",
|
||||
"江",
|
||||
"童",
|
||||
"颜",
|
||||
"郭",
|
||||
"梅",
|
||||
"盛",
|
||||
"林",
|
||||
"刁",
|
||||
"锺",
|
||||
"徐",
|
||||
"丘",
|
||||
"骆",
|
||||
"高",
|
||||
"夏",
|
||||
"蔡",
|
||||
"田",
|
||||
"樊",
|
||||
"胡",
|
||||
"凌",
|
||||
"霍",
|
||||
"虞",
|
||||
"万",
|
||||
"支",
|
||||
"柯",
|
||||
"昝",
|
||||
"管",
|
||||
"卢",
|
||||
"莫",
|
||||
"经",
|
||||
"房",
|
||||
"裘",
|
||||
"缪",
|
||||
"干",
|
||||
"解",
|
||||
"应",
|
||||
"宗",
|
||||
"丁",
|
||||
"宣",
|
||||
"贲",
|
||||
"邓",
|
||||
"郁",
|
||||
"单",
|
||||
"杭",
|
||||
"洪",
|
||||
"包",
|
||||
"诸",
|
||||
"左",
|
||||
"石",
|
||||
"崔",
|
||||
"吉",
|
||||
"钮",
|
||||
"龚",
|
||||
"程",
|
||||
"嵇",
|
||||
"邢",
|
||||
"滑",
|
||||
"裴",
|
||||
"陆",
|
||||
"荣",
|
||||
"翁",
|
||||
"荀",
|
||||
"羊",
|
||||
"於",
|
||||
"惠",
|
||||
"甄",
|
||||
"麹",
|
||||
"家",
|
||||
"封",
|
||||
"芮",
|
||||
"羿",
|
||||
"储",
|
||||
"靳",
|
||||
"汲",
|
||||
"邴",
|
||||
"糜",
|
||||
"松",
|
||||
"井",
|
||||
"段",
|
||||
"富",
|
||||
"巫",
|
||||
"乌",
|
||||
"焦",
|
||||
"巴",
|
||||
"弓",
|
||||
"牧",
|
||||
"隗",
|
||||
"山",
|
||||
"谷",
|
||||
"车",
|
||||
"侯",
|
||||
"宓",
|
||||
"蓬",
|
||||
"全",
|
||||
"郗",
|
||||
"班",
|
||||
"仰",
|
||||
"秋",
|
||||
"仲",
|
||||
"伊",
|
||||
"宫",
|
||||
"宁",
|
||||
"仇",
|
||||
"栾",
|
||||
"暴",
|
||||
"甘",
|
||||
"斜",
|
||||
"厉",
|
||||
"戎",
|
||||
"祖",
|
||||
"武",
|
||||
"符",
|
||||
"刘",
|
||||
"景",
|
||||
"詹",
|
||||
"束",
|
||||
"龙",
|
||||
"叶",
|
||||
"幸",
|
||||
"司",
|
||||
"韶",
|
||||
"郜",
|
||||
"黎",
|
||||
"蓟",
|
||||
"薄",
|
||||
"印",
|
||||
"宿",
|
||||
"白",
|
||||
"怀",
|
||||
"蒲",
|
||||
"邰",
|
||||
"从",
|
||||
"鄂",
|
||||
"索",
|
||||
"咸",
|
||||
"籍",
|
||||
"赖",
|
||||
"卓",
|
||||
"蔺",
|
||||
"屠",
|
||||
"蒙",
|
||||
"池",
|
||||
"乔",
|
||||
"阴",
|
||||
"郁",
|
||||
"胥",
|
||||
"能",
|
||||
"苍",
|
||||
"双",
|
||||
"闻",
|
||||
"莘",
|
||||
"党",
|
||||
"翟",
|
||||
"谭",
|
||||
"贡",
|
||||
"劳",
|
||||
"逄",
|
||||
"姬",
|
||||
"申",
|
||||
"扶",
|
||||
"堵",
|
||||
"冉",
|
||||
"宰",
|
||||
"郦",
|
||||
"雍",
|
||||
"郤",
|
||||
"璩",
|
||||
"桑",
|
||||
"桂",
|
||||
"濮",
|
||||
"牛",
|
||||
"寿",
|
||||
"通",
|
||||
"边",
|
||||
"扈",
|
||||
"燕",
|
||||
"冀",
|
||||
"郏",
|
||||
"浦",
|
||||
"尚",
|
||||
"农",
|
||||
"温",
|
||||
"别",
|
||||
"庄",
|
||||
"晏",
|
||||
"柴",
|
||||
"瞿",
|
||||
"阎",
|
||||
"充",
|
||||
"慕",
|
||||
"连",
|
||||
"茹",
|
||||
"习",
|
||||
"宦",
|
||||
"艾",
|
||||
"鱼",
|
||||
"容",
|
||||
"向",
|
||||
"古",
|
||||
"易",
|
||||
"慎",
|
||||
"戈",
|
||||
"廖",
|
||||
"庾",
|
||||
"终",
|
||||
"暨",
|
||||
"居",
|
||||
"衡",
|
||||
"步",
|
||||
"都",
|
||||
"耿",
|
||||
"满",
|
||||
"弘",
|
||||
"匡",
|
||||
"国",
|
||||
"文",
|
||||
"寇",
|
||||
"广",
|
||||
"禄",
|
||||
"阙",
|
||||
"东",
|
||||
"欧",
|
||||
"殳",
|
||||
"沃",
|
||||
"利",
|
||||
"蔚",
|
||||
"越",
|
||||
"夔",
|
||||
"隆",
|
||||
"师",
|
||||
"巩",
|
||||
"厍",
|
||||
"聂",
|
||||
"晁",
|
||||
"勾",
|
||||
"敖",
|
||||
"融",
|
||||
"冷",
|
||||
"訾",
|
||||
"辛",
|
||||
"阚",
|
||||
"那",
|
||||
"简",
|
||||
"饶",
|
||||
"空",
|
||||
"曾",
|
||||
"毋",
|
||||
"沙",
|
||||
"乜",
|
||||
"养",
|
||||
"鞠",
|
||||
"须",
|
||||
"丰",
|
||||
"巢",
|
||||
"关",
|
||||
"蒯",
|
||||
"相",
|
||||
"查",
|
||||
"后",
|
||||
"荆",
|
||||
"红",
|
||||
"游",
|
||||
"竺",
|
||||
"权",
|
||||
"逑",
|
||||
"盖",
|
||||
"益",
|
||||
"桓",
|
||||
"公",
|
||||
"万俟",
|
||||
"司马",
|
||||
"上官",
|
||||
"欧阳",
|
||||
"夏侯",
|
||||
"诸葛",
|
||||
"闻人",
|
||||
"东方",
|
||||
"赫连",
|
||||
"皇甫",
|
||||
"尉迟",
|
||||
"公羊",
|
||||
"澹台",
|
||||
"公冶",
|
||||
"宗政",
|
||||
"濮阳",
|
||||
"淳于",
|
||||
"单于",
|
||||
"太叔",
|
||||
"申屠",
|
||||
"公孙",
|
||||
"仲孙",
|
||||
"轩辕",
|
||||
"令狐",
|
||||
"锺离",
|
||||
"宇文",
|
||||
"长孙",
|
||||
"慕容",
|
||||
"鲜于",
|
||||
"闾丘",
|
||||
"司徒",
|
||||
"司空",
|
||||
"丌官",
|
||||
"司寇",
|
||||
"仉",
|
||||
"督",
|
||||
"子车",
|
||||
"颛孙",
|
||||
"端木",
|
||||
"巫马",
|
||||
"公西",
|
||||
"漆雕",
|
||||
"乐正",
|
||||
"壤驷",
|
||||
"公良",
|
||||
"拓拔",
|
||||
"夹谷",
|
||||
"宰父",
|
||||
"谷梁",
|
||||
"晋",
|
||||
"楚",
|
||||
"阎",
|
||||
"法",
|
||||
"汝",
|
||||
"鄢",
|
||||
"涂",
|
||||
"钦",
|
||||
"段干",
|
||||
"百里",
|
||||
"东郭",
|
||||
"南门",
|
||||
"呼延",
|
||||
"归",
|
||||
"海",
|
||||
"羊舌",
|
||||
"微生",
|
||||
"岳",
|
||||
"帅",
|
||||
"缑",
|
||||
"亢",
|
||||
"况",
|
||||
"后",
|
||||
"有",
|
||||
"琴",
|
||||
"梁丘",
|
||||
"左丘",
|
||||
"东门",
|
||||
"西门",
|
||||
"商",
|
||||
"牟",
|
||||
"佘",
|
||||
"佴",
|
||||
"伯",
|
||||
"赏",
|
||||
"南宫",
|
||||
"墨",
|
||||
"哈",
|
||||
"谯",
|
||||
"笪",
|
||||
"年",
|
||||
"爱",
|
||||
"阳",
|
||||
"佟",
|
||||
"第五",
|
||||
"言",
|
||||
"福"
|
||||
]
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
[{"code":"11","name":"北京市"},{"code":"12","name":"天津市"},{"code":"13","name":"河北省"},{"code":"14","name":"山西省"},{"code":"15","name":"内蒙古自治区"},{"code":"21","name":"辽宁省"},{"code":"22","name":"吉林省"},{"code":"23","name":"黑龙江省"},{"code":"31","name":"上海市"},{"code":"32","name":"江苏省"},{"code":"33","name":"浙江省"},{"code":"34","name":"安徽省"},{"code":"35","name":"福建省"},{"code":"36","name":"江西省"},{"code":"37","name":"山东省"},{"code":"41","name":"河南省"},{"code":"42","name":"湖北省"},{"code":"43","name":"湖南省"},{"code":"44","name":"广东省"},{"code":"45","name":"广西壮族自治区"},{"code":"46","name":"海南省"},{"code":"50","name":"重庆市"},{"code":"51","name":"四川省"},{"code":"52","name":"贵州省"},{"code":"53","name":"云南省"},{"code":"54","name":"西藏自治区"},{"code":"61","name":"陕西省"},{"code":"62","name":"甘肃省"},{"code":"63","name":"青海省"},{"code":"64","name":"宁夏回族自治区"},{"code":"65","name":"新疆维吾尔自治区"}]
|
||||
Reference in New Issue
Block a user