高德API公交数据解析:3步将JSON响应转为结构化DataFrame 高德API公交数据解析实战从JSON响应到结构化DataFrame的完整指南引言为什么需要处理公交API数据在智慧城市和交通数据分析领域公交线路信息是基础而关键的数据资源。高德地图API提供了丰富的公交数据接口但返回的JSON结构往往嵌套复杂直接使用存在诸多不便数据结构混乱多层级嵌套的JSON难以直观理解信息提取困难关键数据分散在不同层级中分析门槛高原始数据格式不适合直接进行统计分析本文将手把手教你使用Python将高德API返回的公交线路JSON数据转换为规整的DataFrame涵盖从API调用到数据清洗的完整流程。无论你是刚接触API调用的新手还是需要处理复杂JSON的中级开发者都能从中获得实用技巧。1. 高德公交API基础配置1.1 获取API密钥使用高德地图API的第一步是申请开发者密钥访问 高德开放平台 注册账号进入控制台创建新应用在Key管理页面获取Web服务类型的API Key# 配置示例 AMAP_KEY your_api_key_here # 替换为实际Key CITY_NAME 北京 # 目标城市 LINE_NAME 1路 # 公交线路1.2 理解公交线路API响应结构高德公交线路API的核心端点是https://restapi.amap.com/v3/bus/linename典型请求参数包括key: API密钥city: 城市名称keywords: 公交线路名称extensions: 返回数据详细程度(all/base)提示设置extensionsall可获取包含站点坐标、行驶轨迹等完整信息2. JSON响应深度解析2.1 原始API请求与响应让我们先发起一个基础请求并查看原始响应import requests import json url fhttps://restapi.amap.com/v3/bus/linename?key{AMAP_KEY}city{CITY_NAME}extensionsallkeywords{LINE_NAME} response requests.get(url).json() print(json.dumps(response, indent2, ensure_asciiFalse))典型响应结构包含以下关键字段{ status: 1, info: OK, buslines: [ { name: 1路, start_stop: 老山公交场站, end_stop: 四惠枢纽站, busstops: [ { name: 老山公交场站, location: 116.231843,39.913055, sequence: 1 } ], polyline: 116.231843,39.913055;116.232028,39.912872... } ] }2.2 关键数据结构图解通过分析API响应我们可以绘制出数据结构关系图buslines (列表) ├─ 0 (字典) ├─ name: 线路名称 ├─ start_stop: 始发站 ├─ end_stop: 终点站 ├─ distance: 全程距离(米) ├─ busstops (列表) │ ├─ 0 (字典) │ │ ├─ name: 站点名 │ │ ├─ location: 经纬度 │ │ └─ sequence: 站点序号 │ └─ ... └─ polyline: 行驶轨迹坐标串3. 数据提取与转换实战3.1 基础信息提取函数首先创建提取公交线路基础信息的函数def extract_basic_info(busline): 提取线路基础信息 return { line_name: busline[name], start_stop: busline[start_stop], end_stop: busline[end_stop], total_distance: float(busline[distance]), stop_count: len(busline[busstops]) }3.2 站点信息处理站点信息需要特殊处理特别是坐标的拆分def process_stops(busstops): 处理站点列表数据 stops_data [] for stop in busstops: lng, lat map(float, stop[location].split(,)) stops_data.append({ stop_name: stop[name], sequence: int(stop[sequence]), longitude: lng, latitude: lat }) return stops_data3.3 轨迹坐标解析行驶轨迹坐标以分号分隔需要转换为经纬度列表def parse_polyline(polyline_str): 解析轨迹坐标字符串 return [ list(map(float, point.split(,))) for point in polyline_str.split(;) ]4. 构建结构化DataFrame4.1 整合数据到Pandas将提取的数据整合为DataFrameimport pandas as pd def json_to_dataframe(response): 将API响应转换为结构化DataFrame busline response[buslines][0] # 基础信息 line_info extract_basic_info(busline) # 站点信息 stops_df pd.DataFrame(process_stops(busline[busstops])) # 轨迹信息 trajectory parse_polyline(busline[polyline]) trajectory_df pd.DataFrame(trajectory, columns[longitude, latitude]) trajectory_df[point_type] trajectory return { line_info: pd.DataFrame([line_info]), stops: stops_df, trajectory: trajectory_df }4.2 数据表示例执行转换后我们得到三个结构清晰的DataFrame线路信息表line_namestart_stopend_stoptotal_distancestop_count1路老山公交场站四惠枢纽站15200.025站点信息表stop_namesequencelongitudelatitude老山公交场站1116.23184339.913055老山南路东口2116.23202839.912872轨迹点表longitudelatitudepoint_type116.23184339.913055trajectory116.23202839.912872trajectory5. 高级处理技巧5.1 处理多线路情况当API返回多条线路时如环线我们需要调整处理逻辑def multi_line_processing(response): 处理可能的多线路响应 results [] for busline in response[buslines]: line_data json_to_dataframe({buslines: [busline]}) results.append(line_data) return results5.2 数据增强与计算基于基础数据我们可以计算更多有用指标def enhance_stop_data(stops_df): 计算站点间距等增强数据 stops_df stops_df.sort_values(sequence) # 计算相邻站点距离 stops_df[distance_to_next] stops_df.apply( lambda row: haversine( (row[latitude], row[longitude]), (stops_df.at[row.name1, latitude], stops_df.at[row.name1, longitude]) ) if row.name1 in stops_df.index else 0, axis1 ) return stops_df def haversine(coord1, coord2): 计算两个坐标点的球面距离 # 实现省略...5.3 异常处理机制健壮的生产代码需要完善的错误处理def safe_api_call(url): 带错误处理的API调用 try: response requests.get(url, timeout10) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(fAPI请求失败: {e}) return None except json.JSONDecodeError: print(响应解析失败) return None6. 完整代码示例以下是整合所有功能的完整实现import requests import pandas as pd from math import radians, sin, cos, sqrt, asin class AmapBusProcessor: def __init__(self, api_key): self.api_key api_key self.base_url https://restapi.amap.com/v3/bus/linename def get_bus_line(self, city, line_name): 获取公交线路数据 params { key: self.api_key, city: city, keywords: line_name, extensions: all } response requests.get(self.base_url, paramsparams).json() return self.process_response(response) def process_response(self, response): 处理API响应 if response[status] ! 1: raise ValueError(fAPI返回错误: {response[info]}) results [] for busline in response[buslines]: line_data { line_info: self._extract_line_info(busline), stops: self._process_stops(busline[busstops]), trajectory: self._parse_polyline(busline[polyline]) } results.append(line_data) return results[0] if len(results) 1 else results def _extract_line_info(self, busline): 提取线路信息 return pd.DataFrame([{ line_name: busline[name], start_stop: busline[start_stop], end_stop: busline[end_stop], total_distance: float(busline[distance]), stop_count: len(busline[busstops]) }]) def _process_stops(self, busstops): 处理站点数据 stops_data [] for stop in busstops: lng, lat map(float, stop[location].split(,)) stops_data.append({ stop_name: stop[name], sequence: int(stop[sequence]), longitude: lng, latitude: lat }) return pd.DataFrame(stops_data) def _parse_polyline(self, polyline_str): 解析轨迹坐标 points [ list(map(float, point.split(,))) for point in polyline_str.split(;) ] return pd.DataFrame(points, columns[longitude, latitude])使用示例processor AmapBusProcessor(AMAP_KEY) data processor.get_bus_line(北京, 1路) # 保存到CSV data[stops].to_csv(bus_stops.csv, indexFalse) data[trajectory].to_csv(bus_trajectory.csv, indexFalse)7. 实际应用场景结构化的公交数据可以支持多种分析应用站点密度分析统计各区域公交站点分布线路优化评估计算线路非直线系数等指标可视化展示在地图上绘制线路轨迹和站点换乘分析结合多线路数据计算换乘方案# 简单可视化示例 import matplotlib.pyplot as plt plt.figure(figsize(10, 8)) plt.scatter( data[trajectory][longitude], data[trajectory][latitude], s5, label轨迹点 ) plt.scatter( data[stops][longitude], data[stops][latitude], s50, cred, label站点 ) plt.legend() plt.title(f{data[line_info][line_name][0]}公交线路) plt.show()处理高德API公交数据的关键在于理解其嵌套的JSON结构并设计合理的数据提取逻辑。通过将复杂JSON转换为结构化的DataFrame我们获得了更适合分析的数据形式。实际项目中你可能还需要考虑数据更新机制、异常处理、性能优化等问题。