起因
接触googlemaps,是源自于同学所托。嗯,一个还在深造的同学。他想得到这样的效果:
1 从google提供的map-api,获取两个坐标之间的多条路径,并仅筛选出这些路径中,距离最近的和距离最远的。
2 这两条路径,需要把路径指示中,每个分段路径的起始坐标,耗时和距离返回。
3 需要保存数据到txt文件。嗯,没选择数据库,让我比较疑惑。
大致的数据可以形如一个字典:
# 数据形式data = { 'fastest':[ [(起点坐标),(终点坐标),时间,距离], ... [(起点坐标),(终点坐标),时间,距离] ], 'shortest':[ [(起点坐标),(终点坐标),时间,距离], ... [(起点坐标),(终点坐标),时间,距离] ] }
初步接触googlemaps库
googlemaps库,是通过访问google map服务器提供的接口,采用requests库,发起get或者post请求,提供相关参数,来获取路线信息。
所以,对这个库的使用要求是,能够解决网络问题,请求能够到达google map所在的服务器,嗯,也就是说,需要能够海外代理或者,梯子。从同学嘱托我这个东西到完成,差不多4天时间,而网络问题,差不多耗尽了3天半。主要原因是,在同学已经提供了梯子和账号的情况下,未能正确配置本地信息。pac模式和全局代理模式。
使用googlemaps 的directions api
在googlemaps的github上,有使用教程,如何初始化一个client,然后如何调用库里面封装好的api。而想要实现获取多条路径,则需要使用directions这个api。但是在文档中,并没有详细的,关于如何使用directions的说明。只能查看源码。好在,源码对这个api,需要的参数是做了详细说明的,大致包括,起点,终点,是否多路径返回,出发时间,想到达的时间,语言设置等。如下:
Get directions between an origin point and a destination point. :param origin: The address or latitude/longitude value from which you wish to calculate directions. :type origin: string, dict, list, or tuple :param destination: The address or latitude/longitude value from which you wish to calculate directions. :type destination: string, dict, list, or tuple :param mode: Specifies the mode of transport to use when calculating directions. One of "driving", "walking", "bicycling" or "transit" :type mode: string :param waypoints: Specifies an array of waypoints. Waypoints alter a route by routing it through the specified location(s). :type waypoints: a single location, or a list of locations, where a location is a string, dict, list, or tuple :param alternatives: If True, more than one route may be returned in the response. :type alternatives: bool :param avoid: Indicates that the calculated route(s) should avoid the indicated features. :type avoid: list or string :param language: The language in which to return results. :type language: string :param units: Specifies the unit system to use when displaying results. "metric" or "imperial" :type units: string :param region: The region code, specified as a ccTLD ("top-level domain" two-character value. :type region: string :param departure_time: Specifies the desired time of departure. :type departure_time: int or datetime.datetime :param arrival_time: Specifies the desired time of arrival for transit directions. Note: you can't specify both departure_time and arrival_time. :type arrival_time: int or datetime.datetime :param optimize_waypoints: Optimize the provided route by rearranging the waypoints in a more efficient order. :type optimize_waypoints: bool :param transit_mode: Specifies one or more preferred modes of transit. This parameter may only be specified for requests where the mode is transit. Valid values are "bus", "subway", "train", "tram", "rail". "rail" is equivalent to ["train", "tram", "subway"]. :type transit_mode: string or list of strings :param transit_routing_preference: Specifies preferences for transit requests. Valid values are "less_walking" or "fewer_transfers" :type transit_routing_preference: string :param traffic_model: Specifies the predictive travel time model to use. Valid values are "best_guess" or "optimistic" or "pessimistic". The traffic_model parameter may only be specified for requests where the travel mode is driving, and where the request includes a departure_time. :type units: string :rtype: list of routes
如何构思
我准备完成一个python文件,相当于在googlemaps上再次封装,让他能够简单使用。向外提供一个函数,也就是api,需要的参数是起始的坐标,返回加工好的数据。同时默认一个参数save=True
,用于以坐标为文件名,存放数据。
此接口,将调用本文件中的多个私有方法:
1 获取路径信息
2 筛选出最快和最慢的路径
3 将路径信息转换结构,剔除不需要返回的信息
4 保存到指定路径下
5 统一输出,如果后面需要,用logging替代print
同时,编写_test_demo,也就是一个例子,可以让同学便于使用。完成的效果在github上,查看原文可查看。
一些坑
一些在完成过程中需要解决或者关注的东西
1 获取google key,也就是在初始化googlemaps的client时,需要的参数,相当于,这是google map 的要求。所以需要有google的账号,然后按照googlemaps的github上的教程,生成key。这需要翻墙,以及,英文能力。
2 代理的设置。使用的是shadowsocks,代码要能连外网,需要改为全局模式。
3 同学的需求在一开始是模糊的,测试发现,最短和最快是同一路径。可能是因为,没有加参数,出发时间,出行方式,以及,最短路本身就很有可能是最快路,还有可能是,选择的起始坐标,交通良好。现在已经添加了出发时间,以及出行方式,但测得的结果,最短仍然是最快——这是google map 返回的数据,加工过程暂时没有错误,google map 应该也不会出问题,那就是只有在传入参数时,限制不够。这里的数据正确性,待确认。
额外配置
此次采用的是全局代理,所以代码能够直接连接到外网。但如果没有梯子,只有代理IP,那么在初始化client时,是可以指定代理信息的。googlemaps库依赖于requets库,requests库是支持代理的。有个参数,requests_kwargs
,能够以字典的形式,传入requests库需要的参数。




