← 全部指南

赛季赛历、下一场比赛与结果

用 Python 构建带「下一场比赛」倒计时的赛历,以及每一轮的结果页。

阅读约 8 分钟

每个赛车应用都需要赛历。本指南基于 races 端点构建三样东西:

  1. 按轮次排序的完整赛季赛历。
  2. 下一场比赛,用于倒计时或推送通知。
  3. 已完赛轮次的正式结果。

赛历

GET /races/seasons/{year} 返回某一组别一个赛季的所有轮次:

{
  "round_number": 12,
  "name": "Qatar Airways Grand Prix of Great Britain",
  "circuit_name": "Silverstone Circuit, Silverstone",
  "country": "United Kingdom",
  "flag": "🇬🇧",
  "category": "MOTOGP",
  "race_date": "2026-08-09",
  "season_year": 2026
}

返回的轮次不保证有序,因此请按 round_number 排序:

import os
from datetime import date

import requests

HOST = "motogp-api-championship-data-statistics.p.rapidapi.com"
HEADERS = {"X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"], "X-RapidAPI-Host": HOST}


def get(path: str, **params):
    res = requests.get(f"https://{HOST}{path}", headers=HEADERS, params=params, timeout=10)
    res.raise_for_status()
    return res.json()["data"]


def calendar(year: int, category: str = "MOTOGP") -> list[dict]:
    races = get(f"/races/seasons/{year}", category=category)
    return sorted(races, key=lambda r: r["round_number"])


for race in calendar(2026):
    print(f"R{race['round_number']:>2}  {race['race_date']}  {race['flag']}  {race['name']}")
...
R 6  2026-05-17  🇪🇸  Monster Energy Grand Prix of Catalunya
...
R12  2026-08-09  🇬🇧  Qatar Airways Grand Prix of Great Britain
...

下一场比赛

race_date 是 ISO 日期(YYYY-MM-DD),因此可以按字符串排序和比较,也可以用 date.fromisoformat 解析:

def next_race(races: list[dict], today: date) -> dict | None:
    upcoming = [r for r in races if date.fromisoformat(r["race_date"]) >= today]
    return upcoming[0] if upcoming else None


race = next_race(calendar(2026), date.today())
if race:
    days = (date.fromisoformat(race["race_date"]) - date.today()).days
    print(f"Next: {race['name']} at {race['circuit_name']} in {days} days")
else:
    print("Season finished")

某一轮的结果

一轮比赛结束后,可按赛季和轮次获取其结果:

def results(year: int, round_number: int, category: str = "MOTOGP") -> list[dict]:
    rows = get(f"/races/seasons/{year}/round/{round_number}/results", category=category)
    return sorted(rows, key=lambda r: r["position"])


for row in results(2026, 1)[:3]:
    print(f"P{row['position']}  {row['rider_name']:<22} {row['team_name']:<32} +{row['points']} pts")
P1  Marco Bezzecchi        Aprilia Racing                   +25 pts
P2  ...
P3  Raúl Fernández         SuperFile Trackhouse MotoGP Team +16 pts

每一行都有 status:已计入名次的车手为 FINISHED,其他情况为 DNF 或 DNS 等值。请把未完赛的车手显示在已完赛车手之下。

赛后轮询

比赛结果会在每个比赛周末之后加入。如果你要发送「结果已出」通知,请在比赛日期之后每 30–60 分钟轮询一次最新一轮的结果端点,而不是每隔几秒一次:空列表表示「还没有」,缓慢轮询能让你远低于配额上限。不在赛历中的轮次会返回 404。

def results_ready(year: int, round_number: int) -> bool:
    return len(results(year, round_number)) > 0

Moto2 和 Moto3

向上述任一函数传入 category="MOTO2" 或 category="MOTO3" 即可。轮次编号和日期遵循同一份赛历,因此合并周末视图只需按 round_number 合并。

下一篇指南 → 为 MotoGP 梦幻联赛计分