NodeJS實現批量查詢地理位置經緯度接口

最近要實現一個顯示各個城市信息的功能, 好吧,後臺丟了一個包含一堆城市的excel給我,發現不只有每一個省的直轄市,還有二三線等的城市,數量還很多,一個個去查還挺浪費時間的,那爲何不寫個腳本去實現批量查詢呢。javascript

Demo

實現了讀取文件批量查詢後,順便寫了個網頁版批量查詢地理經緯度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白名單做爲校驗。算法

二、nodejs進行查詢

有了供調用的接口,咱們就能夠寫個小腳本去請求數據,咱們須要三個依賴,分別是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讀寫文件

此次咱們須要多兩個依賴,一個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":["北京市,北京市","北京市,市轄區","天津市,天津市"]}

四、綜合步驟二、3實現一個讀取本地城市文件、批量查詢、寫入新的文件的接口

好了,有了這個文件,咱們就能夠再次讀取而後進行批量查詢:

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})
                })
        })
    });
})

五、實現一個網頁,能夠進行輸入地理位置來進行地理位置的批量查詢

這些就是前端的事情了,怎麼好看怎麼寫

相關文章
相關標籤/搜索