1. 程式人生 > >(資料科學學習手札80)用Python編寫小工具下載OSM路網資料

(資料科學學習手札80)用Python編寫小工具下載OSM路網資料

本文對應指令碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes

1 簡介

  我們平時在資料視覺化或空間資料分析的過程中經常會需要某個地區的道路網路及節點資料,而OpenStreetMap就是一個很好的資料來源(譬如圖1柏林路網):

圖1

  通常我們可以在 https://www.openstreetmap.org/export 中選擇矩形區域內的路網向量資料進行下載,但這種方式對選擇區域的大小有一定限制,想獲取較大範圍區域的路網資料並下載比較費事;而另一種方式是事先下載已經整合好的大區域的檔案,譬如在 http://download.geofabrik.de/ 中提供了各大洲、國家等大範圍的資料整合包,可以花費一定時間將其下載下來,再在需要哪些小區域時在本地GIS

軟體或程式設計工具中裁剪下所需的範圍路網,但這種方式一是對電腦資源要求較高,譬如中國範圍路網資訊shapefile檔案大小達到了800多兆,二是OSM的路網資訊不定期更新之後,要想及時跟上最新資料,就需要人工持續下載資料。

  為了更加靈活自由,且即時地獲取最新版本的OSM路網,我們可以利用Python,來編寫指令碼工具方便快捷地檢索或下載OSM可以識別出的各個級別行政區對應的向量格式資料。

2 基於Python的OSM路網下載

2.1 工作流程

  編寫這個工具靈感來源於 https://anvaka.github.io/city-roads/?q= 這個網站:

圖2

  使用者通過輸入指定城市的名稱並檢索,等待資料資源載入完成之後就可以在網頁中看到渲染好的城市路網,以重慶為例:

圖3

  通過對該網站進行抓包和原始碼分析,我弄明白了其工作流程大致如下:

  • Step1:

    根據使用者輸入的城市名稱,利用OSM官方的API進行模糊匹配,獲取可能的物件列表:

圖4
  • Step2:

    使用者點選選擇正確的區域,後臺js對其所對應的id資訊進行變換,再通過網站自帶的API獲取對應的.pbf格式資料,或overpass的API獲取JSON格式的向量資料。

圖5
  • Step3:

    渲染路網:

圖6

  瞭解了上述步驟之後,我們利用requestsgeopandas等庫僅用不到100行程式碼就可以參考上述過程,提取所需的shapefileGeoJSON檔案儲存到本地,具體的程式碼部分本文不做詳細說明,我將這部分功能封裝到文章開頭對應Github

倉庫下的OsmDownloader.py(https://github.com/CNFeffery/DataScienceStudyNotes/blob/master/(資料科學學習手札80)用Python編寫小工具下載OSM路網資料/OsmDownloader.py )中,可以自行去下載並使用,下面我們來學習如何在Python中使用它。

2.2 使用方式

  按照上文所述的地址下載對應指令碼之後(請提前安裝完成requestsgeopandaspandas以及tqdm這幾個三方庫),記住其所在路徑,接著在其他指令碼開頭匯入模組部分新增:

import sys
sys.path.append(r'所在路徑')
from OsmDownloader import OsmDownloader

  這樣才能成功匯入沒有在Python中註冊過的獨立模組,接下來我們來下載資料,只需要兩行程式碼即可完成對單個行政區路網資料的下載,以成都市為例:

# 單個地區路網下載
downloader = OsmDownloader(area='成都市') # area引數控制檢索的行政區,請儘量準確填寫
downloader.download_shapefile(path='儲存路徑') # path引數控制檔案儲存的路徑

  程式執行後稍等片刻即可完成下載(具體的耗時取決於你的網路狀況),譬如這裡我花了不到20秒就完成成都市路網資料的下載:

圖7

  儲存下來的資料線圖層與點圖層分開儲存:

圖8
圖9

  如果你想要下載儲存JSON格式的資料,換成downloader.download_geojson(path)即可,而如果你想要批量下載多個地區的資料,結合for迴圈即可,如下例:

# 多個地區路網下載
area_list = ['北京市', '重慶市江北區', 'Tokyo', 'Boston', '臺灣省']
for area in area_list:
    downloader = OsmDownloader(area=area)
    downloader.download_shapefile(path='儲存路徑')

  等待一段時間後,我們area_list裡多個不同級別行政區的路網資料便下載完成:

圖10

  如果擔心中途網路連線原因導致中斷,可以結合Python中的錯誤捕捉機制來進行相對應的處理,比較簡單這裡就不再贅述。

  
  以上就是本文全部內容,對指令碼獲取或使用有疑問的可以留言告訴我