之前找數據時,我遇到過這樣一個問題:我需要確定東莞市33個鎮和街道的經緯度,以及任意兩個鎮或街道之間行車距離。用過地圖軟體的童鞋都知道地圖軟體里一定都存著這些數據,但是需要自己一個一個搜,而且有些數據在app里是看不到的,比如經緯度。好在我知道大部分提供信息的網站都有開放平台,是給開發者接入到軟體里的,得用程序語言才能獲取其中的數據,正好我會python,那就開始吧~

國內兩大地圖平台百度和高德都有各自的開放平台,這裡就用高德做示範。高德開放平台的主頁:高德開放平台 | 高德地圖API,進去以後,是這樣的:

第一次用需要註冊,點擊右上角的註冊:

這就是註冊頁面,註冊成功後,你就成為了一名高德開發者,我就不示範了。有了賬號之後還是回到主頁,點擊右上角的登錄,登錄之後,右上角會變成這樣:

進入控制台,是這個樣子的:

如果是第一次用,先點左側的引用管理,創建應用和秘鑰,這裡我演示一下:

點擊右上角的創建新應用,給應用起一個名字,根據需要選一個應用類型,創建好了之後這個應用就會出現在頁面中,再點擊該應用右上角的添加新key,創建一個秘鑰:

給key起一個名字,服務平台選web服務(畢竟我們不是在手機上用),下面提示你可使用的服務,這些你都可以用,IP白名單中你可以添加自己的IP地址,不填也可以。最後勾選同意,提交。

然後你就擁有了一個屬於你的key。每一個key都有每天調用次數的限制,為了防止被別人使用,注意保護好隱私。

現在就可以用這個key獲取高德地圖的數據了。在個人中心→配額管理中,我們可以看到每一項服務的每日調用量上限,如果是免費用戶,配額就是這樣的:

點擊頁面右上角的開發者文檔,可以查看每一項服務的詳細說明。我們添加key時選的是web服務,那就翻到這裡:

比如我現在要通過街道和鎮的名字獲取它們的經緯度,那就選擇搜索API。

看一下文檔的內容:

產品介紹:搜索服務API是一類簡單的HTTP介面,提供多種查詢POI信息的能力,其中包括關鍵字搜索、周邊搜索、多邊形搜索、ID查詢四種篩選機制。

我們要用的關鍵字搜索:

關鍵字搜索:通過用POI的關鍵字進行條件搜索,例如:肯德基、朝陽公園等;同時支持設置POI類型搜索,例如:銀行

使用說明:

第一步,申請」Web服務API」密鑰(Key);

第二步,拼接HTTP請求URL,第一步申請的Key需作為必填參數一同發送;第三步,接收HTTP請求返回的數據(JSON或XML格式),解析數據。

秘鑰已經有了,下面需要拼接請求:

關鍵字搜索API服務地址:https://restapi.amap.com/v3/place/text?parameters

parameters就是我們需要修改的部分,根據文檔中的請求參數的說明,我們需要拼接到路徑中的參數有:

key:自己的秘鑰

keywords:關鍵字,在這裡是東莞市各鎮街的名稱

city:查詢城市範圍,即東莞,或查詢高德的編碼表,用東莞的adcode代替漢字

offset和page:每頁數據條數和當前頁數,我們只需要第一頁的第一條,都是1,一般會返回各鎮街行政中心的數據

output:返回數據的類型,我一般用JSON,也可用XML

最後拼接出來的請求就是:

http://restapi.amap.com/v3/place/text?keywords=i&city=東莞&output=json&offset=1&page=1&key=mykey1

其中的keywords=i,可以將i替換成鎮街的名稱,mykey1換成自己的秘鑰。

這個請求用瀏覽器也能讀取,那我們就先看一看高德返回給我們的數據是什麼樣的。記住這個結構,後面要用關鍵字和索引讀取location後面的經緯度,路徑是:pois→0→location

下面就該請python登場了,需要用到的幾個庫:

import urllib.request #發送請求
from urllib import parse #URL編碼
import json #解析json數據
from openpyxl import load_workbook #從Excel中讀取鎮街名稱

我的數據保存在xlsx文件里,

所以要用openpyxl讀取各鎮街的名稱:

nameList = [] #創建一個列表用於接收數據
book = load_workbook(dongguan.xlsx) #打開文件
nameSheet = book["data"] #讀取工作表
#按行讀取第一列,並存入列表:
for row in range(1,nameSheet.max_row+1):
nameList.append(str(nameSheet["A%d"%(row)].value))

下面就該發送請求了:

dict = {} #創建一個字典用於接收數據
for i in nameList:
#拼接請求
url1 = http://restapi.amap.com/v3/place/text?keywords=+i+&city=東莞&output=json&offset=1&page=1&key=mykey1
#將一些符號進行URL編碼
newUrl1 = parse.quote(url1, safe="/:=&?#+!$,;@()*[]")
#發送請求
response1 = urllib.request.urlopen(newUrl1)
#讀取數據
data1 = response1.read()
#解析json數據
jsonData1 = json.loads(data1)
#pois→0→location得到經緯度,寫入字典
dict[i] = jsonData1[pois][0][location]
#拆分字元串,逗號之前是經度,逗號之後是緯度
locations = dict[i].split(",")

最後得到的數據,也可以寫入Excel文件里。

下一步,就該獲取距離數據了,這一部分用的是路徑規劃API,還是先看一下開發者文檔:

產品介紹:

路徑規劃API是一套以HTTP形式提供的步行、公交、駕車查詢及行駛距離計算介面,返回JSON 或 XML格式的查詢數據,用於實現路徑規劃功能的開發。使用說明:第一步,申請」Web服務API」密鑰(Key);第二步,拼接HTTP請求URL,第一步申請的Key需作為必填參數一同發送;第三步,接收HTTP請求返回的數據(JSON或XML格式),解析數據。

我要用的是駕車路徑規劃,示例:

https://restapi.amap.com/v3/direction/driving?origin=116.481028,39.989643&destination=116.465302,40.004717&extensions=all&output=xml&key=<用戶的key>

我需要提交的請求:

key:秘鑰

origin:起點的經緯度

destination:終點的經緯度

strategy:行駛策略,我選擇距離最短,代碼是2

output:返回數據類型,默認json

最後我拼接出來的請求就是:

https://restapi.amap.com/v3/driving?origin=origin&destination=destination&extensions=all&strategy=2&output=json&key=mykey1

origin和destination換成上面得到的經緯度,就可以了。我們也可以用瀏覽器先看看數據是什麼樣的。返回了許多數據,如果只要第三行的distance,路徑為:route→paths→0→distance

好了,發送請求:

distanceList = [] #創建一個列表用於接收數據
k = len(nameList) #nameList列表中元素個數
#遍歷nameList列表
for m in range(k):
subList = [] #創建一個子列表用於接收每一條數據,主要是為了後面方便創建數組
for n in range(k):
#從nameList中得到鎮街的名稱,作為鍵,獲得dict中的經緯度
origin = dict[nameList[m]]
destination = dict[nameList[n]]
#拼接請求
url2 = https://restapi.amap.com/v3/driving?origin=+origin+&destination=+destination+&extensions=all&type=1&output=json&key=mykey1
#編碼
newUrl2 = parse.quote(url2, safe="/:=&?#+!$,;@()*[]")
#發送請求
response2 = urllib.request.urlopen(newUrl2)
#接收數據
data2 = response2.read()
#解析json文件
jsonData2 = json.loads(data2)
#從json文件中提取距離
distance = jsonData2[route][path][0][distance]
#將距離寫入子列表
subList.append(int(distance))
#看一下得到的數據,這一行有沒有無所謂
print(nameList[m],nameList[n],distance)
#將子列表寫入distanceList
distanceList.append(subList)

這個得到的數據也可以寫進excel文件,就像這樣:

好了,批量獲取數據的任務到這裡就完成了。

需要注意的是,駕車路徑規劃API每天的配額是2000,我這裡有33個鎮和街道,窮舉兩兩組合,就要調用33*(33-1)/2 = 528次,如果有64個,就要調用2016次,2000的配額就不夠用了。

其實調用API和爬蟲技術的原理是差不多的,都是向對方的伺服器發送一個請求,對方返回一些數據,但調用API比爬蟲簡單很多,因為沒有反爬限制,返回的數據也是對方已經整理好的。只要有一點Python基礎,能看得懂我寫的代碼,就可以獲取海量的地理數據。

最後要說的是,在返回的json里還有很多數據,高德開放平台提供的API也有很多功能,怎麼用,都在開發文檔里,另外百度地圖開放平台也可以批量獲取數據,也有一些區別於高德的功能,有需要就自己探索吧。

推薦閱讀:

查看原文 >>
相关文章