合并选择器和地址解析

This commit is contained in:
2022-03-26 16:21:52 +08:00
commit 1fa9959cdf
42 changed files with 24100 additions and 0 deletions
+114
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -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}
+18
View File
@@ -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
+544
View File
@@ -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
+185
View File
@@ -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()
+506
View File
@@ -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
+1
View File
@@ -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":"新疆维吾尔自治区"}]