最近要實現一個顯示各個城市信息的功能, 好吧,後臺丟了一個包含一堆城市的excel給我,發現不只有每一個省的直轄市,還有二三線等的城市,數量還很多,一個個去查還挺浪費時間的,那爲何不寫個腳本去實現批量查詢呢。javascript
實現了讀取文件批量查詢後,順便寫了個網頁版批量查詢地理經緯度,php
網站上這種類型的接口還很多,筆者直接找了百度地圖的接口作,接口文檔,調用的API是Geocoding API中的地理編碼服務前端
請求示例:對北京市百度大廈進行地理編碼查詢
http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderOption&output=json&address=百度大廈&city=北京市java
這裏面須要一個ak參數,這個參數就是用戶建立應用時生成的一串字符串,須要在請求數據的時候調用。node
[注意]git
建立的應用爲服務端類型github
建立應用有兩種校驗方式供選擇,你能夠選擇使用IP白名單校驗,也能夠選擇使用sn作校驗,二者不一樣點在於IP須要提早設定好你請求時候的IP地址,若是你不想提早設定死IP地址,也能夠選擇sn校驗,這是利用md5做爲加密算法的校驗方式。web
筆者一開始選擇sn作校驗,可是調用crypto生成md5簽名一直校驗不過,只能改用ip白名單做爲校驗。算法
有了供調用的接口,咱們就能夠寫個小腳本去請求數據,咱們須要三個依賴,分別是express、superagent、eventproxyexpress
express是一個輕量級的web應用
superagent是一個爬蟲常常用的庫,能夠模擬各類請求
eventproxy是一個併發控制器
首先咱們先寫一個簡單的請求來檢測是否能獲取到地理位置:
app.get('/one', function(req, res, next) { var sk = 'yoursk' // 建立應用的sk , address = '北京市' ; superagent.get('http://api.map.baidu.com/geocoder/v2/') .query({address: address}) .query({output: 'json'}) .query({ak: sk}) .end(function(err, sres) { if (err) { console.log('err:', err); return; } res.send(sres.text); }) })
而後打開瀏覽器訪問:http://localhost:8888/one
{ status: 0, result: { location: { lng: 116.39564503787867, lat: 39.92998577808024 }, precise: 0, confidence: 10, level: "城市" }
當你能看到這些信息的時候 ,說明接口成功了,若是status不爲0的時候,請參考返回碼狀態表
爲何要專門開個服務器才能去請求呢,由於咱們建立的應用是服務端,咱們須要建一個服務器才能去請求。
好了,一個城市能夠查詢了,接下來咱們要進行多個城市的查詢,咱們使用eventproxy作併發控制,你能夠把它看作一個計數器,你能夠命令它監聽某個事件,並在n次後執行對應的函數。
關鍵代碼以下:
app.get('/many', function(req, res, next) { var sk = 'yoursk' , addresses = ['北京市', '深圳市', '廣州市', '普寧市'] ; ep.after('getLocation', addresses.length, function(locations) { res.send(locations); }) addresses.forEach(function(e, i) { superagent.get('http://api.map.baidu.com/geocoder/v2/') .query({address: e}) .query({output: 'json'}) .query({ak: sk}) .end(function(err, sres) { ep.emit('getLocation', {address: e, res: sres.text}) }) }) })
打開瀏覽器訪問:http://localhost:8888/many
[ { address: "北京市", res: "{"status":0,"result":{"location":{"lng":116.39564503787867,"lat":39.92998577808024},"precise":0,"confidence":10,"level":"城市"}}" }, { address: "深圳市", res: "{"status":0,"result":{"location":{"lng":114.0259736573215,"lat":22.546053546205248},"precise":0,"confidence":14,"level":"城市"}}" }, { address: "廣州市", res: "{"status":0,"result":{"location":{"lng":113.30764967515182,"lat":23.12004910207623},"precise":0,"confidence":12,"level":"城市"}}" }, { address: "普寧市", res: "{"status":0,"result":{"location":{"lng":116.07816590835329,"lat":23.28895358314155},"precise":0,"confidence":14,"level":"區縣"}}" } ]
好了,批量查詢也沒有問題了,接下來咱們要用nodejs去讀取後臺工程師丟給個人excel文件
此次咱們須要多兩個依賴,一個nodejs內置的fs模塊,一個用來讀寫excel的庫node-xlsx
將要城市的excel文件丟到根目錄下,另起一個腳本xls2js.js:
var xlsx = require('node-xlsx') , fs = require('fs') ; var file_path = './query_result.xlsx'; var file_data = xlsx.parse(file_path);
再調用fs.writeFile將提取出來的城市寫入,代碼以下:
file_data.forEach(function(sheet, index) { var sheetname = sheet.name // 表格名稱 , sheetdata = sheet.data // 表格的數據 , sheethead = sheetdata[0] // 第一行通常爲表頭,但不是必定的 , sheetbody = sheetdata.slice(1) // 真正的數據 , file_path_towrite = './static/address.json' , file_data_json , cities_name = [] ; // 將城市的數據寫進去 sheetbody.forEach(function(e, i) { cities_name.push('' + e[1] + ',' + e[2]) }) file_data_json = JSON.stringify({cities_name: cities_name}); fs.writeFile(file_path_towrite, file_data_json, function(err) { if (err) console.log('寫入數據失敗', err); else console.log('寫入文件成功'); }) })
打開static/address.json文件,會看到以下格式的文本:
{"cities_name":["北京市,北京市","北京市,市轄區","天津市,天津市"]}
好了,有了這個文件,咱們就能夠再次讀取而後進行批量查詢:
app.get('/', function(req, res, next) { var sk = 'yoursk' , addresses = [] , file_path = './static/address.json' , file_path_towrite = './static/geocoder.json' , file_data ; fs.readFile(file_path, function(err, data) { if (err) { console.log('讀取文件失敗', err); return; } file_data = JSON.parse(data); addresses = file_data.cities_name; ep.after('getLocation', addresses.length, function(locations) { var file_data = {}; locations.forEach(function(e, i) { file_data[e.address.split(',')[1]] = [e['location']['lng'], e['location']['lat']]; }) fs.writeFile(file_path_towrite, JSON.stringify(file_data), function(err) { if (err) console.log('寫入數據失敗', err); else console.log('獲取數據並寫入文件成功'); res.send(file_data); }) }) addresses.forEach(function(e, i) { superagent.get('http://api.map.baidu.com/geocoder/v2/') .query({address: e.split(',').join(' ')}) .query({city: e.split(',')[1]}) .query({output: 'json'}) .query({ak: sk}) .end(function(err, sres) { var location , res_json ; res_json = JSON.parse(sres.text); if (res_json.status == 0) { location = res_json.result && res_json.result.location || ''; } else { location = {"lng":0,"lat":0}; } ep.emit('getLocation', {address: e, location: location}) }) }) }); })
這些就是前端的事情了,怎麼好看怎麼寫