以物流行業為例,分析了 PostgreSQL 與 Greenplum 在地理位置資訊處理,最佳路徑演算法,機器學習等方面的物流行業應用方法。其中提到了地址轉換成座標的問題,更專業些的名詞應該是“地理編碼”,即知道一個地址,如北京市海澱區上地十街10號,怎麼樣可以擷取到對應的經緯度位置資訊(40,116),或者反過來。
地理編碼概念
很多地圖相關的廠商都提供了相關的API,我們可以直接利用這些API得到這些資訊。比如百度的Geocoding API。
Geocoding API是一類介面,用於提供從地址到經緯度座標或者從經緯度座標到地址的轉換服務,使用者可以使用C# 、C++、Java等開發語言發送請求且接收JSON、XML的返回資料。Geocoding API包括位址解析和逆位址解析功能:
借用ESRI文檔中更直觀的一張圖
地理編碼:即位址解析,由詳細到街道的結構化地址得到百度經緯度資訊,例如:“北京市海澱區中關村南大街27號”位址解析的結果是“lng:116.31985,lat:39.959836”。同時,地理編碼也支援名勝古迹、標誌性建築名稱直接解析返回百度經緯度,例如:“百度大廈”位址解析的結果是“lng:116.30815,lat:40.056885” 。
逆地理編碼:即逆位址解析,由百度經緯度資訊得到結構化地址資訊,例如:“lat:31.325152,lng:120.558957”逆位址解析的結果是“江蘇省蘇州市虎丘區塔園路318號”。
不過,需要說明的一點是,若想使用百度的這套API的前提是,有百度帳號並申請相應的Key。其實,除了百度之外,Google、ESRI、微軟的Bing等都有類似的地理編碼服務。不過這些服務大多沒有專門針對Python的庫並且彼此之間的Json結構也不一致。於是乎專治不服的Python大神做了一個專門的地理編碼工具geocoder,將這些不同廠商的服務整合統一起來。
地理編碼工具geocoder
首先看一下它都支援哪些公司的地理編碼服務:
安裝
pip install geocoder
地理編碼
import geocoderg = geocoder.google("1403 Washington Ave, New Orleans, LA 70130")g = geocoder.arcgis(u"北京市海澱區上地十街10號")g.latlng
輸出為
[29.9287839, -90.08421849999999]
也可以查看完整的geojson
g.geojson
輸出為
{'bbox': [-90.0855674802915, 29.9274349197085, -90.0828695197085, 29.9301328802915], 'geometry': {'coordinates': [-90.08421849999999, 29.9287839], 'type': 'Point'}, 'properties': {'accuracy': u'ROOFTOP', 'address': u'1403 Washington Ave, New Orleans, LA 70130, USA', 'bbox': [-90.0855674802915, 29.9274349197085, -90.0828695197085, 29.9301328802915], 'city': u'New Orleans', 'confidence': 9, 'country': u'US', 'county': u'Orleans Parish', 'encoding': 'utf-8', 'housenumber': u'1403', 'lat': 29.9287839, 'lng': -90.08421849999999, 'location': '1403 Washington Ave, New Orleans, LA 70130', 'neighborhood': u'Garden District', 'ok': True, 'place': u'ChIJGyFHWc2lIIYRYSoneaXAUiw', 'postal': u'70130', 'provider': 'google', 'quality': u'street_address', 'state': u'LA', 'status': 'OK', 'status_code': 200, 'street': u'Washington Ave'}, 'type': 'Feature'}
直接用Google嘗試查詢中文地址時失敗
g = geocoder.google(u"北京市海澱區上地十街10號")g.ok
輸出為
False
用百度應該沒問題,不過我沒有申請相應的key。切換到arcgis,能夠成功編碼
g = geocoder.arcgis(u"北京市海澱區上地十街10號")g.latlng
輸出為
[40.050934, 116.30079]
逆地理編碼
g = geocoder.google([29.9287839, -90.08421849999999], method='reverse')print g.addressprint g.cityprint g.stateprint g.country
輸出為
1403 Washington Ave, New Orleans, LA 70115, USANew OrleansLAUS
換成中國的地址
g = geocoder.google([40.050934, 116.30079], method='reverse')print g.addressprint g.cityprint g.stateprint g.country
輸出為
Bai Du Da Sha, Haidian Qu, Beijing Shi, China, 100193BeijingBeijing ShiCN
用arcgis的服務試試
g = geocoder.arcgis([40.050934, 116.30079], method='reverse')print g.addressprint g.cityprint g.stateprint g.country
輸出為
None北京市北京市CHN
Google轉換成的是英文,但地址比較全。arcgis雖然是中文,但是詳細的地址居然輸出為了None,這有個X用。
其他
geocoder 的功能不止於此,它還可以查IP(包括自己的)。
g = geocoder.ip('199.7.157.0')print g.latlngprint g.cityg = geocoder.ip('me')print g.latlngprint g.city
輸出為
[43.6934, -79.4857]Toronto[51.05, 13.75]Dresden
查詢一個城市的空間包圍盒
g = geocoder.arcgis(u"山東")g.bbox
輸出為
{'northeast': [38.976997, 121.976998], 'southwest': [33.022997, 116.022998]}
小結
空間資訊既可以利用行政區劃、自然地理地區等文本資訊描述,也可以用座標系統、數字(郵編等)來標識。利用地理編碼技術,可以將空間資訊的地理定位要素與相應的文本資訊關聯起來。本文主要介紹了geocoder地理編碼這一小工具,可以方便快捷的利用地圖等相關廠商提供的地理編碼服務,將文字描述的位置轉換成地圖上的經緯度,或者通過地圖上的某個位置座標獲得相應的位置資訊文字描述。