怎麼樣用Python實現地理編碼

(本文已受權Python中文社區發佈)html

引言

今天看到一篇阿里雲的文章天下武功,惟快不破,以物流行業爲例,分析了 PostgreSQL 與 Greenplum 在地理位置信息處理,最佳路徑算法,機器學習等方面的物流行業應用方法。其中提到了地址轉換成座標的問題,更專業些的名詞應該是「地理編碼」,即知道一個地址,如北京市海淀區上地十街10號,怎麼樣能夠獲取到對應的經緯度位置信息(40,116),或者反過來。算法

地理編碼概念

不少地圖相關的廠商都提供了相關的API,咱們能夠直接利用這些API獲得這些信息。好比百度的Geocoding APIjson

Geocoding API是一類接口,用於提供從地址到經緯度座標或者從經緯度座標到地址的轉換服務,用戶可使用C# 、C++、Java等開發語言發送請求且接收JSON、XML的返回數據。Geocoding API包括地址解析和逆地址解析功能:api

借用ESRI文檔中更直觀的一張圖微信

Paste_Image.png

地理編碼:即地址解析,由詳細到街道的結構化地址獲得百度經緯度信息,例如:「北京市海淀區中關村南大街27號」地址解析的結果是「lng:116.31985,lat:39.959836」。同時,地理編碼也支持名勝古蹟、標誌性建築名稱直接解析返回百度經緯度,例如:「百度大廈」地址解析的結果是「lng:116.30815,lat:40.056885」 。機器學習

逆地理編碼:即逆地址解析,由百度經緯度信息獲得結構化地址信息,例如:「lat:31.325152,lng:120.558957」逆地址解析的結果是「江蘇省蘇州市虎丘區塔園路318號」。ide

不過,須要說明的一點是,若想使用百度的這套API的前提是,有百度帳號並申請相應的Key。其實,除了百度以外,谷歌、ESRI、微軟的Bing等都有相似的地理編碼服務。不過這些服務大多沒有專門針對Python的庫而且彼此之間的Json結構也不一致。因而乎專治不服的Python大神作了一個專門的地理編碼工具geocoder,將這些不一樣廠商的服務整合統一塊兒來。工具

地理編碼工具geocoder

首先看一下它都支持哪些公司的地理編碼服務:post

Provider Optimal Usage Policy
ArcGIS World
  Baidu China API key
Bing World API key
CanadaPost Canada API key
FreeGeoIP World
  Geocoder.ca CA & US Rate Limit
GeocodeFarm World Policy
GeoNames World Username
GeoOttawa Ottawa
Google World Rate Limit, Policy
HERE World API key
IPInfo World
  Mapbox World API key
MapQuest World API key
Mapzen World API key
MaxMind World
  OpenCage World API key
OpenStreetMap World Policy
Tamu US API key
TomTom World API key
What3Words World API key
Yahoo World
Yandex Russia
  TGOS Taiwan
安裝
pip install geocoder
地理編碼
import geocoder
g = 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.address
print g.city
print g.state
print g.country

輸出爲

1403 Washington Ave, New Orleans, LA 70115, USA
New Orleans
LA
US

換成中國的地址

g = geocoder.google([40.050934, 116.30079], method='reverse')
print g.address
print g.city
print g.state
print g.country

輸出爲

Bai Du Da Sha, Haidian Qu, Beijing Shi, China, 100193
Beijing
Beijing Shi
CN

用arcgis的服務試試

g = geocoder.arcgis([40.050934, 116.30079], method='reverse')
print g.address
print g.city
print g.state
print g.country

輸出爲

None
北京市
北京市
CHN

Google轉換成的是英文,但地址比較全。arcgis雖然是中文,可是詳細的地址竟然輸出爲了None,這有個X用。

其餘

geocoder 的功能不止於此,它還能夠查IP(包括本身的)。

g = geocoder.ip('199.7.157.0')
print g.latlng
print g.city
g = geocoder.ip('me')
print g.latlng
print 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地理編碼這一小工具,能夠方便快捷的利用地圖等相關廠商提供的地理編碼服務,將文字描述的位置轉換成地圖上的經緯度,或者經過地圖上的某個位置座標得到相應的位置信息文字描述。

歡迎關注我的微信公衆號

相關文章
相關標籤/搜索