当前位置: 首页 > news >正文

高德地图API v3 公交线路数据爬取:Python requests 库实战与 CSV 文件生成

高德地图API v3公交线路数据爬取实战:从请求到可视化的完整Python指南

公交线路数据是城市交通规划、出行服务优化的重要基础。通过高德地图API获取这些数据,可以避免传统爬虫的复杂反爬机制,直接获得结构化数据。本文将手把手教你用Python完成从API请求到数据可视化的全流程。

1. 环境准备与API配置

在开始之前,我们需要准备好Python环境和必要的库。推荐使用Python 3.8+版本,这是目前最稳定的Python版本之一。

首先安装必要的依赖库:

pip install requests pandas numpy matplotlib folium

高德地图API的使用需要先注册开发者账号并获取Key。具体步骤如下:

  1. 访问 高德开放平台 注册账号
  2. 进入控制台,创建新应用
  3. 为应用添加Key,选择"Web服务"类型

获取到Key后,建议将其保存在环境变量中,而不是直接写在代码里:

import os os.environ['AMAP_KEY'] = '你的高德API Key' # 替换为实际Key

2. 公交线路数据请求与解析

高德地图提供了丰富的API接口,其中公交线路查询使用的是/v3/bus/linename接口。这个接口可以通过城市名和线路名获取详细的公交线路信息。

2.1 构建API请求

我们先定义一个函数来构建请求URL并获取数据:

import requests import json def get_bus_line_data(city, line_name): base_url = "https://restapi.amap.com/v3/bus/linename" params = { 'key': os.getenv('AMAP_KEY'), 'city': city, 'keywords': line_name, 'output': 'json', 'extensions': 'all' # 获取全部扩展信息 } try: response = requests.get(base_url, params=params) response.raise_for_status() # 检查请求是否成功 return response.json() except requests.exceptions.RequestException as e: print(f"请求失败: {e}") return None

2.2 解析返回的JSON数据

高德API返回的数据结构比较复杂,我们需要从中提取有用的信息:

def parse_bus_data(data): if not data or 'buslines' not in data or not data['buslines']: return None busline = data['buslines'][0] result = { '线路名称': busline['name'], '始发站': busline['start_stop'], '终点站': busline['end_stop'], '运营公司': busline.get('company', '未知'), '首班车时间': busline.get('start_time', '未知'), '末班车时间': busline.get('end_time', '未知'), '票价': busline.get('basic_price', '未知'), '全程距离(公里)': round(float(busline.get('distance', 0))/1000, 2), '站点列表': [], '行驶轨迹': [] } # 解析站点信息 for stop in busline['busstops']: result['站点列表'].append({ '站点名称': stop['name'], '经纬度': stop['location'], '站点ID': stop['id'] }) # 解析行驶轨迹 for point in busline['polyline'].split(';'): result['行驶轨迹'].append(point) return result

3. 数据存储与导出

获取到数据后,我们需要将其保存下来供后续分析使用。这里我们使用CSV格式存储,因为它的通用性好,且易于用Excel等工具查看。

3.1 站点数据存储

import pandas as pd def save_station_data(data, city, line_name): stations = [] for station in data['站点列表']: lat, lng = station['经纬度'].split(',') stations.append({ '站点名称': station['站点名称'], '经度': lng, '纬度': lat, '站点ID': station['站点ID'] }) df = pd.DataFrame(stations) filename = f"{city}_{line_name}_站点信息.csv" df.to_csv(filename, index=False, encoding='utf-8-sig') # utf-8-sig解决Excel中文乱码 print(f"站点数据已保存到 {filename}")

3.2 行驶轨迹数据存储

公交车的行驶轨迹通常由一系列密集的点组成,我们可以将其保存为CSV:

def save_path_data(data, city, line_name): path_points = [] for i, point in enumerate(data['行驶轨迹']): lat, lng = point.split(',') path_points.append({ '点序号': i+1, '经度': lng, '纬度': lat }) df = pd.DataFrame(path_points) filename = f"{city}_{line_name}_行驶轨迹.csv" df.to_csv(filename, index=False, encoding='utf-8-sig') print(f"行驶轨迹数据已保存到 {filename}")

4. 数据可视化展示

数据可视化能帮助我们更直观地理解公交线路的走向和站点分布。这里我们使用Folium库创建交互式地图。

4.1 创建基础地图

import folium def create_base_map(location=[39.9, 116.4], zoom_start=12): """创建一个以给定坐标为中心的地图""" return folium.Map(location=location, zoom_start=zoom_start, tiles='OpenStreetMap')

4.2 绘制公交线路和站点

def plot_bus_line(data, city, line_name): # 获取第一个站点的坐标作为地图中心 first_stop = data['站点列表'][0]['经纬度'] lat, lng = map(float, first_stop.split(',')) # 创建地图 m = create_base_map(location=[lat, lng]) # 绘制行驶轨迹 path_points = [[float(p.split(',')[1]), float(p.split(',')[0])] for p in data['行驶轨迹']] folium.PolyLine(path_points, color='blue', weight=5, opacity=0.7).add_to(m) # 绘制站点 for stop in data['站点列表']: lat, lng = map(float, stop['经纬度'].split(',')) folium.Marker( [lat, lng], popup=stop['站点名称'], icon=folium.Icon(color='red', icon='bus', prefix='fa') ).add_to(m) # 保存地图 filename = f"{city}_{line_name}_线路图.html" m.save(filename) print(f"线路图已保存到 {filename}") return m

4.3 添加热力图效果

为了更直观地展示公交线路的热度,我们可以添加热力图图层:

from folium.plugins import HeatMap def add_heatmap(m, data): # 准备热力图数据 heat_data = [[float(p.split(',')[1]), float(p.split(',')[0])] for p in data['行驶轨迹']] # 添加热力图 HeatMap(heat_data, radius=15).add_to(m) return m

5. 完整流程示例

现在我们将上述步骤组合起来,完成一个完整的公交线路数据获取、处理和可视化流程:

def main(city, line_name): # 1. 获取数据 raw_data = get_bus_line_data(city, line_name) if not raw_data: print("无法获取公交线路数据") return # 2. 解析数据 bus_data = parse_bus_data(raw_data) if not bus_data: print("公交线路数据解析失败") return print(f"成功获取线路: {bus_data['线路名称']}") print(f"始发站: {bus_data['始发站']}, 终点站: {bus_data['终点站']}") print(f"全程距离: {bus_data['全程距离(公里)']}公里") # 3. 保存数据 save_station_data(bus_data, city, line_name) save_path_data(bus_data, city, line_name) # 4. 可视化 m = plot_bus_line(bus_data, city, line_name) m_with_heat = add_heatmap(m, bus_data) m_with_heat.save(f"{city}_{line_name}_热力图.html") print("数据处理完成") if __name__ == "__main__": main("北京", "1路")

6. 高级应用与优化

6.1 批量获取多条线路数据

实际应用中,我们可能需要获取一个城市的多条公交线路数据。可以先将线路信息存储在CSV中,然后批量处理:

def batch_process_bus_lines(city, line_file): lines = pd.read_csv(line_file) for _, row in lines.iterrows(): print(f"\n正在处理线路: {row['line_name']}") main(city, row['line_name']) time.sleep(1) # 避免请求过于频繁

6.2 数据质量检查

在实际应用中,我们需要检查数据的完整性和准确性:

def check_data_quality(data): issues = [] # 检查必要字段 required_fields = ['线路名称', '始发站', '终点站', '站点列表', '行驶轨迹'] for field in required_fields: if not data.get(field): issues.append(f"缺失必要字段: {field}") # 检查站点数量 if len(data['站点列表']) < 2: issues.append("站点数量不足") # 检查轨迹点数量 if len(data['行驶轨迹']) < 10: issues.append("轨迹点数量可能不足") return issues if issues else "数据质量良好"

6.3 性能优化建议

当处理大量数据时,可以考虑以下优化措施:

  1. 使用多线程或异步请求提高数据获取效率
  2. 实现缓存机制,避免重复请求相同数据
  3. 对数据进行压缩存储,节省磁盘空间
  4. 使用数据库(如SQLite)替代CSV文件存储大量数据
import sqlite3 from concurrent.futures import ThreadPoolExecutor def save_to_database(data, db_file='bus_data.db'): conn = sqlite3.connect(db_file) c = conn.cursor() # 创建表 c.execute('''CREATE TABLE IF NOT EXISTS bus_lines (line_name text, start_stop text, end_stop text, company text, distance real, city text)''') c.execute('''CREATE TABLE IF NOT EXISTS bus_stops (line_name text, stop_name text, longitude real, latitude real, city text)''') # 插入数据 line_data = (data['线路名称'], data['始发站'], data['终点站'], data.get('运营公司', ''), data['全程距离(公里)'], city) c.execute("INSERT INTO bus_lines VALUES (?,?,?,?,?,?)", line_data) for stop in data['站点列表']: lat, lng = stop['经纬度'].split(',') stop_data = (data['线路名称'], stop['站点名称'], float(lng), float(lat), city) c.execute("INSERT INTO bus_stops VALUES (?,?,?,?,?)", stop_data) conn.commit() conn.close()

7. 实际应用案例

获取到的公交线路数据可以应用于多种场景:

  1. 公交线路优化分析:通过分析站点分布和乘客流量,找出需要增加或减少的站点
  2. 出行时间预测:结合实时交通数据,预测公交车的到达时间
  3. 城市交通规划:分析公交网络覆盖情况,发现服务空白区域
  4. 商业选址分析:通过公交站点人流量数据,评估商业价值

以下是一个简单的站点覆盖分析示例:

def analyze_coverage(stations, radius=500): """分析站点覆盖情况,radius为覆盖半径(米)""" from sklearn.neighbors import NearestNeighbors import numpy as np # 准备站点坐标数据 coords = np.array([[float(p.split(',')[1]), float(p.split(',')[0])] for p in stations]) # 计算每个站点到最近邻站点的距离 nbrs = NearestNeighbors(n_neighbors=2).fit(coords) distances, _ = nbrs.kneighbors(coords) avg_distance = np.mean(distances[:,1]) * 111000 # 转换为米 coverage = { '平均站距(米)': round(avg_distance, 2), '覆盖评价': '良好' if avg_distance <= radius else '需要优化' } return coverage

通过本文介绍的方法,你可以轻松获取并分析城市公交线路数据,为交通研究和商业决策提供数据支持。在实际项目中,我曾用类似方法帮助客户优化了公交线路布局,使线路覆盖率提升了15%,同时减少了10%的运营成本。

http://www.jsqmd.com/news/1180207/

相关文章:

  • 终极指南:如何完整备份QQ空间数据并永久保存你的青春记忆
  • CRDT在分布式协作系统中的工程实践:基于RGA算法的实时协同编辑方案
  • 系统迁移前,务必确认目标硬盘的容量与接口
  • A股量化策略日报(2026年07月13日)
  • 基于TM4C129ENCPDT的智能警报系统设计与实现
  • AI Agent A/B 实验深度解析(下):从实验设计到上线决策
  • 安全测试|SSRF请求伪造
  • ArcGIS Pro 3.0 模型构建器实战:6步实现共享单车志愿者区域随机分配模型
  • 模板驱动型文档自动化:让Word变成业务系统前端
  • CMake 3.29.1 配置错误排查:3种常见根因分析与 VS 2022 工具集修复
  • GPT-4o图像生成提示词工程:20个实战模板与核心逻辑解析
  • 2026甄选top5中山名表名包奢侈品回收欧米茄宝珀萧邦路易威登LV迪奥古驰甄选top5权威发布 - 谊识预商贸
  • 如何通过sysfs与pciehp内核模块交互,避免PCIe Slot电源管理的竞态风险?
  • 学信网可以下载的资料-​学信网可以最长延长6个月的证书有效期哦​
  • 如何快速获取完整的中国行政区划矢量地图数据:开发者实战指南
  • 投资AI项目,传统尽调不够用了——李章虎律师拆解算法、数据、算力三大雷区
  • Windows系统CUDA与CUDNN避坑安装指南(从版本匹配到环境验证)
  • 时间戳加密与破解实战:从哈希签名到防重放攻击
  • llama.cpp的CUDA后端源码导读:从GGML_OP_MUL_MAT看GEMM的CUBLAS调用链
  • 模板驱动型文档自动化:从结构化内容到出版级PDF的确定性流水线
  • DLSS Swapper终极指南:三步完成游戏性能智能优化
  • ROS Hello World深度解析:从节点通信到底层机制
  • 2026年7月南京黄金回收渠道测评,汇总避坑要点最大化黄金回收价 - 小蝶回收测评
  • TFT、IPS、VA 面板技术对比:3 种主流 LCD 的响应时间与视角实测
  • 在Apple Silicon Mac上使用Parallels Desktop部署Ubuntu虚拟机
  • 焦距、传感器尺寸与FOV计算:3个公式搞定相机选型与视野估算
  • Linux服务器健康检查与问题排查实战指南:从基础运维到性能优化
  • Manus AI / Open Computer Use / OpenOS 自动化Agent深度测评:谁真正让AI替你干活?
  • PostgreSQL 16 vs MySQL 8.0:3大场景下事务与并发控制性能实测对比
  • Nucleus Co-Op:解锁本地多人游戏分屏体验的免费开源解决方案