由于我本人没有任何编程基础,而且设定的目标是爬取全国三百多个城市之间的行驶距离,且目前手头也仅有这些城市的txt,所以今天遇到许多难点。
首先是怎么获取城市之间的行驶距离,其次是怎么将excel导入python,还有就是怎么建立城市之间的od关系(虽然说起来很糗,但真的小白总是流血流泪...),这是主要的三个问题。
当然其他还有很多小问题,比如打开pycharm想要import pandas、itertools啥的,很多都是灰色,最后室友提醒是很多运行包我都没安装。回顾整个历程,从早上九点多到此刻下午四点,总体是非常磕磕绊绊。
以Gavin_Sunny的《Python利用百度地图获取两地距离 最详细过程和源代码》这篇文章中的代码为基础,借助了python的itertools中的combinations也就是排列组合最后形成了两个城市之间的od对应关系,最终得到了答案,唯一问题就是运算过程挺慢的,亲测四十个城市计算大概八百条结果,用时八分钟左右。
一开始的准备工作比如申请百度开放平台的ak密钥这一步按下不表,主要运用其中的地点检索服务以及批量算路服务两个web api。
主代码如下:
# 本次整体的源代码
AK = 'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
# 需要用到的模块:pandas、requests、json等
import pandas as pd
import requests
import json
from itertools import combinations
#获取对应地点的经纬度
def getPosition(address):
url = r"http://api.map.baidu.com/place/v2/search?query={}®ion=全国&output=json&ak={}".format(
address,
'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
)
res = requests.get(url)
json_data = json.loads(res.text)
if json_data['status'] == 0:
lat = json_data["results"][0]["location"]["lat"] # 纬度
lng = json_data["results"][0]["location"]["lng"] # 经度
else:
print("[ERROR] Can not find {}.".format(address))
return "0,0", json_data["status"]
return str(lat) + "," + str(lng), json_data["status"]
#获取两地之间的行驶距离
def getDistance(start, end):
url = "http://api.map.baidu.com/routematrix/v2/driving?output=json&origins={}&destinations={}&ak={}".format(
start,
end,
'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
)
res = requests.get(url)
content = res.content
jsonv = json.loads(str(content, "utf-8"))
dist = jsonv["result"][0]["distance"]["value"]
return dist
#合并函数调用
def calcDistance(startName, endName):
start, status1 = getPosition(startName)
end, status2 = getPosition(endName)
if status1 == 0 and status2 == 0:
return getDistance(start, end)
else:
return -1
#批量地点计算距离(选取5座城市进行测试)
if __name__ == "__main__":
data = ['北京市','天津市','上海市','重庆市','阿坝藏族羌族自治州']
res = []
#计算几座城市之间的非重复排列组合关系
for i in combinations(data,2):
startName = i[0] #设置起始点与终点
endName = i[1]
dist = calcDistance(startName, endName)
res.append([startName, endName, dist / 1000])
pd.DataFrame(res).to_excel(
"result1.xlsx",
header=["起点", "终点", "距离"],
index=None,
encoding="utf-8"
)
ps:原代码中是读取已经分列的起始点与终点,在其后加入距离等指标,在这里我还没有研究透它的用法,以后再更新上。最后还有疑问,由于百度平台似乎每日能读取的数据量是有一定限制的,我还在研究怎么让python实现分次从excel中读取固定数量的数据(如从上到下,每次录入40座城市),进行相互之间距离计算后自动更新拼合成一个完整的城市间距离计算的表格。???????
更新于2021年10月23日晚9点
替换代码中地点仅可罗列的部分,实现从excel中读取若干量的数据进行计算
代码如下
# 本次整体的源代码
AK = 'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
import pandas as pd
import requests
import json
from itertools import combinations
def getPosition(address):
url = r"http://api.map.baidu.com/place/v2/search?query={}®ion=全国&output=json&ak={}".format(
address,
'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
)
res = requests.get(url)
json_data = json.loads(res.text)
if json_data['status'] == 0:
lat = json_data["results"][0]["location"]["lat"] # 纬度
lng = json_data["results"][0]["location"]["lng"] # 经度
else:
print("[ERROR] Can not find {}.".format(address))
return "0,0", json_data["status"]
return str(lat) + "," + str(lng), json_data["status"]
def getDistance(start, end):
url = "http://api.map.baidu.com/routematrix/v2/driving?output=json&origins={}&destinations={}&ak={}".format(
start,
end,
'NAwGuQe2WmQ7RSdvQIafcZ0Kjnv8Aldc'
)
res = requests.get(url)
content = res.content
jsonv = json.loads(str(content, "utf-8"))
dist = jsonv["result"][0]["distance"]["value"]
return dist
def calcDistance(startName, endName):
start, status1 = getPosition(startName)
end, status2 = getPosition(endName)
if status1 == 0 and status2 == 0:
return getDistance(start, end)
else:
return -1
if __name__ == "__main__":
data = pd.read_excel("city_data.xlsx")
res1 = []
res2 = []
for num_city in range(0,6):
data1 = data.iloc[num_city,0]
res1.append(data1)
for i in combinations(res1,2):
startName = i[0]
endName = i[1]
dist = calcDistance(startName, endName)
res2.append([startName, endName,dist/1000])
pd.DataFrame(res2).to_excel(
"result2.xlsx",
header=["起点", "终点",'距离'],
index=None,
encoding="utf-8"
)
ps:combinations中的''.join(i)真不是个好东西,无法选择起点与终点,去掉了反而更好,不知道为啥
|