本文是通过调用百度开放平台的API实现的经纬度查询。因此在使用前需要你去注册一个应用。
源码被我拆成了三个小节,分别是 数据准备、计算经纬度、计算两地距离,其他中间的处理代码则可能需要读者手动完善。
# 导入相关的包
import requests #HTTP请求
import time
import re
import json # 用于解析Json
import pandas as pd # 用于处理数据(数据分析相关的同学必须会的包)
CSV文件中有一列是city
,使用pandas直接读取即可:
df = pd.DataFrame()
df = pd.read_csv(r'./city.csv',encoding="gbk")
df['city']
得到的数据如下所示,总共有一百条,是我国2020年百强县的名单:
0 昆山市
1 江阴市
2 张家港市
3 晋江市
4 常熟市
...
95 福安市
96 射阳县
97 邹平县
98 海城市
99 青州市
Name: city, Length: 100, dtype: object
user_geohash | num | city | |
---|---|---|---|
0 | 94ek6ke | 1028 | 昆山市 |
1 | 94ek6lj | 980 | 江阴市 |
2 | 94ek6lw | 919 | 张家港市 |
3 | 94ek6kn | 908 | 晋江市 |
4 | 94ek6l5 | 517 | 常熟市 |
... | ... | ... | ... |
95 | 9q0ltaw | 243 | 福安市 |
96 | 99s4avh | 242 | 射阳县 |
97 | 9519pwt | 240 | 邹平县 |
98 | 94jrlp3 | 240 | 海城市 |
99 | 946hodd | 240 | 青州市 |
100 rows × 3 columns
因为使用的是API,因此得到是上述的Json字符串。
/*
*/
def calc_ll(x):
# 获取自己的AK替换Post_url中 中文括号 的内容即可
Post_url = "http://api.map.baidu.com/geocoding/v3/?address=" + x + "&output=json&ak=(百度API开放平台获取的AK)&callback=showLocation"
Post_data = {
'address': x
}
Text = se.post(Post_url, data=Post_data).text.replace("'", '"').replace('/ ', '/')[27:-1] # 提取为Json格式,去掉‘showLocation&&showLocation()’这些额外的字符
jsonValue = json.loads(Text) # 转化为Json对象
# print(jsonValue) # 打印Json值
if('result' in jsonValue):
print(jsonValue['result']['location']['lng'])
return [jsonValue['result']['location']['lng'],jsonValue['result']['location']['lat']]
else:
return ' '
# 通过这行的代码去调用的获取经纬度的 API 接口
address = df['city'].apply(calc_ll) # 这里的address是可以直接导入pandas的,详细的可以查看apply的返回值
se = requests.session()
执行calc_ll
后返回的值如下所示:
showLocation&&showLocation({"status":0,"result":{"location":{"lng":120.98745249794995,"lat":31.390863425081866},"precise":0,"confidence":20,"comprehension":100,"level":"区县"}})
上述百强县执行代码后的结果:
{'status': 0, 'result': {'location': {'lng': 120.98745249794995, 'lat': 31.390863425081864}, 'precise': 0, 'confidence': 20, 'comprehension': 100, 'level': '区县'}}
120.98745249794995
...
...
{'status': 0, 'result': {'location': {'lng': 120.26444564891948, 'lat': 33.78101359213001}, 'precise': 0, 'confidence': 20, 'comprehension': 100, 'level': '区县'}}
120.26444564891948
{'status': 0, 'result': {'location': {'lng': 117.74947848721935, 'lat': 36.8700322166973}, 'precise': 0, 'confidence': 20, 'comprehension': 100, 'level': '区县'}}
117.74947848721935
{'status': 0, 'result': {'location': {'lng': 109.12452136754654, 'lat': 21.481065838235963}, 'precise': 0, 'confidence': 20, 'comprehension': 100, 'level': '区县'}}
109.12452136754654
{'status': 0, 'result': {'location': {'lng': 118.48653672086745, 'lat': 36.690416508705376}, 'precise': 0, 'confidence': 20, 'comprehension': 100, 'level': '区县'}}
118.48653672086745
查看address的值:
address
0 [120.98745249794995, 31.390863425081864]
1 [120.29156800752115, 31.926044909769043]
2 [120.56155363871446, 31.88114053634028]
3 [118.55843052000408, 24.787824575144548]
4 [120.75949588665195, 31.65953827674108]
...
95 [119.65440636047963, 27.094323508059915]
96 [120.26444564891948, 33.78101359213001]
97 [117.74947848721935, 36.8700322166973]
98 [109.12452136754654, 21.481065838235963]
99 [118.48653672086745, 36.690416508705376]
Name: city, Length: 100, dtype: object
df['pos'] = df1 # 保存到df文件中
user_geohash | num | city | pos | |
---|---|---|---|---|
0 | 94ek6ke | 1028 | 昆山市 | [120.98745249794995, 31.390863425081864] |
1 | 94ek6lj | 980 | 江阴市 | [120.29156800752115, 31.926044909769043] |
2 | 94ek6lw | 919 | 张家港市 | [120.56155363871446, 31.88114053634028] |
3 | 94ek6kn | 908 | 晋江市 | [118.55843052000408, 24.787824575144548] |
4 | 94ek6l5 | 517 | 常熟市 | [120.75949588665195, 31.65953827674108] |
... | ... | ... | ... | ... |
95 | 9q0ltaw | 243 | 福安市 | [119.65440636047963, 27.094323508059915] |
96 | 99s4avh | 242 | 射阳县 | [120.26444564891948, 33.78101359213001] |
97 | 9519pwt | 240 | 邹平县 | [117.74947848721935, 36.8700322166973] |
98 | 94jrlp3 | 240 | 海城市 | [109.12452136754654, 21.481065838235963] |
99 | 946hodd | 240 | 青州市 | [118.48653672086745, 36.690416508705376] |
100 rows × 4 columns
在得到相关地名的经纬度之后,进一步就可以根据经纬度计算两点之间的距离,输入的是度数(°)
根据经纬度计算实际距离的代码:
import math
Earth_Radius=6378.137
def sin_square(a):
result=math.sin(a)
return result*result
def rad(ang):
return math.pi*ang/180.0
#a,b参数是数组
def distance_calculate(a,b):
lata,lnga=a[0],a[1]
latb,lngb=b[0],b[1]
radlata,radlnga=rad(lata),rad(lnga)
radlatb, radlngb = rad(latb), rad(lngb)
#纬度差
minus_a=radlata-radlatb
#经度差
minus_b=radlnga-radlngb
return 2*math.asin( math.sqrt(sin_square(minus_a/2) + math.cos(radlata)*math.cos(radlatb)*sin_square(minus_b/2)))*Earth_Radius
#坐标测试
#google
print(1000*distance_calculate((30.26848247,119.9499548338),(30.2688658749,119.9628533571)))
#baidu
print(1000*distance_calculate((30.274671,119.969392),(30.274261,119.956631)))