
FastF1 的 Jolpica-F1 数据接口完全指南Ergast 兼容客户端的 API 端点、结果类型与分页机制【免费下载链接】Fast-F1FastF1 is a python package for accessing and analyzing Formula 1 results, schedules, timing data and telemetry项目地址: https://gitcode.com/GitHub_Trending/fa/Fast-F1Jolpica-F1 API 是 FastF1 获取 F1 历史成绩、赛历、积分榜等结构化数据的核心通道其前身是于 2025 年初关闭的 Ergast MRDMotor Racing DatabaseJolpica-F1 以「drop-in 兼容」的方式接管了全部接口。本文基于仓库内 docs/api_reference/jolpica.rst 展开结合 fastf1/ergast/interface.py 与 fastf1/ergast/structure.py 等源码完整讲解Ergast客户端的全部端点、Raw/DataFrame 两种结果格式、自动类型转换、MultiResponse 多表结构以及内置分页等核心机制读完即可在自己的 F1 数据分析脚本中熟练驾驭这套接口。背景Ergast 退役与 Jolpica-F1 接棒FastF1 的这一套 API 接口模块长期以 Ergast 命名但数据源已经切换。按照官方文档的说明Ergast motor racing databaseErgast MRD于 2025 年初关闭Jolpica-F1 作为其继任者提供了「drop-in compatible」可直接替换、无需改代码的替代 API。为了向后兼容模块名如fastf1.ergast并没有改动但所有数据现在都实际来自 Jolpica-F1。从源码可以看到数据源与请求参数的真实面貌fastf1/ergast/interface.py 中定义BASE_URL https://api.jolpi.ca/ergast/f1 TIMEOUT 5.0 HEADERS {User-Agent: fFastF1/{__version_short__}}也就是说所有端点请求都发往api.jolpi.ca/ergast/f1携带 5 秒超时与标识客户端版本的User-Agent。这一实现细节也说明只要请求 URL 结构与 Ergast 时代保持一致上层业务代码无需任何迁移即可继续工作。快速上手创建 Ergast 接口对象接口的入口是Ergast类位于 fastf1/ergast/init.py从fastf1.ergast.interface导入。创建方式非常直接from fastf1.ergast import Ergast ergast Ergast() # 全部使用默认参数 ergast_pandas Ergast(result_typepandas, auto_castTrue) # 显式指定 ergast_raw Ergast(result_typeraw) # 偏好 Raw 结果Ergast对象暴露了Jolpica-F1 API 的全部端点每个端点对应一个方法。从 interface.py 源码归纳端点方法分为两类单结果端点返回ErgastSimpleResponse或ErgastRawResponse方法对应端点说明get_seasons()seasons赛季列表get_race_schedule()races赛历 / 分站列表get_driver_info()drivers车手信息get_constructor_info()constructors制造商信息get_circuits()circuits赛道信息get_finishing_status()status完赛状态码列表多结果端点返回ErgastMultiResponse或ErgastRawResponse方法对应端点说明get_race_results()results分站正赛成绩get_qualifying_results()qualifying排位赛成绩get_sprint_results()sprint冲刺赛成绩get_driver_standings()driverStandings车手积分榜get_constructor_standings()constructorStandings制造商积分榜get_lap_times()laps单圈用时get_pit_stops()pitstops进站信息一个端点是返回单表还是多表由响应数据的结构复杂度决定而非人为指定——这正是下一节要讲的结果类型体系。结果类型Raw 与 Pandas DataFrame 双格式API 返回的数据在 FastF1 中有两种格式由result_type参数控制所有响应对象都继承自ErgastResponseMixin提供分页能力见下文Raw ResponseErgastRawResponse原始 JSON 数据的 JSON-like 表示通过json.load解析得到本质是一个list包装源码中class ErgastRawResponse(ErgastResponseMixin, list)。Flattened into Pandas DataFramesErgastSimpleResponse直接包装一个 PandasDataFrameErgastResultFrameErgastMultiResponse由一个描述性DataFrame.description和一个存放主体内容的DataFrame列表.content组成。端点的复杂度决定具体返回类型每个端点的文档都会标明。例如get_circuits、get_seasons属于简单端点而get_constructor_standings、get_race_results返回的是复杂的多级嵌套结构因此必须用ErgastMultiResponse承载。从 interface.py 的_build_result可以看出分发逻辑请求返回的 JSON 先取MRData段再剥离table如RaceTable、SeasonTable、category[name]主键剩余的响应头信息total、limit、offset 等用于驱动分页result_type raw时走ErgastRawResponse否则若存在subcategory如RaceResults、Laps就构造ErgastMultiResponse否则构造ErgastSimpleResponse。通用参数result_type、auto_cast 与 limit这三个参数既可以在构造Ergast时作为默认值设置也可以在每个端点方法调用时单独覆盖方法级参数优先源码中_build_default_result实现了「未显式传入则回落到实例默认值」的逻辑result_typeraw或pandas默认pandas选择返回 Raw 响应还是 DataFrame 响应。源码中Ergast.__init__的默认值为result_type: Literal[raw, pandas] pandas。auto_castbool默认True是否把所有值从 API 默认的字符串表示自动转换为最合适的数据类型。Ergast/Jolpica 提供的所有值原本都是字符串开启后如lat、long会转成float数字字段转成int时间字段转成datetime/timedelta等。limitint默认不设置单次请求返回的最大结果数。不设置时使用服务器默认值30允许的最大值为1000。实测中受此限制一次请求通常只能取回部分数据需要配合分页遍历完整结果集。offsetint默认 0仅作为方法级参数存在表示结果集内的偏移量用于手动分页。auto_cast 的底层实现自动类型转换并非魔法而是由 fastf1/ergast/structure.py 中的「类别category」元数据驱动的。每个端点对应一个 category 定义内含map字段到目标类型的映射与sub子类别。ErgastRawResponse._auto_cast会递归遍历数据对已知字段调用mappingtype完成转换ErgastResultFrame._flatten_element则负责在扁平化过程中同步完成类型转换。其中几个关键的类型转换函数值得注意date_from_ergast把YYYY-MM-DD格式的字符串转为datetime.datetimetime_from_ergast解析[hh:][mm:]ss[.micros][Z/±hh:mm]格式时间串为datetime.time源码注释指出这是为绕开旧版 Python 中datetime.time.fromisoformat的若干限制而自行实现的 ISO 8601 子集timedelta_from_ergast解析[±][hh:][mm:]ss[.micros]为datetime.timedeltasave_int把纯整数字符串转为int无法解析时返回-1用于表示 int 型缺失值因为int不支持真正的NaNsave_float把浮点字符串转为float无法解析时返回nan。缺省值约定官方文档明确提示-1用于表示int类型值的缺失。这一约定来自save_int的实现——典型的例子是 1954 年英国大奖赛中某位车手的完赛时间毫秒数为空字符串此时会被转换为-1而不是报错。常见意外行为Common Surprises首次使用这套接口的用户最可能被以下几点绊倒结果永远按升序返回。例如查询赛历而不指定赛季时会从 1950 年F1 首个赛季的最早赛季开始返回。同理不指定赛季查询积分榜时拿到的是最早可用赛季的数据。这决定了「默认查询」往往不会返回你直觉上想要的最新数据。过滤器组合受限且因端点而异。并非所有筛选参数的组合都被 API 允许而且每个端点的可用组合都不同。FastF1 并不代为限制这些组合因为关系相当复杂而是在服务器拒绝请求时抛出fastf1.exceptions.ErgastInvalidRequestError异常中会携带服务器的错误响应内容。FastF1 的 raw 响应并非完整 JSON。它只返回响应中的实际数据部分如赛道列表而版本号、查询参数、响应长度等元数据会被剥离——不过这些元数据会被内部用于分页与信息统计见后文total_results、is_complete。扁平化时部分键会被重命名以保证复杂响应扁平化后列名唯一典型例子Raw 响应中的url在 DataFrame 中变为circuitUrl。实战示例一Simple DataFrame 响应查询 2022 赛季举办过大奖赛的所有赛道这是典型的单 DataFrame 端点from fastf1.ergast import Ergast ergast Ergast() response_frame ergast.get_circuits(season2022) print(response_frame)输出形如circuitId ... country 0 albert_park ... Australia 1 americas ... USA 2 bahrain ... Bahrain ... 19 villeneuve ... Canada 20 yas_marina ... UAE 21 zandvoort ... Netherlands [22 rows x 7 columns]查看列名可以发现重命名规则 response_frame.columns Index([circuitId, circuitUrl, circuitName, lat, long, locality, country], dtypeobject)原始 JSON 里的url字段被重命名为circuitUrl响应中可能还有其他 URL 字段重命名是为了列名唯一。每个端点的文档都附带一张「API Mapping」展示原始响应结构、扁平化后的新键名与自动类型转换的目标类型同时还有一份「DataFrame Description」列出结果 DataFrame 的全部列名并标明auto_castTrue时各列被转换成的类型。实战示例二Raw 响应与类型转换对比需要拿到贴近 API 原貌的数据时指定result_typerawergast.get_circuits(season2022, result_typeraw)返回一个由 dict 组成的列表[{circuitId: albert_park, url: https://en.wikipedia.org/wiki/Albert_Park_Circuit, circuitName: Albert Park Grand Prix Circuit, Location: {lat: -37.8497, long: 144.968, locality: Melbourne, country: Australia}}, ...]注意此处lat、long已经是float因为默认开启auto_cast ergast.get_circuits(season2022, result_typeraw)[0][Location] {lat: -37.8497, long: 144.968, locality: Melbourne, country: Australia}而设置auto_castFalse后两者保持 API 提供的字符串原貌 ergast.get_circuits(season2022, result_typeraw, auto_castFalse)[0][Location] {lat: -37.8497, long: 144.968, locality: Melbourne, country: Australia}这也印证了「Ergast/Jolpica 本身只提供字符串」的实现事实。日常分析通常建议保持auto_castTrue它会让后续的数值运算、时间比较等操作省去大量手工转换。实战示例三MultiResponse 多表响应当端点返回复杂嵌套结构时如积分榜、完整分站成绩result_typepandas会得到ErgastMultiResponse。以制造商积分榜为例standings ergast.get_constructor_standings() # 未指定 season不指定赛季时接口按升序返回多个赛季的积分榜。响应对象提供两个核心属性源码定义见 interface.py.description描述性DataFrameErgastResultFrame每个赛季一行说明.content中各元素对应哪个赛季、哪个分站 standings.description season round 0 1958 11 1 1959 9 2 1960 10.content主体内容列表每个元素是一个赛季的积分榜DataFrame。.content的第i个元素与.description的第i行一一对应 standings.content[0] position positionText ... constructorName constructorNationality 0 1 1 ... Vanwall British 1 2 2 ... Ferrari Italian ... 8 9 9 ... OSCA Italian [9 rows x 8 columns]由于默认limit30的限制一次请求只能覆盖三个赛季的积分榜数据——这正是分页机制存在的意义。get_race_results也是同类端点官方示例中同时查询 2022 赛季前两个分站成绩时第二个分站只返回了前 10 名正是 30 条默认限制的直接体现可以通过调大limit或分页获取完整数据。分页机制内置翻页与手动偏移所有 Ergast 响应对象都通过ErgastResponseMixininterface.py获得分页能力。当响应超过单次请求的结果上限时API 会把结果切分为多个「页」。以get_seasons(limit3)为例 seasons ergast.get_seasons(limit3) seasons season seasonUrl 0 1950 https://en.wikipedia.org/wiki/1950_Formula_One... 1 1951 https://en.wikipedia.org/wiki/1951_Formula_One... 2 1952 https://en.wikipedia.org/wiki/1952_Formula_One...Mixin 提供以下成员.is_complete属性判断当前响应是否已包含请求对应的全部结果。实现逻辑是若响应头中的offset非零则必然不完整否则只有当limit total时才完整interface.py。.total_results属性该请求对应的可用结果总数来自响应头的total字段。例如赛季总数 74 seasons.is_complete False seasons.total_results 74.get_next_result_page()按当前请求相同的limit获取下一页结果 seasons.get_next_result_page() season seasonUrl 0 1953 https://en.wikipedia.org/wiki/1953_Formula_One... 1 1954 https://en.wikipedia.org/wiki/1954_Formula_One... 2 1955 https://en.wikipedia.org/wiki/1955_Formula_One....get_prev_result_page()获取上一页结果当offset已为 0 时抛出ValueError。手动偏移也可以直接在端点方法上指定offset参数跳过指定数量的结果 ergast.get_seasons(limit3, offset6) season seasonUrl 0 1956 https://en.wikipedia.org/wiki/1956_Formula_One... 1 1957 https://en.wikipedia.org/wiki/1957_Formula_One... 2 1958 https://en.wikipedia.org/wiki/1958_Formula_One...翻页实现的关键在于get_next_result_page内部通过_ergast_constructor重新构造Ergast并复用原请求保存的查询过滤器与选择器_query_metadata、_selectors将offset推进到原offset limit从而保证翻页时筛选条件与分页大小完全一致。当offset limit total时该方法会抛出ValueError(No more data after this response.)。一个实用的完整遍历模式resp ergast.get_seasons(limit30) while True: process(resp) # 处理当前页 if resp.is_complete: break resp resp.get_next_result_page()缓存与速率限制FastF1 的请求治理Jolpica-F1 本身存在速率限制rate limits但 FastF1 为所有 HTTP 请求内置了缓存与限速系统详见 docs/api_reference/cache_and_rate_limits.rst缓存默认开启命中缓存的请求不计入任何速率限制因此启用缓存可以「虚拟地」提升限速额度关闭缓存通常会显著拖慢程序官方强烈不建议这样做。当速率限制被超出时FastF1 采取两种策略之一若小幅延迟即可保持在限额内则主动节流soft rate limit拉长请求间隔若必须立即停止则抛出fastf1.exceptions.RateLimitExceededErrorhard rate limit。请求在源码层面统一经由Cache.requests_get发出interface.py因此 Jolpica-F1 接口自动享受与 FastF1 其他数据源一致的缓存与限速保障。异常处理三类 Ergast 专属异常接口相关的异常统一定义在 fastf1/exceptions.py形成了清晰的继承体系ErgastErrorErgast API 错误的基类捕获这一类即可覆盖全部接口异常。ErgastJsonError服务器响应无法解析时抛出ErgastJsonError继承自ErgastError。源码中会在解析失败时调用Cache.delete_response(url)丢弃可能损坏的缓存避免反复使用坏数据。ErgastInvalidRequestError服务器拒绝了请求如无效的过滤参数组合异常信息中会包含服务器响应原因。需要说明的是历史版本的fastf1.ergast.interface模块曾直接导出这些异常现在已迁移至fastf1.exceptionsinterface.py 中保留了__getattr__兼容层并发出弃用警告建议新代码一律从fastf1.exceptions导入。从源码理解端点的 URL 构造如果想深入理解各端点的筛选能力可以看 interface.py 的_build_url所有选择器season、round、circuit、constructor、driver、grid_position、results_position、fastest_rank、status、standings_position、lap_number、stop_number按固定顺序拼接进 URL 路径最终形成https://api.jolpi.ca/ergast/f1/{selectors}.json。这解释了为什么get_lap_times与get_pit_stops要求必须提供season和round它们没有可选性而get_race_schedule、get_circuits等允许省略筛选条件此时按升序从 1950 年开始返回全部数据。与其他数据源的关系值得注意的是仓库中还存在 fastf1/mvapiMultiviewer API提供赛道几何信息与实时数据接口fastf1/livetiming。它们与本文的 Jolpica-F1 接口相互补充Jolpica-F1fastf1.ergast负责结构化的历史成绩与赛季元数据而遥测、实时数据等则由其他模块承载。FastF1 上层 API如fastf1.core.Session内部也会调用Ergast客户端参见 fastf1/core.py 中self._ergast ergast.Ergast()因此掌握本接口的机制也有助于理解 FastF1 会话数据加载链路中成绩数据的来源。小结Jolpica-F1 接口是 FastF1 中面向结构化 F1 数据的标准入口。本文覆盖了其核心使用全貌从 Ergast 到 Jolpica-F1 的迁移背景、Ergast对象的全部端点、Raw/DataFrame 双结果格式、result_type/auto_cast/limit三个通用参数的语义与实现、ErgastMultiResponse的 description/content 双表结构、基于ErgastResponseMixin的内置分页与手动 offset以及缓存、速率限制与异常体系。继续深入可阅读 docs/api_reference/ergast.rst、docs/api_reference/exceptions.rst 与 docs/api_reference/cache_and_rate_limits.rst并在 fastf1/tests/test_ergast.py 与 fastf1/tests/test_api.py 中查看接口行为的测试验证。【免费下载链接】Fast-F1FastF1 is a python package for accessing and analyzing Formula 1 results, schedules, timing data and telemetry项目地址: https://gitcode.com/GitHub_Trending/fa/Fast-F1创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考