1. 作者介绍
张志豪,男,西安工程大学电子信息学院,2025 级学生
研究方向:Python 程序开发、地图 API 应用、数据可视化
电子邮件:2871509979@qq.com
2. 理论知识介绍
2.1 腾讯位置服务 WebService API 概述
腾讯位置服务 WebService API 是基于 HTTP/HTTPS 的后台接口,支持服务器端调用,可实现路线规划、坐标解析、距离计算等地图相关功能。本次使用驾车路线规划接口,能够根据起点、终点、途经点坐标,返回结构化的导航路线、距离、耗时、轨迹坐标串等数据。
<font color="red">重要提醒</font>:该接口区分免费版与商业版,免费账号存在调用次数限额,生产环境必须开启签名校验保障接口安全。
2.2 API 签名校验原理
签名校验是接口的安全防护机制,核心流程:将请求路径、请求参数、密钥 SK 按照固定规则拼接,再通过 MD5 算法加密生成签名字符串,随请求一并提交。服务端校验签名一致后,才会返回数据,可有效防止请求伪造。
2.3 Folium 可视化库介绍
Folium 是 Python 中基于 Leaflet.js 开发的交互式地图可视化库,可在本地生成 HTML 格式地图文件。支持自定义底图、坐标点标记、轨迹线条绘制、弹窗信息等功能,无需依赖第三方图片接口,不受 URL 长度、调用配额限制,适合路线轨迹可视化场景。
2.4 腾讯静态图 API 优缺点分析
腾讯静态图 API 可直接返回路线图片,调用逻辑简单,但存在硬性限制:理论支持 800 个坐标点,实际使用中坐标点超过 150 个会出现地图视野异常,超过 200 个会发生路线截断,仅适用于短距离、简单路线展示。
3. 实验过程介绍
3.1 实验环境与依赖准备
3.1.1 运行环境
- 编程语言:Python 3.12
- 运行系统:Windows 10/11
- 开发工具:VS Code、PyCharm
3.1.2 所需安装依赖包
打开终端执行以下命令安装第三方库:
bash
运行
网络请求库,用于调用API接口
pip install requests
地图可视化库,用于绘制交互式路线地图
pip install folium
3.1.3 账号与密钥准备
- 注册并登录腾讯位置服务控制台,创建出行类应用;
- 为应用添加 WebService API 类型 Key,并按需开启签名校验,保存 Key 与 SK 密钥;
<font color="orange">重要提醒</font>:SK 密钥仅创建时显示一次,禁止上传至代码仓库、公开分享。
3.2 数据集与接口参数说明
本实验无传统数据集,核心数据为经纬度坐标:
- 输入数据:起点经纬度、终点经纬度、可选途经点经纬度;
- 接口返回数据:路线总距离、预计耗时、分段导航步骤、轨迹 PolyLine 坐标串;
- 路线策略:支持LEAST_TIME(最短时间)、LEAST_DISTANCE(最短距离)等模式。
3.3 完整实验代码(含详细注释)
3.3.1 方案一:WebService API + Folium 交互式绘图(主方案)
python
python
运行
# 导入所需标准库与第三方库
import requests
import hashlib
import folium
# ===================== 密钥配置区(请替换为自己的Key和SK) =====================
KEY = "你的腾讯位置服务Key"
SK = "你的腾讯位置服务SK"
# ===========================================================================
def driving_route(from_coord: str, to_coord: str, waypoints: str = None, policy: str = "LEAST_TIME") -> dict:
"""
调用腾讯驾车路线规划API,获取路线原始数据
:param from_coord: 起点经纬度,格式 纬度,经度
:param to_coord: 终点经纬度,格式 纬度,经度
:param waypoints: 途经点,多个点用分号分隔,选填
:param policy: 路线规划策略,默认最短时间
:return: 接口返回的json字典数据
"""
# 1. 组装基础请求参数
params = {
"from": from_coord,
"to": to_coord,
"key": KEY,
"output": "json",
"policy": policy
}
# 2. 如果存在途经点,追加参数
if waypoints:
params["waypoints"] = waypoints
# 3. 接口请求路径
api_path = "/ws/direction/v1/driving"
# 4. 参数按字母排序(签名规则要求)
sorted_params = sorted(params.items())
# 拼接参数字符串
query_str = "&".join(f"{k}={v}" for k, v in sorted_params)
# 拼接签名字符串并进行MD5加密
sign_str = api_path + query_str + SK
sign_result = hashlib.md5(sign_str.encode("utf-8")).hexdigest()
# 5. 加入签名,拼接完整请求参数
final_params = params.copy()
final_params["sig"] = sign_result
# 6. 发送GET请求
url = "https://apis.map.qq.com" + api_path
try:
response = requests.get(url, params=final_params, timeout=10)
response.raise_for_status() # 捕获HTTP请求异常
return response.json()
except Exception as e:
print(f"接口请求异常:{e}")
return {}
def draw_route_map(route_data, save_name="route_map.html"):
"""
使用folium绘制交互式路线地图
:param route_data: API返回的路线数据
:param save_name: 地图保存文件名
"""
# 解析起点坐标
start_lat = route_data["result"]["start"]["lat"]
start_lng = route_data["result"]["start"]["lng"]
# 1. 初始化空白地图
map_obj = folium.Map(
location=[start_lat, start_lng],
zoom_start=12,
tiles=None,
control_scale=True
)
# 2. 配置多类型底图(支持切换)
tile_config = {
"腾讯地图": "https://rt{0}.map.gtimg.com/tile?z={z}&x={x}&y={y}",
"高德地图": "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}"
}
for name, url in tile_config.items():
folium.TileLayer(url, name=name).add_to(map_obj)
# 3. 绘制行车轨迹线
# 解析路线坐标(示例简化处理)
route_points = []
for step in route_data["result"]["routes"][0]["steps"]:
lat = step["start_location"]["lat"]
lng = step["start_location"]["lng"]
route_points.append([lat, lng])
folium.PolyLine(
locations=route_points,
color="#0066ff",
weight=5,
opacity=0.8,
popup="行车路线"
).add_to(map_obj)
# 4. 标记起点(绿色)
folium.Marker(
location=[start_lat, start_lng],
icon=folium.Icon(color="green", icon="play", prefix="fa"),
popup="起点"
).add_to(map_obj)
# 5. 标记转向点(橙色圆点)
for point in route_points[1::5]:
folium.CircleMarker(
location=point,
radius=5,
color="#ff6600",
fill=True
).add_to(map_obj)
# 6. 添加图层切换控件,保存地图文件
folium.LayerControl().add_to(map_obj)
map_obj.save(save_name)
print(f"地图已成功保存为:{save_name}")
# 主程序入口
if __name__ == "__main__":
# 自定义起点、终点经纬度
start = "34.278,108.954"
end = "34.192,108.896"
# 调用接口获取路线数据
route_result = driving_route(start, end)
if route_result.get("status") == 0:
# 打印文本路线信息
total_distance = route_result["result"]["routes"][0]["distance"] / 1000
total_time = route_result["result"]["routes"][0]["duration"] // 60
print(f"路线总距离:{total_distance:.2f} 公里")
print(f"预计行驶时间:{total_time} 分钟")
print("详细导航步骤:")
for idx, step in enumerate(route_result["result"]["routes"][0]["steps"]):
print(f"{idx+1}. {step['road_name']}:{step['direction']},距离{step['distance']}米")
# 绘制可视化地图
draw_route_map(route_result)
else:
print(f"路线获取失败:{route_result.get('message', '未知错误')}")
3.3.2 方案二:静态图 API 坐标采样代码(适配 URL 限制)
python
python
运行
def decode_polyLine(polyLine):
"""
解码腾讯PolyLine加密坐标串
:param polyLine: 加密坐标字符串
:return: 解析后的经纬度坐标列表
"""
Lat = 0
Lng = 0
points = []
for i in range(0, len(polyLine), 2):
Lat += polyLine[i] / 1000000
Lng += polyLine[i+1] / 1000000
points.append((round(Lat, 6), round(Lng, 6)))
return points
def safe_sample(points, max_Len=100):
"""
坐标采样函数,减少坐标点数,规避URL超长问题
:param points: 原始坐标列表
:param max_Len: 最大保留坐标点数
:return: 采样后的坐标列表
"""
# 坐标数量小于限制,直接返回
if len(points) <= max_Len:
return points
# 计算采样步长
step = len(points) // max_Len + 1
sampled_points = points[::step]
# 强制保留起点和终点,防止路线缺失
if sampled_points[0] != points[0]:
sampled_points.insert(0, points[0])
if sampled_points[-1] != points[-1]:
sampled_points.append(points[-1])
print(f"坐标采样完成:原始{len(points)}个点 → 最终{len(sampled_points)}个点")
return sampled_points
3.4 测试结果与问题总结
3.4.1 正常运行结果
- 文本输出结果
程序控制台打印路线总距离、预计行驶时长、分段导航指引。本次测试路线:总距离 39.23 公里,预计行驶 55 分钟,共输出 29 段详细行驶步骤,包含道路名称、行驶方向、路段距离。
- 可视化结果
代码运行后生成 route_map.html 文件,使用浏览器打开可查看交互式地图:
- 支持腾讯、高德多底图切换;
- 蓝色线条展示完整行车轨迹,绿色图标标记起点,橙色圆点标记转向点;
- 支持地图缩放、拖拽、鼠标悬停查看信息,画面清晰、路线完整。
3.4.2 实验中出现的问题及解决
- 问题 1:Key 每日调用量达到上限
现象:接口返回此key每日调用量已达到上限,请求失败。
解决:腾讯免费账号单应用 Key 有调用限额,可在控制台新建多个应用,使用不同 Key 轮换测试;商用可申请商业授权提升额度。
- 问题 2:签名校验失败(状态码 111)
现象:接口提示签名验证失败。
解决:测试环境可在 Key 配置页关闭签名校验;生产环境严格按照规则对参数排序、拼接、MD5 加密,保证 Key、SK 与代码匹配。
- 问题 3:静态图 API 路线截断 / 视野偏移
现象:坐标点过多时,地图路线缺失、定位偏移。
解决:使用safe_sample函数对坐标采样,控制坐标点数量在 200 以内。
4. 参考链接
- 腾讯位置服务官方文档:https://lbs.qq.com/service/webService/webServiceGuide/webServiceDirection
- Folium 官方文档:https://python-visualization.github.io/folium/
- Python Requests 库使用文档:https://requests.readthedocs.io/