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

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

Demo

實現了讀取文件批量查詢后,順便寫了個網頁版批量查詢地理經緯度

實現步驟

1、 查詢接口

網站上這種類型的接口還不少,筆者直接找了百度地圖的接口做,接口文檔,調用的API是Geocoding API中的地理編碼服務

請求示例:對北京市百度大廈進行地理編碼查詢
http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderOption&output=json&address=百度大廈&city=北京市

這里面需要一個ak參數,這個參數就是用戶創建應用時生成的一串字符串,需要在請求數據的時候調用。

[注意]

  • 創建的應用為服務端類型
  • 創建應用有兩種校驗方式供選擇,你可以選擇使用IP白名單校驗,也可以選擇使用sn做校驗,兩者不同點在于IP需要提前設定好你請求時候的IP地址,如果你不想提前設定死IP地址,也可以選擇sn校驗,這是利用md5作為加密算法的校驗方式。
    筆者一開始選擇sn做校驗,但是調用crypto生成md5簽名一直校驗不過,只能改用ip白名單作為校驗

2、nodejs進行查詢

有了供調用的接口,我們就可以寫個小腳本去請求數據,我們需要三個依賴,分別是express、superagent、eventproxy
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文件

3、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":["北京市,北京市","北京市,市轄區","天津市,天津市"]}

4、綜合步驟2、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})
                })
        })
    });
})

5、實現一個網頁,可以進行輸入地理位置來進行地理位置的批量查詢

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容

  • 國家電網公司企業標準(Q/GDW)- 面向對象的用電信息數據交換協議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,043評論 6 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,596評論 25 707
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,776評論 18 139
  • 睡不醒先生總是愛做夢 他總是幻想著撐一支竹篙,緩緩地滑 他總是渴望品一杯清茗,讀幾首小詩 他總是追求者旁人唾棄、無...
    綿羊菌閱讀 406評論 0 0
  • 還是沒辦法一覺睡到天亮。到了該解脫的時候了。早安,今天又會是美好的一天。
    _____倍堅強閱讀 179評論 0 0