← Alle Anleitungen

Fahrerprofilseiten mit Karrierestatistiken

Kombinieren Sie Profil und Karrierebilanz eines Fahrers zu einer Profilkarte, abgerufen über die Startnummer.

8 Min. Lesezeit

Fan-Apps, Fantasy-Spiele und Nachrichtenseiten brauchen jeweils eine Seite pro Fahrer. Zwei Aufrufe liefern alles für eine Profilkarte: den Fahrer und seine Karrierebilanz.

Die zwei Aufrufe

GET /riders/93
GET /riders/93/career-stats

/riders/{rider_number} liefert das Profil:

{
  "rider_number": 93,
  "full_name": "Marc Márquez",
  "nationality": "Spain",
  "flag": "🇪🇸",
  "birth_date": "1993-02-17",
  "height_cm": 168,
  "weight_kg": 59,
  "team_name": "Gresini Racing MotoGP",
  "image_url": null
}

/riders/{rider_number}/career-stats liefert die Gesamtwerte:

{
  "rider_number": 93,
  "rider_name": "Marc Márquez",
  "total_wins": 44,
  "total_podiums": 66,
  "total_points": 1302,
  "world_titles": 2,
  "total_races": 118
}

Die Karrierewerte werden aus den in der API verfügbaren Saisons berechnet, nicht aus der gesamten Laufbahn eines Fahrers. Beschriften Sie sie entsprechend, zum Beispiel mit „Seit 2024“.

Beide parallel abrufen

import os
from concurrent.futures import ThreadPoolExecutor
from dataclasses import dataclass
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) -> dict:
    res = requests.get(f"https://{HOST}{path}", headers=HEADERS, timeout=10)
    res.raise_for_status()
    return res.json()["data"]


@dataclass(frozen=True)
class RiderCard:
    number: int
    name: str
    flag: str
    team: str
    age: int
    wins: int
    podiums: int
    titles: int
    races: int

    @property
    def podium_rate(self) -> float:
        return self.podiums / self.races if self.races else 0.0


def age_on(birth: str, today: date) -> int:
    born = date.fromisoformat(birth)
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day))


def rider_card(number: int) -> RiderCard:
    with ThreadPoolExecutor(max_workers=2) as pool:
        profile_f = pool.submit(get, f"/riders/{number}")
        stats_f = pool.submit(get, f"/riders/{number}/career-stats")
        profile, stats = profile_f.result(), stats_f.result()
    return RiderCard(
        number=profile["rider_number"],
        name=profile["full_name"],
        flag=profile["flag"],
        team=profile["team_name"],
        age=age_on(profile["birth_date"], date.today()),
        wins=stats["total_wins"],
        podiums=stats["total_podiums"],
        titles=stats["world_titles"],
        races=stats["total_races"],
    )


card = rider_card(93)
print(f"{card.flag} #{card.number} {card.name} — {card.team}, {card.age}")
print(f"{card.wins} wins, {card.podiums} podiums in {card.races} races ({card.podium_rate:.0%})")

Die Indexseiten bauen

Profilseiten brauchen eine Liste, von der aus sie verlinkt werden:

SeiteEndpunkt
Startfeld dieser SaisonGET /riders/seasons/{year}?category=MOTOGP
Fahrer nach LandGET /riders/nationality/{nationality} (z. B. Italy)
Jeder Fahrer in der DatenbankGET /riders?page=1&size=200

Verwenden Sie rider_number als URL-Slug (/riders/93/); danach suchen Fans.

Fehlende Daten behandeln

  • image_url kann null sein. Zeigen Sie statt eines defekten Bildes die Startnummer in einem farbigen Badge.
  • Eine nicht vergebene Nummer liefert 404 – rendern Sie eine „Fahrer nicht gefunden“-Seite statt eines Fehlers.
  • Fahrer wechseln zwischen den Saisons manchmal die Nummer. Wenn Sie Favoriten speichern, speichern Sie die Nummer mit der Saison, aus der sie stammt.
Nächste Anleitung → Saisonkalender, nächstes Rennen und Ergebnisse