将API返回JSON快速转为Pandas DataFrame的最优方案(体育博彩场景)
高效将体育博彩API数据转换为Pandas DataFrame的方案
当前代码的性能瓶颈
- 循环创建临时
DataFrame并反复调用pd.concat:每次concat都会复制已有数据,当数据量达到3万条时,时间开销会呈指数级上升。 - 使用
requests.json()解析JSON:底层依赖标准库json.loads,在大量数据场景下解析速度不够理想。
优化方案
1. 先收集所有数据到列表,再一次性生成DataFrame
列表的append操作是常数时间复杂度,最后用pd.DataFrame()批量转换,彻底避免多次复制数据的开销。
2. 用msgspec替代标准JSON解析
msgspec是基于C扩展的高性能JSON解析库,解析速度比标准库快2-5倍,尤其适合处理大量API返回的JSON数据。
优化后代码示例
import pandas as pd import requests import msgspec # 初始化数据收集列表(高效存储所有记录) records = [] for game in games.json()['data']: odds_params = {'key': api_key, 'game_id': game['id'], 'sportsbook': sportsbooks} response = requests.get(api_url, params=odds_params) # 用msgspec直接解析响应字节流,跳过字符串转换,比response.json()更快 odds_data = msgspec.json.decode(response.content) # 提取赛事基础字段(排除不需要的is_live,保留id) base_game_data = {k: v for k, v in game.items() if k != 'is_live'} # 遍历每条赔率数据,合并赛事与赔率字段 for odd in odds_data['data'][0]['odds']: record = base_game_data.copy() # 重命名赔率id字段,避免与赛事id冲突 record['odds_id'] = odd.pop('id') # 合并赔率其他字段 record.update(odd) records.append(record) # 一次性生成最终DataFrame,vectorized操作效率远超循环concat master_df = pd.DataFrame(records)
额外优化建议
如果API响应格式固定,可以用msgspec.Struct定义数据结构,实现类型校验的同时进一步提升解析速度:
from msgspec import Struct # 定义赔率数据结构 class Odd(Struct): id: str sports_book_name: str name: str price: float checked_date: str bet_points: str | None is_main: bool is_live: bool market_name: str home_rotation_number: str | None away_rotation_number: str | None deep_link_url: str | None player_id: str | None # 定义API响应结构 class OddsResponse(Struct): data: list[dict] # 指定类型解析,速度更快且自带类型校验 odds_data = msgspec.json.decode(response.content, type=OddsResponse)
内容的提问来源于stack exchange,提问作者bbennett36
相关产品推荐
相关产品推荐

