Python突破高德API限制爬取交通態勢資料+GIS視覺化(超詳細)
一、需求:
爬取高德的交通態勢API,將資料視覺化為含有交通態勢資訊的向量路網資料。
二、使用的工具:
Python IDLE、記事本編輯器、ArcGIS 10.2、申請的高德開發者KEY(免費)。
三、主要思路:
本文的思路是使用Python的requests模組爬取高德API的返回資訊,將返回的資訊資料(JSON),通過程式碼解析的方式存入CSV檔案中,再匯入ArcGIS中進行視覺化處理。
四、分析階段:
根據高德提供的交通態勢資訊API文件,注意到高德提供了兩種獲取交通態勢資訊的方式,一種是通過設定矩形區域(傳入左下角以及右上角座標)的方式,一種是通過設定圓形區域的方式(設定圓心座標和半徑),本文使用的是設定矩形區域的方式。 但是問題來了,高德對使用者的API行為進行了限制,要求設定的矩形區域的對角線長度不超過10公里,但這是難不倒程式猿的,可以使用網格的思想來突破這一限制,如下圖:
即將爬取區域分成多個網格,每個網格在高德規定的10公里範圍之內即可,這樣雖然增加了API的呼叫次數,但不得不說是較為合適的解決方案,本思想同樣也適用於POI資訊的爬取,在本文中筆者使用了簡單的for迴圈來實現網格爬取,當然讀者也可以參考:
這篇博文中的LocaDiv類來實現更為複雜化的網格爬取方式。
五、編寫程式碼:
由於本文的爬蟲程式比較簡單,因此筆者為了方便直接使用Python自帶的IDLE進行程式編寫,程式碼如下:
import requests import pandas as pd import json import time #初始API的URL url="https://restapi.amap.com/v3/traffic/status/rectangle?key=申請的key&extensions=all&rectangle=" #設定整個網格左下角座標的經緯度值 baselng=116.927748 baselat=36.62361 #設定每個網格單元的經緯度寬 widthlng=0.05 widthlat=0.04 #用於儲存資料 x=[] #用於標識交通態勢線段 num=0 #爬取過程可能會出錯中斷,因此增加異常處理 try: #迴圈每個網格進行資料爬取,在這裡構建了3X3網格 for i in range(0,3): #設定網格單元的左下與右上座標的緯度值 #在這裡對資料進行處理,使之保留6位小數(不保留可能會莫名其妙出錯) startlat=round(baselat+i*widthlat,6) endlat=round(startlat+widthlat,6) for j in range(0,3): #設定網格單元的左下與右上座標的經度值 startlng=round(baselng+j*widthlng,6) endlng=round(startlng+widthlng,6) #設定API的URL並進行輸出測試 locStr=str(startlng)+","+str(startlat)+";"+str(endlng)+","+str(endlat) thisUrl=url+locStr print(thisUrl) #爬取資料 data=requests.get(thisUrl) s=data.json() a=s["trafficinfo"]["roads"] #注意,提取數值需要使用XXX.get()的方式來實現,如a[k].get('speed') #若使用a[k]['speed']來提取,或會導致KeyError錯誤 for k in range(0,len(a)): s2=a[k]["polyline"] s3=s2.split(";") for l in range(0,len(s3)): s4=s3[l].split(",") x.append([a[k].get('name'),a[k].get('status'),a[k].get('speed'),num,float(s4[0]),float(s4[1])]) num=num+1 #若爬取網格較多,可使用time.sleep(秒數)來避免高德的單秒API呼叫次數的限制 except Exception as e: pass #將資料結構化儲存至規定目錄的CSV檔案中 c = pd.DataFrame(x) c.to_csv('E:/BigRoads.csv',encoding='utf-8-sig')#感謝網友weixin_43475766的提醒
六、CSV資料處理:
在相關目錄下找到爬取的CSV檔案,用記事本開啟,刪除第一行的內容(,0,1,2,3,4,5),否則會導致匯入ArcGIS時出錯。
七、交通態勢資訊視覺化:
1、開啟Arcmap,在右側的catlog(目錄)中找到爬取的CSV檔案直接拖入左側的內容列表中,如圖:
2、右鍵點選該CSV資料,選擇“顯示XY資料”:
3、在彈出的設定框中,進行如下設定:
需要注意的是,本文中爬取的高德資料的座標值使用的是GCJ-02座標系,若要應用至專案中,需要轉換為WGS-84座標系,本文為了省事,且為了與高德線上底圖對比驗證,直接當作WGS84座標來處理。點選兩次確定,即可看到CSV檔案成功的轉換為了點要素檔案。
4、接下來的一步十分重要,開啟生成要素的屬性表可以發現,屬性表並沒有FID(objectID)欄位,若無該欄位,該點要素將無法轉換為線要素,因此需要將該要素匯出為SHP檔案,方法是右鍵單擊該要素,選擇資料->匯出資料,如下圖:
然後進行如下設定,注意要匯出為shp格式:
5、接下來是將交通態勢點轉換為線,在toolbox中找到“點集轉線”工具(資料管理工具->要素->點集轉線),在彈出的設定介面進行如下設定:
注意線欄位選擇Field5(即程式碼中的num變數),排序欄位選擇FID。
6、等待片刻,完整的路網呈現在眼前:
看到了路網是不是一陣狂喜,但是開啟屬性表,似乎笑不出來了,原來的交通態勢屬性去哪了!!!
不要著急,接下來一步,將屬性完美的找回來。
7、右鍵路網資料,選擇連線和關聯->連線,如下圖:
在彈出的設定框中進行如下設定:
第二個選項可以是原始的CSV表,也可以是用來轉線的點檔案(即本文的jinan.shp),點選確定,再開啟屬性表,屬性是不是回來了呢?
8、分級渲染視覺化一下,美滋滋~
什麼?為什麼這麼醜?不要在意這些細節...........