笔者使用的是百度地图“Web服务API”提供的路径规划功能,官方网站地址如下:
http://lbsyun.baidu.com/index.php?title=webapi
批量输入两点经纬坐标返回多种交通方式的当前时刻预计行程时间
(若基础数据为文字地址,可使用百度地图API提供的“正/逆地理编码服务”转换为经纬坐标数据)
秘钥是访问百度地图API各项功能的密码,需向百度地图申请获得
点击网址,登录百度账号,点击获取秘钥,即可进入控制台界面
我们需要以开发应用的名义申请秘钥,因此在应用管理的我的应用中点击创建应用
简单输入必要信息提交后稍等便可通过验证
返回控制台即可获得所申请应用的AK码即秘钥
点击网址中的路线规划分区进入路线规划服务界面
百度标明了请求格式,以及返回格式
请求格式中不可或缺的部分是API地址+起终点经纬度+AK秘钥(各要素间通过&连接)
还有许多选填参数,如输入输出坐标类型(火星坐标/百度坐标/GPS坐标)、出行者选择路径的策略
值得一提的是在公交路径规划中是可以通过控制“公交换乘策略”是否使用地铁这一变量分别获得仅公交车出行和综合使用公共交通两种状态下的行程时间的
这在需要分别获得公交车以及地铁出行数据并加以对比时十分方便
由于唯一的变量为起终点经纬度,因此可以将请求代码整合为一个函数,方便调用:
def stod(slat,slng,dlat,dlng):#输入:起点纬度、起点经度、终点纬度、终点经度
url ="http://api.map.baidu.com/direction/v2/transit?" #API地址
ak = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' #秘钥
real_url = url +"origin="+slat+","+slng+"&destination="+dlat+","+dlng+"&ak="+ak #完整的请求代码
req = requests.get(real_url)
t = req.text
data = json.loads(t) #将数据保存在数组data中
try:#防止某几条数据报错导致请求终止
total_duration = data['result']["routes"][0]["duration"]/60
stepstr = str(total_duration) #获取该条数据总行程时间
steps = data['result']["routes"][0]['steps'] #获取该条路径的所有步骤
for step in steps:
step_tructions = step[0]["instructions"]#每一步的介绍包括乘坐公交车或地铁线路名
step_duration = step[0]["duration"]#每一步所花费的时间
stepstr = stepstr+"/"+step_tructions+"/"+str(step_duration/60)
except:
stepstr = None
req.close()
return stepstr #返回数据为总时长/第一步/第一步耗时/第二步/第二步耗时/...
全方式整合版
由于计算每种出行方式出行时耗都要单独编写一个函数,不够简洁,笔者将公共交通、小汽车、电动车、自行车、步行五种出行方式整合为一个Class(类)方便后续在其他py文件中直接调用。
类文件如下:
import requests
import json
class Round_plan():
"""一个关于调用百度地图API全方式路径规划功能的类"""
def __init__(self,transit_mode):
self.transit_mode=transit_mode
def stod(self,slat,slng,dlat,dlng):
self.slat=slat
self.slng=slng
self.dlat=dlat
self.dlng=dlng
if self.transit_mode=='Car':
a="driving"
elif self.transit_mode=='Public transit' :
a="transit"
elif self.transit_mode=="E-bike":
a="riding"
elif self.transit_mode=="Bike":
a="riding"
elif self.transit_mode=="Walk":
a="walking"
url = "http://api.map.baidu.com/direction/v2/"+a+"?"
ak = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
if self.transit_mode=="E-bike":
real_url = url + "origin="+slat+","+slng+"&destination="+dlat+","+dlng+"&ak="+ak+"&riding_type="+"1"
else:
real_url = url + "origin="+slat+","+slng+"&destination="+dlat+","+dlng+"&ak="+ak
req = requests.get(real_url)
t = req.text
data = json.loads(t)
# print(data['result']["routes"][0])
try:
if self.transit_mode != 'Public transit' :
total_duration = data['result']["routes"][0]["duration"]/60
stepstr = str(total_duration)
else:
total_duration = data['result']["routes"][0]["duration"]/60
stepstr = str(total_duration)
steps = data['result']["routes"][0]['steps']
for step in steps:
step_tructions = step[0]["instructions"]
step_duration = step[0]["duration"]
# print(step_tructions , step_duration)
stepstr = stepstr+"/"+step_tructions+"/"+str(step_duration/60)
except:
stepstr = None
req.close()
return stepstr
应用案例
原始数据为test.xlsx,包含5条起终点经纬坐标:
主程序代码如下
from round_plan import Round_plan #引用类
import xlrd
import openpyxl
import time
import socket
socket.setdefaulttimeout(20)
transit_mode=input("Please input which transit mode you will choose:(Car/Public transit/E-bike/Bike/Walk)")
file_name=input("Please input the filename of the data:")
if __name__ == '__main__': #调用文件的方式为直接执行
path = file_name+r'.xlsx'
xl = xlrd.open_workbook(path)
sheet = xl.sheets()[0]
data = []
data.append(sheet.col_values(0))
data.append(sheet.col_values(1))
data.append(sheet.col_values(2))
data.append(sheet.col_values(3))
slat = data[0]
slng = data[1]
dlat = data[2]
dlng = data[3]
stepstr_list=[]
# print(data)
for i in range(len(slat)):
print(i)
if(i%100==0):
time.sleep(1)
rount_result=Round_plan(transit_mode) #类的实例
stepstr = rount_result.stod(str(slat[i]), str(slng[i]), str(dlat[i]), str(dlng[i]))
stepstr_list.append(stepstr)
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = 'stepstr_data'
value = [stepstr_list]
for i in range(0, 1):
for j in range(0, len(value[i])):
sheet.cell(row=j + 1, column=i + 1, value=value[i][j])
wb.save(transit_mode+'-test.xlsx')
print("写入数据成功!")
当数据量较大时建议设置较长的每100次请求间隔时间,这是为了防止远程主机认为短时间内一款应用产生大量请求,系为恶意访问强行终止访问,报错如下
最终效果如图所示:
得到数据结构如图所示: