forked from cnluzhang/chinaddress
-
Notifications
You must be signed in to change notification settings - Fork 1
/
extract.js
137 lines (124 loc) · 3.63 KB
/
extract.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// city.json 及 province.json 来自
// https://misc.360buyimg.com/jdf/1.0.0/ui/area/1.0.0/area.js
const fs = require('fs')
const https = require('https')
const url = 'https://misc.360buyimg.com/jdf/1.0.0/ui/area/1.0.0/area.js'
let info = require('./cache/pingyin.json')
main().then(process.exit, process.exit)
async function main() {
let areas = {}
try {
console.log('Fetching Provinces and Cities')
const {provincesRaw, citiesRaw} = await getProvincesAndCities()
provincesRaw.split(',').forEach(item => {
let provinceName = item.split('|')[0]
areas[provinceName] = {
id: item.split('|')[1],
capital: item.split('|')[2],
isMunicipality: !!item.split('|')[3]
}
})
console.log('Extracting areas')
for (const key of Object.keys(areas)) {
let cities = {}
const provinceId = areas[key].id
citiesRaw[provinceId].split(',').forEach(val => {
const [city, id] = val.split('|')
cities[city] = id
})
if (areas[key].isMunicipality) {
attempt(() => {
const temp = {}
temp[info[key].fullName] = Object.keys(cities)
cities = temp
})
}
areas[key] = cities
}
console.log('Filling districts')
areas = await fillDistricts(areas)
if (areas['港澳']) {
areas['香港特别行政区'] = {
'香港特别行政区': areas['港澳']['香港特别行政区']
}
areas['澳门特别行政区'] = {
'澳门特别行政区': areas['港澳']['澳门特别行政区']
}
}
delete areas['港澳']
console.log('Filling districts')
for (const province of Object.keys(areas)) {
if (!info[province]) {
continue
}
console.log('Filling %s', province)
const {pingyin, fullName} = info[province]
const provinceData = {}
provinceData[fullName] = areas[province]
areas[fullName] = areas[province]
delete areas[province]
fs.writeFileSync('./src/' + pingyin + '.json', JSON.stringify(provinceData, null, 2))
}
fs.writeFileSync('./cache/areas.json', JSON.stringify(areas, null, 2))
} catch (err) {
console.error(err)
}
}
async function fillDistricts(areas) {
for (const key of Object.keys(areas)) {
const province = areas[key]
for (const city in province) {
const cityId = province[city]
if (typeof cityId !== 'string') {
continue
}
try {
let districts = await getDistricts(cityId)
districts = districts.map(item => item.name)
province[city] = districts
} catch (err) {
console.error(err)
}
}
}
return areas
}
function getProvincesAndCities() {
return new Promise((resolve, reject) => {
https.get(url, res => {
let str = ''
res.on('data', (d) => {
str = str.concat(d.toString())
})
res.on('end', () => {
const provincesRaw = str.match(/a\.each\(("[\w\W]+?")\.split/mi)[1]
const citiesRaw = str.match(/a\.each\(({[\w\W]+?}),\s?function/mi)[1]
resolve({provincesRaw: eval('(' + provincesRaw + ')'), citiesRaw: eval('(' + citiesRaw + ')')})
})
res.on('error', err => {
reject(err)
})
})
})
}
function getDistricts(fid) {
return new Promise((resolve, reject) => {
console.log('Fetching %s', fid)
https.get(`https://fts.jd.com/area/get?fid=${fid}`, res => {
let result = ''
res.on('data', (d) => {
result += d.toString()
})
res.on('end', () => {
resolve(JSON.parse(result))
})
res.on('error', reject)
})
})
}
function attempt(cb) {
try {
cb()
} catch (err) {
}
}