Jelajahi Sumber

refactor: 代码重构,新增保留编码的联动数据

modood 7 tahun lalu
induk
melakukan
41d7cc0248
6 mengubah file dengan 51 tambahan dan 454 penghapusan
  1. 44 13
      README.md
  2. 0 164
      index.js
  3. 0 3
      output.js
  4. 7 7
      package.json
  5. TEMPAT SAMPAH
      preview.png
  6. 0 267
      spider.js

+ 44 - 13
README.md

@@ -19,13 +19,16 @@
 
 | 文件列表                                     | 下载地址       |
 |:---------------------------------------------|:---------------|
-| 省份数据                                     | [provinces.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/provinces.json) |
-| 城市数据                                     | [cities.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/cities.json) |
-| 区县数据                                     | [areas.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/areas.json) |
-| 乡镇(街道)数据                             | [streets.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/streets.json) |
-| “省份、城市” 二级联动数据                    | [address2.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/address2.json) |
-| “省份、城市、区县” 三级联动数据              | [address3.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/address3.json) |
-| “省份、城市、区县、乡镇” 四级联动数据        | [address4.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/address4.json) |
+| 省份数据                                        | [provinces.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/provinces.json) |
+| 城市数据                                        | [cities.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/cities.json) |
+| 区县数据                                        | [areas.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/areas.json) |
+| 乡镇(街道)数据                                | [streets.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/streets.json) |
+| “省份、城市” 二级联动数据                       | [pc.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pc.json) |
+| “省份、城市” 二级联动数据(带编码)             | [pc-code.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pc-code.json) |
+| “省份、城市、区县” 三级联动数据                 | [pca.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pca.json) |
+| “省份、城市、区县” 三级联动数据(带编码)       | [pca-code.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pca-code.json) |
+| “省份、城市、区县、乡镇” 四级联动数据           | [pcas.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pcas.json) |
+| “省份、城市、区县、乡镇” 四级联动数据(带编码) | [pcas-code.json](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pcas-code.json) |
 
 ## Usage
 
@@ -36,8 +39,37 @@ $ npm install
 
 $ npm run build
 ```
-
-![preview](preview.png)
+```
+[1/1] 正在抓取省份、城市和区县数据...
+[1/2848] 正在抓取乡镇数据,当前区县: 110105 朝阳区
+[2/2848] 正在抓取乡镇数据,当前区县: 110101 东城区
+[3/2848] 正在抓取乡镇数据,当前区县: 110106 丰台区
+[4/2848] 正在抓取乡镇数据,当前区县: 110109 门头沟区
+[5/2848] 正在抓取乡镇数据,当前区县: 110112 通州区
+[6/2848] 正在抓取乡镇数据,当前区县: 110102 西城区
+[7/2848] 正在抓取乡镇数据,当前区县: 110107 石景山区
+[8/2848] 正在抓取乡镇数据,当前区县: 110111 房山区
+[9/2848] 正在抓取乡镇数据,当前区县: 110108 海淀区
+[10/2848] 正在抓取乡镇数据,当前区县: 110113 顺义区
+...
+[2841/2848] 正在抓取乡镇数据,当前区县: 659006 铁门关市
+[2842/2848] 正在抓取乡镇数据,当前区县: 210522 桓仁满族自治县
+[2843/2848] 正在抓取乡镇数据,当前区县: 210881 盖州市
+[2844/2848] 正在抓取乡镇数据,当前区县: 130902 新华区
+[2845/2848] 正在抓取乡镇数据,当前区县: 150782 牙克石市
+[2846/2848] 正在抓取乡镇数据,当前区县: 542421 那曲县
+[2847/2848] 正在抓取乡镇数据,当前区县: 610122 蓝田县
+[2848/2848] 正在抓取乡镇数据,当前区县: 610322 凤翔县
+[1/5] 正在导出 “省份” JSON 数据...
+[2/5] 正在导出 “城市” JSON 数据...
+[3/5] 正在导出 “区县” JSON 数据...
+[4/5] 正在导出 “乡镇” JSON 数据...
+[5/5] 数据抓取完成!
+[1/4] 正在导出 “省份、城市” 二级联动数据...
+[2/4] 正在导出 “省份、城市、区县” 三级联动数据...
+[3/4] 正在导出 “省份、城市、区县、乡镇” 四级联动数据...该步骤操作数据较多,比较耗时,请耐心等候...
+[4/4] 数据更新完成!
+```
 
 >  提示:
 >
@@ -45,12 +77,12 @@ $ npm run build
 >
 >  但是不会影响其它数据的顺序以及所有数据的完整性。
 
-## TEST
+## Testing
 
 ```
 $ npm test
 
-> mocha -t 5000
+> eslint . && mocha -t 5000
 
   中华人民共和国行政区划:
     ✓ 省份数据
@@ -75,5 +107,4 @@ $ npm test
 
 ## License
 
-this repo is released under the [MIT License](http://www.opensource.org/licenses/MIT).
-
+this repo is released under the [WTFPL](http://www.wtfpl.net/) – Do What the Fuck You Want to Public License.

+ 0 - 164
index.js

@@ -1,164 +0,0 @@
-'use strict'
-
-var fs = require('fs')
-var path = require('path')
-
-var spider = require('./spider')
-
-/**
- * 输出 JSON 数据
- * @Author   https://github.com/modood
- * @DateTime 2016-10-08 17:16
- */
-module.exports = {
-  outputJSON: outputJSON,
-  provinces: require(path.resolve(__dirname, 'dist/provinces.json')),
-  cities: require(path.resolve(__dirname, 'dist/cities.json')),
-  areas: require(path.resolve(__dirname, 'dist/areas.json')),
-  streets: require(path.resolve(__dirname, 'dist/streets.json')),
-  address2: require(path.resolve(__dirname, 'dist/address2.json')),
-  address3: require(path.resolve(__dirname, 'dist/address3.json')),
-  address4: require(path.resolve(__dirname, 'dist/address4.json'))
-}
-
-/**
- * 输出 JSON 数据到 dist 目录下
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-19 16:45
- */
-function outputJSON () {
-  spider.getData(function (err, result) {
-    if (err) return console.log(err)
-
-    var provinces = result.provinces
-    var cities = result.cities
-    var areas = result.areas
-    var streets = result.streets
-
-    console.log('[1/3] 正在生成 “省份、城市” 二级联动数据...')
-    var pc = getAddressPC(provinces, cities)
-    console.log('[2/3] 正在生成 “省份、城市、区县” 三级联动数据...')
-    var pca = getAddressPCA(provinces, cities, areas, streets)
-    console.log('[3/3] 正在生成 “省份、城市、区县、乡镇” 四级联动数据...')
-    var pcas = getAddressPCAS(provinces, cities, areas, streets)
-
-    console.log('[1/7] 正在导出 “省份” JSON 数据...')
-    outputFile('provinces', provinces)
-    console.log('[2/7] 正在导出 “城市” JSON 数据...')
-    outputFile('cities', cities)
-    console.log('[3/7] 正在导出 “区县” JSON 数据...')
-    outputFile('areas', areas)
-    console.log('[4/7] 正在导出 “乡镇” JSON 数据...')
-    outputFile('streets', streets)
-    console.log('[5/7] 正在导出 “省份、城市”二级联动 JSON 数据...')
-    outputFile('address2', pc)
-    console.log('[6/7] 正在导出 “省份、城市、区县”三级联动 JSON 数据...')
-    outputFile('address3', pca)
-    console.log('[7/7] 正在导出 “省份、城市、区县、乡镇” 四级联动 JSON 数据...')
-    outputFile('address4', pcas)
-
-    console.log('数据更新完成!')
-  })
-}
-
-/**
- * 获取省市二级联动数据
- * @Author   https://github.com/modood
- * @DateTime 2016-10-09 15:25
- */
-function getAddressPC (provinces, cities) {
-  var doc = {}
-
-  // 过滤三级联动时才有效的名称
-  var filterName = ['县', '省直辖县级行政区划', '自治区直辖县级行政区划']
-
-  provinces.forEach(function (p) {
-    doc[p.name] = cities.filter(function (c) {
-      return p.code === c.parent_code && filterName.every(function (filterName) {
-        return c.name !== filterName
-      })
-    }).map(function (c) {
-      return c.name === '市辖区' ? p.name : c.name
-    })
-  })
-
-  return doc
-}
-
-/**
- * 获取省市区三级联动数据
- * @Author   https://github.com/modood
- * @DateTime 2016-10-09 16:00
- */
-function getAddressPCA (provinces, cities, areas, streets) {
-  var doc = {}
-
-  provinces.forEach(function (p) {
-    doc[p.name] = {}
-
-    cities.filter(function (c) {
-      return p.code === c.parent_code
-    }).forEach(function (c) {
-      // 特殊城市单独处理(中山市、东莞市、儋州市和嘉峪关市没有县级行政区划)
-      if (['441900', '442000', '460400', '620200'].indexOf(c.code) !== -1) {
-        doc[p.name][c.name] = streets.filter(function (s) {
-          return (c.code === '620200' ? '620201' : c.code) === s.parent_code
-        }).map(function (s) {
-          return s.name
-        })
-        return
-      }
-      doc[p.name][c.name] = areas.filter(function (a) {
-        return c.code === a.parent_code
-      }).map(function (a) {
-        return a.name
-      })
-    })
-  })
-
-  return doc
-}
-
-/**
- * 获取省市区镇四级联动数据
- * @Author   https://github.com/modood
- * @DateTime 2016-10-09 16:09
- */
-function getAddressPCAS (provinces, cities, areas, streets) {
-  var doc = {}
-
-  provinces.forEach(function (p) {
-    doc[p.name] = {}
-
-    cities.filter(function (c) {
-      return p.code === c.parent_code
-    }).forEach(function (c) {
-      doc[p.name][c.name] = {}
-
-      areas.filter(function (a) {
-        return c.code === a.parent_code
-      }).forEach(function (a) {
-        doc[p.name][c.name][a.name] = streets.filter(function (s) {
-          return a.code === s.parent_code
-        }).map(function (s) {
-          return s.name.replace('办事处', '')
-        })
-      })
-    })
-  })
-  // 特殊区县单独处理(福建省泉州市金门县没有乡镇级行政区划)
-  doc['福建省']['泉州市']['金门县'].push('金门县')
-
-  return doc
-}
-
-/**
- * 输出 JSON 文件
- * @Author   https://github.com/modood
- * @DateTime 2016-10-08 17:16
- */
-function outputFile (name, data) {
-  var fileName = 'dist/' + name + '.json'
-
-  fs.writeFileSync(path.resolve(__dirname, fileName), JSON.stringify(data))
-}

+ 0 - 3
output.js

@@ -1,3 +0,0 @@
-'use strict'
-
-require('./index').outputJSON()

+ 7 - 7
package.json

@@ -1,11 +1,11 @@
 {
   "name": "china-division",
-  "version": "1.1.2",
+  "version": "1.2.0",
   "description": "中华人民共和国行政区划:省份、城市、区县、乡镇(街道)",
-  "main": "index.js",
+  "main": "scripts/exp.js",
   "scripts": {
     "test": "eslint . && mocha -t 5000",
-    "build": "node output.js",
+    "build": "node scripts/get.js && node scripts/fmt.js && npm test",
     "precommit": "npm test"
   },
   "repository": {
@@ -29,12 +29,10 @@
     "email": "modood@qq.com",
     "url": "https://github.com/modood"
   },
-  "dependencies": {
+  "dependencies": {},
+  "devDependencies": {
     "async": "^2.1.4",
     "bufferhelper": "^0.2.1",
-    "iconv-lite": "^0.4.15"
-  },
-  "devDependencies": {
     "eslint": "^4.4.1",
     "eslint-config-standard": "^10.2.1",
     "eslint-plugin-import": "^2.7.0",
@@ -42,6 +40,8 @@
     "eslint-plugin-promise": "^3.5.0",
     "eslint-plugin-standard": "^3.0.1",
     "husky": "^0.13.4",
+    "iconv-lite": "^0.4.15",
+    "lodash": "^4.17.4",
     "mocha": "^3.1.0"
   },
   "license": "MIT",

TEMPAT SAMPAH
preview.png


+ 0 - 267
spider.js

@@ -1,267 +0,0 @@
-'use strict'
-
-var http = require('http')
-
-var async = require('async')
-var iconv = require('iconv-lite')
-var BufferHelper = require('bufferhelper')
-
-var al = 0
-var ai = 0
-
-/**
- * 从国家统计局(http://www.stats.gov.cn/)抓取县级以及县级以上行政区划数据
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-19 16:32
- */
-function fetch (callback) {
-  // 数据截止 2016 年 07 月 31 日(发布时间:2017-03-10 10:33)
-  http.get('http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html', function (res) {
-    var rawData = ''
-    var statusCode = res.statusCode
-
-    console.log('[1/1] 正在抓取省份、城市和区县数据...')
-
-    if (statusCode !== 200) {
-      res.resume()
-      return callback(new Error('Request Failed. Status Code: ' + statusCode))
-    }
-
-    res.setEncoding('utf8')
-
-    res.on('data', function (chunk) {
-      rawData += chunk
-    })
-
-    res.on('end', function () {
-      var current
-      var result = {}
-      var reg = /<span lang="EN-US">(.*?)<span>(?:&nbsp;)+ <\/span><\/span>(?:<\/b>)?(?:<b>)?<span style="font-family: 宋体">(.*?)<\/span>/g
-
-      while ((current = reg.exec(rawData)) !== null) {
-        result[current[1]] = current[2].trim()
-      }
-      return callback(null, result)
-    })
-  }).on('error', callback)
-}
-
-/**
- * 从国家统计局(http://www.stats.gov.cn/)抓取城乡行政区划数据
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-19 16:35
- */
-function fetchStreets (area, callback) {
-  var html = ''
-  var areaCode = area.code
-  var areaName = area.name
-
-  // 特殊城市单独处理(中山市、东莞市、儋州市没有县级行政区划)
-  switch (areaCode) {
-    case '441900': html = '44/4419.html'; break
-    case '442000': html = '44/4420.html'; break
-    case '460400': html = '46/4604.html'; break
-    default: html = areaCode.substr(0, 2) + '/' + areaCode.substr(2, 2) + '/' + areaCode + '.html'
-  }
-
-  // 数据截止 2016 年 07 月 31 日(发布时间:2017-05-16)
-  http.get('http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/' + html, function (res) {
-    var bufferHelper = new BufferHelper()
-    var statusCode = res.statusCode
-
-    if (statusCode !== 200 && statusCode !== 404) {
-      res.resume()
-      return fetchStreets(area, callback)
-    }
-
-    // 特殊城市或区县抓取乡镇数据不打印输出
-    if ([
-      '441900', // 东莞市
-      '442000', // 中山市
-      '460400', // 儋州市
-      '460321', // 三沙市-西沙群岛
-      '460322', // 三沙市-南沙群岛
-      '460323', // 三沙市-中沙群岛的岛礁及其海域
-      '620201' // 嘉峪关市
-    ].indexOf(areaCode) === -1) {
-      console.log('[' + ++ai + '/' + al + '] 正在抓取乡镇数据,当前区县:', areaCode, areaName)
-    }
-
-    if (statusCode === 404) {
-      res.resume()
-      return callback(null, {})
-    }
-
-    res.on('data', function (chunk) {
-      bufferHelper.concat(chunk)
-    })
-
-    res.on('end', function () {
-      var rawData = iconv.decode(bufferHelper.toBuffer(), 'GBK')
-      var current
-      var result = {}
-      var reg = /<tr class='.*?'><td><a href=.*?>(.*?)<\/a><\/td><td><a href=.*?>(.*?)<\/a><\/td><\/tr>/g
-
-      while ((current = reg.exec(rawData)) !== null) {
-        result[current[1]] = current[2].trim()
-      }
-      return callback(null, result)
-    })
-  }).on('error', function () {
-    console.log('连接超时,马上重试...')
-    fetchStreets(area, callback)
-  })
-}
-
-/**
- * 提取省份、城市和区县数据
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-20 13:18
- */
-function pick (callback) {
-  fetch(function (err, data) {
-    var provinces = []
-    var cities = []
-    var areas = []
-
-    if (err) return callback(err)
-
-    for (var k in data) {
-      if (k.substr(2, 4) === '0000') {
-        // 省份数据
-        provinces.push({
-          code: k,
-          name: data[k]
-        })
-      } else if (k.substr(4, 2) === '00' && k.substr(2, 4) !== '0000') {
-        // 城市数据
-        cities.push({
-          code: k,
-          name: data[k],
-          parent_code: k.substr(0, 2) + '0000'
-        })
-      } else if (k.substr(4, 2) !== '00' && data[k] !== '市辖区') {
-        // 区县数据
-        areas.push({
-          code: k,
-          name: data[k],
-          parent_code: k.substr(0, 4) + '00'
-        })
-      }
-    }
-
-    return callback(null, {
-      provinces: provinces,
-      cities: cities,
-      areas: areas
-    })
-  })
-}
-
-/**
- * 提取乡镇数据
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-20 13:17
- */
-function pickStreets (areas, callback) {
-  var streets = []
-
-  async.mapLimit(areas, 10, function (item, cb) {
-    al = areas.length
-    fetchStreets(item, function (err, data) {
-      if (err) return cb(err)
-
-      for (var k in data) {
-        // 乡镇数据
-        streets.push({
-          code: k,
-          name: data[k],
-          parent_code: k.substr(0, 6)
-        })
-      }
-      return cb(null)
-    })
-  }, function (err) {
-    if (err) console.log('getStreets timeout, ignored:\n', err)
-    return callback(null, streets)
-  })
-}
-
-/**
- * 特殊城市单独处理
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-20 15:11
- */
-function handleSpecialCities (callback) {
-  // 1. 中山市、东莞市、儋州市没有县级行政区划
-  // 2. 嘉峪关市下有一个县级行政区划叫市辖区(code: 620201),
-  //    因此也视为没有县级行政区划,但是 code 需要保留处理。
-  // 3. 三沙市下有县级行政区划,但是在 “最新县及县以上行政区划代码” 中
-  //    没有,因此需要手动加上。
-  // 4. 福建省泉州市金门县没有乡镇级行政区划
-  var areas = [
-    { code: '442000', name: '中山市', parent_code: '442000' },
-    { code: '441900', name: '东莞市', parent_code: '441900' },
-    { code: '460400', name: '儋州市', parent_code: '460400' },
-    { code: '620201', name: '嘉峪关市', parent_code: '620200' },
-    { code: '460321', name: '西沙群岛', parent_code: '460300' },
-    { code: '460322', name: '南沙群岛', parent_code: '460300' },
-    { code: '460323', name: '中沙群岛的岛礁及其海域', parent_code: '460300' }
-  ]
-  var streets = []
-
-  async.each(areas, function (area, cb) {
-    fetchStreets(area, function (err, data) {
-      if (err) return cb(err)
-
-      for (var k in data) {
-        streets.push({
-          code: k,
-          name: data[k],
-          parent_code: k.substr(0, 6)
-        })
-      }
-      return cb(null)
-    })
-  }, function (err, result) {
-    if (err) return callback(err)
-
-    return callback(null, {
-      areas: areas,
-      streets: streets
-    })
-  })
-}
-
-/**
- * 对抓取到的数据进行处理,提取出“省份”、“城市”、“区县”和“乡镇”四种数据
- * @author modood <https://github.com/modood>
- * @datetime 2016-12-19 16:37
- */
-exports.getData = function (callback) {
-  async.auto({
-    pca: function (cb) {
-      pick(cb)
-    },
-    streets: ['pca', function (result, cb) {
-      var areas = result.pca.areas
-      pickStreets(areas, cb)
-    }]
-  }, function (err, result) {
-    if (err) return callback(err)
-
-    handleSpecialCities(function (err, r) {
-      if (err) return callback(err)
-
-      var areas = result.pca.areas.concat(r.areas)
-      var streets = result.streets.concat(r.streets)
-
-      return callback(null, {
-        provinces: result.pca.provinces,
-        cities: result.pca.cities,
-        areas: areas,
-        streets: streets
-      })
-    })
-  })
-}