Python 案例:统计 SofaScore 综合评分
下面给你一个完整的 Python 案例,演示如何从 SofaScore 获取并统计球队/球员的综合评分。

方案说明
SofaScore 官方 API(https://api.sofascore.com/api/v1/)是公开接口,但有反爬限制(Cloudflare 防护),所以下面给出两种方案:
- 方案 A:直接调用 API(需要正确的请求头)
- 方案 B:浏览器抓包 + 手动保存 JSON 后离线统计(更稳定)
方案 A:直接调用 API
import requests
import pandas as pd
import time
HEADERS = {
"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/122.0 Safari/537.36"),
"Referer": "https://www.sofascore.com/",
"Accept": "application/json, text/plain, */*",
}
def get_team_last_matches(team_id: int, page: int = 0):
"""获取球队最近比赛列表"""
url = f"https://api.sofascore.com/api/v1/team/{team_id}/events/last/{page}"
r = requests.get(url, headers=HEADERS, timeout=10)
r.raise_for_status()
return r.json().get("events", [])
def get_match_player_stats(match_id: int):
"""获取一场比赛的球员评分"""
url = f"https://api.sofascore.com/api/v1/event/{match_id}/lineups"
r = requests.get(url, headers=HEADERS, timeout=10)
r.raise_for_status()
data = r.json()
rows = []
for side in ("home", "away"):
team_name = data[side]["team"]["name"]
for player in data[side]["players"]:
p = player["player"]
stats = player.get("statistics", {}) or {}
rows.append({
"team": team_name,
"player": p["name"],
"position": p.get("position"),
"rating": stats.get("rating"),
})
return rows
# ===== 示例:统计某球队近几场球员平均评分 =====
TEAM_ID = 44 # Manchester City 的 ID(可在 SofaScore URL 中找到)
all_rows = []
for page in range(3): # 取最近3页
events = get_team_last_matches(TEAM_ID, page)
for ev in events:
try:
rows = get_match_player_stats(ev["id"])
for r in rows:
r["match_id"] = ev["id"]
r["date"] = ev["startTimestamp"]
all_rows.extend(rows)
time.sleep(1) # 避免触发限流
except Exception as e:
print("跳过比赛", ev["id"], e)
df = pd.DataFrame(all_rows)
df["rating"] = pd.to_numeric(df["rating"], errors="coerce")
df = df.dropna(subset=["rating"])
# 按球员统计平均分
summary = (df.groupby(["team", "player"])["rating"]
.agg(["count", "mean", "max", "min"])
.round(2)
.sort_values("mean", ascending=False))
print(summary.head(20))
summary.to_csv("sofascore_ratings.csv", encoding="utf-8-sig")
方案 B:离线 JSON 统计(推荐)
API 被拦截,可以直接在浏览器 F12 → Network 里复制对应的 JSON 保存到本地,然后统计:
import json
import pandas as pd
# 假设你保存了 lineups 接口返回的 JSON
with open("lineups.json", "r", encoding="utf-8") as f:
data = json.load(f)
rows = []
for side in ("home", "away"):
team = data[side]["team"]["name"]
for player in data[side]["players"]:
stats = player.get("statistics", {}) or {}
rows.append({
"team": team,
"player": player["player"]["name"],
"position": player["player"].get("position"),
"rating": stats.get("rating"),
"goals": stats.get("goals", 0),
"assists": stats.get("goalAssist", 0),
"passes": stats.get("totalPass", 0),
})
df = pd.DataFrame(rows)
df["rating"] = pd.to_numeric(df["rating"], errors="coerce")
df = df.dropna(subset=["rating"])
# 全场平均
print("全场平均评分:", round(df["rating"].mean(), 2))
# 各队平均
print("\n各队平均评分:")
print(df.groupby("team")["rating"].mean().round(2))
# MVP
print("\n全场最佳:")
print(df.sort_values("rating", ascending=False).head(3))
# 分位置平均
print("\n按位置评分:")
print(df.groupby("position")["rating"].mean().round(2))
综合评分公式(自定义加权)
SofaScore 原生 rating 是 0–10 分,如果你想做多维度综合评分,可以按权重合成:
import numpy as np
def combined_score(row):
"""
示例权重:
SofaRating 60% + 进球*0.5 + 助攻*0.3 + 传球成功率 10%
"""
rating = row["rating"] or 0
goal = (row.get("goals") or 0) * 0.5
assist = (row.get("assists") or 0) * 0.3
# 传球成功率归一化到 0-1
acc = (row.get("accuratePass") or 0) / max(row.get("totalPass") or 1, 1)
return 0.6 * rating + goal + assist + 0.1 * (acc * 10)
df["combined"] = df.apply(combined_score, axis=1)
# 结果排序
top = df.sort_values("combined", ascending=False)[
["player", "team", "rating", "goals", "assists", "combined"]
].head(10)
print(top.round(2))
常见问题
| 问题 | 说明 |
|---|---|
| 403 / Cloudflare | SofaScore 有反爬,需完整浏览器头或使用 Playwright |
| Team ID 怎么找 | 打开 SofaScore 球队页面,URL 中 team/44 数字即 ID |
| 球员评分在哪个字段 | /event/{id}/lineups → players[].statistics.rating |
| 限流 | 每请求间隔 ≥ 1s,建议加缓存 |
| 球员姓名重复 | 用 player.id 分组更可靠 |
若使用 Playwright 绕过防护(简版)
from playwright.sync_api import sync_playwright
import json
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
# 先访问主页拿 cookie
page.goto("https://www.sofascore.com/")
# 直接用页面上下文请求 API
resp = page.request.get(
"https://api.sofascore.com/api/v1/team/44/events/last/0"
)
print(resp.json())
browser.close()
如果你告诉我具体需求(统计某球员赛季评分、某联赛所有球队平均分、或按位置分组统计),我可以把代码进一步细化成可直接运行的脚本。