如何用Python實(shí)現(xiàn)地理位置和經(jīng)緯度坐標(biāo)之間的轉(zhuǎn)換 ,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),越城企業(yè)網(wǎng)站建設(shè),越城品牌網(wǎng)站建設(shè),網(wǎng)站定制,越城網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,越城網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
做地圖可視化時(shí)需要提供經(jīng)緯度坐標(biāo),但一般來(lái)說(shuō)我們手上拿到的通常只有地理位置,比如說(shuō) 北京市東大街302號(hào)狗不理包子店,可視化之前需經(jīng)緯度坐標(biāo)轉(zhuǎn)換
需要轉(zhuǎn)換的數(shù)據(jù)如果僅有幾個(gè)還好,可以直接借助谷歌地圖自帶經(jīng)緯度查詢(xún)手動(dòng)轉(zhuǎn)換,但真實(shí)場(chǎng)景下需要轉(zhuǎn)換的數(shù)據(jù)量可能要上百甚至上千,再手動(dòng)的話(huà)就比較頭疼了
如何將地理位置批量轉(zhuǎn)化為經(jīng)緯度坐標(biāo)?將針對(duì)這個(gè)問(wèn)題,介紹兩個(gè)用 Python 來(lái)實(shí)現(xiàn)的方法
最常見(jiàn)辦法就是調(diào)用第三方 API,例如百度、高德地圖等服務(wù)平臺(tái),提供了相應(yīng)的功能接口,它們的這類(lèi)技術(shù)已經(jīng)非常成熟啦,準(zhǔn)確穩(wěn)定,關(guān)鍵還是免費(fèi)的 ~,本期教程以百度為例(高德的用方類(lèi)似),介紹一下其用法
百度地圖開(kāi)放平臺(tái)
登錄控制臺(tái)之后,選擇左側(cè) 應(yīng)用管理-> 我的應(yīng)用 -> 創(chuàng)建應(yīng)用
創(chuàng)建應(yīng)用頁(yè)面中有三項(xiàng)信息需要填寫(xiě)
應(yīng)用名稱(chēng),無(wú)限制隨意填寫(xiě)即可;
應(yīng)用類(lèi)型 ,選擇服務(wù)端;
IP 白名單,只是個(gè)人簡(jiǎn)單測(cè)試的話(huà)0.0.0.0/0 即可,如果考慮安全問(wèn)題, 可以將自己的 IP 填進(jìn)去, AK 參數(shù)泄露的話(huà)非本機(jī) IP 無(wú)法訪(fǎng)問(wèn),這樣也不用擔(dān)心額度被其他用戶(hù)盜用
經(jīng)緯度地理位置根據(jù)轉(zhuǎn)換方向分為兩類(lèi),接下來(lái)我們分別演示一下其用法:
地理編碼:將地理地址轉(zhuǎn)換為坐標(biāo)點(diǎn)(經(jīng)緯度);
逆地理編碼,將經(jīng)緯度轉(zhuǎn)化為地理地址;
1.3.1 地理編碼,
下面就是 Python 測(cè)試代碼塊,將 AK 參數(shù)(前面申請(qǐng)到的)和你需要轉(zhuǎn)換的地理位置拼接到 官方提供的 url 中,用 requests 訪(fǎng)問(wèn)即可,
import requests import json import re AK = '你的AK' address ='北京市海淀區(qū)上地十街10號(hào)' url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}&callback=showLocation'.format(address,AK) res = requests.get(url) print(res.text) results = json.loads(re.findall(r'\((.*?)\)',res.text)[0]) print('\n') print('location is ',results['result']['location'])
輸出結(jié)果如下
showLocation&&showLocation({"status":0,"result":{"location":{"lng":116.3084202915042,"lat":40.05703033345938},"precise":1,"confidence":80,"comprehension":100,"level":"門(mén)址"}}) location is {'lng': 116.3084202915042, 'lat': 40.05703033345938}
1.3.2 逆地理編碼
逆地理編與地理編碼用法相似
lat = '40.05703033345938' lng = '116.3084202915042' AK = '你的AK' url = 'http://api.map.baidu.com/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{}'.format(AK,lat,lng) res = requests.get(url) print(res.text) address = json.loads(res.text)['result']['formatted_address'] print('\n') print('address is ',address)
像我們這類(lèi)免(bai) 費(fèi) piao) 用戶(hù),借助百度 API 每天最高可調(diào)用 6000 次,這個(gè)量級(jí)基本上能滿(mǎn)足我們?nèi)粘P枰?,但如果這個(gè)數(shù)量滿(mǎn)足不了你的話(huà),可以在線(xiàn)購(gòu)買(mǎi)更高的使用額度
2.1 Geopy 庫(kù)介紹
這里介紹一個(gè)Python 包 Geopy ,借助它也可以實(shí)現(xiàn)經(jīng)緯度地理位置轉(zhuǎn)換,
這款包之經(jīng)緯度轉(zhuǎn)換原理其實(shí)還是借助了第三方 API 平臺(tái),因?yàn)槭忻嫔咸峁┙?jīng)緯度轉(zhuǎn)換 第三方平臺(tái)很多,為了方便, Geopy 把這些接口都分別封裝在一個(gè)類(lèi)中,借助 Geopy 模塊來(lái)調(diào)用,支持的第三放平臺(tái)如下
Geopy作為一個(gè)專(zhuān)注于地理處理包之外, 除了能實(shí)現(xiàn)上面地理編碼、逆地理編碼功能之外,還有一個(gè)其它令我經(jīng)驗(yàn)的功能, 提供兩個(gè)經(jīng)緯度坐標(biāo),計(jì)算他們?cè)诘厍蛏系淖疃叹嚯x
下面將介紹一下 Geopy 的具體用法,
2. 2 地理編碼
使用 地理編碼功能時(shí),需要借助 Geopy 的 geocoders 模塊,Geopy 把所有第三方API封裝到 geocoders 中
這里選用 OpenStreetMap 平臺(tái)上提供的 Nominatim 地理編碼器,因?yàn)榭梢悦赓M(fèi)供我們使用,不需要申請(qǐng) API ,但缺點(diǎn)是限流,限額,不能大規(guī)模頻繁訪(fǎng)問(wèn),否則會(huì)返回 403,429錯(cuò)誤代碼
from geopy.geocoders import Nominatim geolocator=Nominatim() location= geolocator.geocode("北京市海淀區(qū)西二旗北路") print(location.address) print(location.latitude,location.longitude)
結(jié)果如下
西二旗北路, 東北旺村, 海淀區(qū), 北京市, 102208, 中國(guó) 40.056793 116.305811
2.3 逆地理編碼
from geopy.geocoders import Nominatim geolocator=Nominatim() location= geolocator.reverse("40.056793 116.305811") print(location.address)
結(jié)果如下
1#, 西二旗北路, 東北旺村, 海淀區(qū), 北京市, 102208, 中國(guó)
結(jié)果看起來(lái)還不錯(cuò),簡(jiǎn)單方便;但提醒一下,因?yàn)榍懊嬲f(shuō)過(guò) Nominatim 模塊是限額度的,不要頻繁訪(fǎng)問(wèn),否則會(huì)出現(xiàn)以下錯(cuò)誤
2.4 根據(jù)經(jīng)緯度計(jì)算距離
Geopy 最讓我驚喜的是這個(gè)用法,提供兩個(gè)經(jīng)緯度坐標(biāo)計(jì)算他們之間的距離,因?yàn)榈厍蚓唧w來(lái)說(shuō)是橢圓,所以不能按照常規(guī)方法來(lái)計(jì)算 ,目前現(xiàn)有比較流行的幾個(gè)模型有以下幾個(gè)
model major (km) minor (km) flattening 'WGS-84': (6378.137, 6356.7523142, 1 / 298.257223563), 'GRS-80': (6378.137, 6356.7523141, 1 / 298.257222101), 'Airy (1830)': (6377.563396, 6356.256909, 1 / 299.3249646), 'Intl 1924': (6378.388, 6356.911946, 1 / 297.0), 'Clarke (1880)': (6378.249145, 6356.51486955, 1 / 293.465), 'GRS-67': (6378.1600, 6356.774719, 1 / 298.25), }
根據(jù)官方介紹,官網(wǎng)選擇的是 WGS-84 模型,根據(jù)統(tǒng)計(jì)最終計(jì)算到的距離誤差最高在0.5%左右;使用方法如下
from geopy import distance newport_ri = (41.49008, -71.312796) cleveland_oh = (41.499498, -81.695391) print(distance.distance(newport_ri, cleveland_oh).miles)#最后以英里單位輸出 #output 538.39044536 wellington = (-41.32, 174.81) salamanca = (40.96, -5.50) print(distance.distance(wellington, salamanca).km)# 以 km 作為單位輸出 19959.6792674
上面聊了這么多知識(shí)點(diǎn),下面引入一個(gè)案例來(lái)簡(jiǎn)單回顧一下;本案例中借助百度API 來(lái)實(shí)現(xiàn)地理位置坐標(biāo)轉(zhuǎn)換,把一個(gè) csv 表格內(nèi)的所有地址位置數(shù)據(jù)批量轉(zhuǎn)換為經(jīng)緯度
3.1 數(shù)據(jù)讀取
import pandas as pd import string data_path = 'H:/Data/Latlon/map-location.csv' df = pd.read_csv(data_path,encoding='GB18030') df
一共有 98 條數(shù)據(jù),每條數(shù)據(jù)都表示一個(gè)地理位置;數(shù)據(jù)明顯有一些擾亂項(xiàng),例如左端的數(shù)字字符、以及數(shù)據(jù)中的分隔符\t;因此轉(zhuǎn)換之前需要對(duì)數(shù)據(jù)進(jìn)行一次預(yù)處理操作
3.2 數(shù)據(jù)預(yù)處理
def process_str(x): # 數(shù)據(jù)預(yù)處理,去掉前面的數(shù)字、及字符串中 \t x = str(x).replace('\t','') x = str(x).strip(string.digits) return x df['location'] = df['location'].apply(process_str) df
預(yù)處理結(jié)果如下
3.3 地理編碼(經(jīng)緯度轉(zhuǎn)換)
import time start = time.time() AK = '你的AK' def get_location(str1): # 獲取經(jīng)緯度坐標(biāo) url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}&callback=showLocation'.format(str1,AK) res = requests.get(url) results = json.loads(re.findall(r'\((.*?)\)',res.text)[0]) return (results['result']['location']['lat'],results['result']['location']['lng']) df['(lat,lng)'] = df['location'].apply(get_location) print('耗時(shí) {}s'.format(time.time()-start)) print(df)
為了測(cè)試轉(zhuǎn)換效率,這里我加了一個(gè)計(jì)時(shí)器;98 條數(shù)據(jù)成功轉(zhuǎn)換后共耗時(shí) 4.65s 左右,效率還不錯(cuò),要比 Geopy 優(yōu)秀得多,
3.5 案例源碼數(shù)據(jù)
我已經(jīng)把本案例中用到代碼的數(shù)據(jù)打包再一起了,感興趣的可以在公號(hào)后臺(tái)回復(fù)關(guān)鍵字:210418 ,即可獲取!
上面介紹了這么多,最后做個(gè)小結(jié);聊一下這兩種方法在 地理坐標(biāo)轉(zhuǎn)換方面 各自的優(yōu)勢(shì)和劣勢(shì)
第三方API
優(yōu)勢(shì):地理編碼、逆編碼比較準(zhǔn)確,精度高;且支持高并發(fā);
劣勢(shì):不支持國(guó)外,環(huán)境配置較為復(fù)雜;
Geopy (用 Nominatim 模塊的話(huà))
優(yōu)勢(shì):簡(jiǎn)單方便,上手快;支持國(guó)外地理編碼
劣勢(shì):不支持并發(fā)訪(fǎng)問(wèn)、效率低且精度較低;
這里給大家一個(gè)建議,如果地址數(shù)據(jù)在國(guó)內(nèi)的話(huà) 經(jīng)緯度轉(zhuǎn)換 建議用第三方 API,穩(wěn)定且準(zhǔn)確;若是涉及下緯度距離計(jì)算、單位換算或地址數(shù)據(jù)在國(guó)外,建議用 Geopy
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。