关于 openfootball
openfootball 提供免费的公共领域足球比赛数据,以预生成的 JSON 文件发布,覆盖多个国家的联赛和赛事。开发者可按赛季和联赛代码获取数据,无需 API 密钥或身份验证。
主要功能
- 01提供多联赛及赛事的比赛数据
- 02通过赛季和联赛代码获取 JSON
- 03包含赛程、球队与比分字段
- 04支持 GitHub 原始链接及 Pages 镜像
- 05数据为公共领域且无需认证
适用场景
- 01获取某联赛某赛季的比赛与结果
- 02筛选特定球队或比赛轮次
- 03基于比分数据计算联赛积分榜
- 04跨赛季汇总球队战绩
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ outsharp/ shipp-skills --skill openfootball安装后在 Claude Code 中输入/openfootball确认已加载。
附带文件README.md
详细介绍
openfootball / football.json API
openfootball 是一个免费、开放、属于公有领域的足球(英式足球)数据集。football.json 仓库为全球主要联赛和锦标赛提供预构建的 JSON 文件。无需 API 密钥或身份验证。
数据源
有两种方式可以访问这些数据:
1. GitHub 原始 URL(首选)
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{league}.json
2. GitHub Pages 镜像
https://openfootball.github.io/{country}/{season}/{league-name}.json
建议: 使用
football.json仓库的 GitHub 原始 URL——它们采用简单、一致的命名规范,且可靠性最高。
URL 结构
https://raw.githubusercontent.com/openfootball/football.json/master/{season}/{code}.json
| 组成部分 | 描述 | 示例 |
|---|---|---|
{season} | 赛季目录——跨年或自然年 | 2024-25、2023-24、2025、2019 |
{code} | 采用 {country}.{division} 格式的联赛代码 | en.1、de.1、es.1、it.1、fr.1 |
可用联赛
英格兰
| 代码 | 联赛 | 级别 |
|---|---|---|
en.1 | 英格兰足球超级联赛 | 第 1 级 |
en.2 | 英格兰足球冠军联赛 | 第 2 级 |
en.3 | 英格兰足球甲级联赛 | 第 3 级 |
en.4 | 英格兰足球乙级联赛 | 第 4 级 |
德国
| 代码 | 联赛 | 级别 |
|---|---|---|
de.1 | 德国足球甲级联赛 | 第 1 级 |
de.2 | 德国足球乙级联赛 | 第 2 级 |
de.3 | 德国足球丙级联赛 | 第 3 级 |
西班牙
| 代码 | 联赛 | 级别 |
|---|---|---|
es.1 | 西班牙足球甲级联赛(La Liga) | 第 1 级 |
es.2 | 西班牙足球乙级联赛 | 第 2 级 |
意大利
| 代码 | 联赛 | 级别 |
|---|---|---|
it.1 | 意大利足球甲级联赛 | 第 1 级 |
it.2 | 意大利足球乙级联赛 | 第 2 级 |
法国
| 代码 | 联赛 | 级别 |
|---|---|---|
fr.1 | 法国足球甲级联赛 | 第 1 级 |
fr.2 | 法国足球乙级联赛 | 第 2 级 |
注意: 并非所有赛季都提供所有联赛。
football.json仓库会持续更新——请查看仓库以获取完整的可用文件列表。
可用赛季
football.json 仓库中的赛季目录最早可追溯到 2010-11。欧洲联赛采用跨年格式(2024-25),而部分自然年联赛采用单年格式(2025)。
| 格式 | 用途 | 示例 |
|---|---|---|
YYYY-YY | 欧洲俱乐部赛季(8 月至 5 月) | 2024-25、2023-24、2015-16 |
YYYY | 自然年赛事 | 2025、2020、2019 |
已知赛季目录:2010-11、2011-12、2012-13、2013-14、2014-15、2015-16、2016-17、2017-18、2018-19、2019-20、2020-21、2021-22、2022-23、2023-24、2024-25、2025-26、2019、2020、2025。
JSON 响应格式
所有文件都遵循相同的 JSON 架构:
{
"name": "English Premier League 2024/25",
"matches": [
{
"round": "Matchday 1",
"date": "2024-08-16",
"time": "20:00",
"team1": "Manchester United FC",
"team2": "Fulham FC",
"score": {
"ht": [0, 0],
"ft": [1, 0]
}
}
]
}
顶层字段
| 字段 | 类型 | 描述 |
|---|---|---|
name | string | 易读的联赛名称和赛季 |
matches | array | 比赛对象数组 |
比赛对象字段
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
round | string | 是 | 轮次/比赛日名称(例如 "Matchday 1"、"Round of 16") |
date | string | 是 | YYYY-MM-DD 格式的比赛日期 |
time | string | 否 | HH:MM 格式的开球时间(24 小时制,当地时间) |
team1 | string | 是 | 主队名称 |
team2 | string | 是 | 客队名称 |
score | object | 否 | 比分对象(尚未进行的未来比赛中不存在) |
status | string | 否 | 特殊状态(例如,"awarded" 表示由行政决定的赛果) |
比分对象字段
| 字段 | 类型 | 描述 |
|---|---|---|
ft | [int, int] | 全场比分 [主队, 客队] |
ht | [int, int] | 半场比分 [主队, 客队](部分比赛可能缺少此字段) |
注意: 部分比赛只有
ft(全场比分),没有ht(半场比分)。访问ht前,请务必检查该字段是否存在。
常见模式
获取联赛赛季(curl)
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" | jq .
获取并解析比赛数据(Python)
import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
print(f"League: {data['name']}")
print(f"Total matches: {len(data['matches'])}")
for match in data["matches"][:10]:
ft = match.get("score", {}).get("ft")
if ft:
print(f" {match['date']} {match['team1']} {ft[0]}-{ft[1]} {match['team2']}")
else:
print(f" {match['date']} {match['team1']} vs {match['team2']} (no score)")
根据比赛结果生成联赛积分榜(Python)
import requests
from collections import defaultdict
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
table = defaultdict(lambda: {"played": 0, "won": 0, "drawn": 0, "lost": 0,
"gf": 0, "ga": 0, "points": 0})
for match in data["matches"]:
score = match.get("score", {}).get("ft")
if not score:
continue
t1, t2 = match["team1"], match["team2"]
g1, g2 = score
for team, gf, ga in [(t1, g1, g2), (t2, g2, g1)]:
table[team]["played"] += 1
table[team]["gf"] += gf
table[team]["ga"] += ga
if gf > ga:
table[team]["won"] += 1
table[team]["points"] += 3
elif gf == ga:
table[team]["drawn"] += 1
table[team]["points"] += 1
else:
table[team]["lost"] += 1
# Sort by points, then goal difference
sorted_table = sorted(table.items(),
key=lambda x: (x[1]["points"], x[1]["gf"] - x[1]["ga"]),
reverse=True)
print(f"{'Team':<35} {'P':>3} {'W':>3} {'D':>3} {'L':>3} {'GF':>4} {'GA':>4} {'GD':>4} {'Pts':>4}")
print("-" * 70)
for i, (team, stats) in enumerate(sorted_table, 1):
gd = stats["gf"] - stats["ga"]
print(f"{i:>2}. {team:<32} {stats['played']:>3} {stats['won']:>3} "
f"{stats['drawn']:>3} {stats['lost']:>3} {stats['gf']:>4} "
f"{stats['ga']:>4} {gd:>+4} {stats['points']:>4}")
按球队筛选比赛(Python)
import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
team = "Arsenal FC"
matches = [m for m in data["matches"]
if team in (m["team1"], m["team2"]) and m.get("score", {}).get("ft")]
for m in matches:
ft = m["score"]["ft"]
opponent = m["team2"] if m["team1"] == team else m["team1"]
venue = "H" if m["team1"] == team else "A"
my_goals = ft[0] if m["team1"] == team else ft[1]
opp_goals = ft[1] if m["team1"] == team else ft[0]
result = "W" if my_goals > opp_goals else ("D" if my_goals == opp_goals else "L")
print(f" {m['date']} ({venue}) {result} {my_goals}-{opp_goals} vs {opponent}")
获取多个联赛的数据(Python)
import requests
leagues = {
"Premier League": "en.1",
"Bundesliga": "de.1",
"La Liga": "es.1",
"Serie A": "it.1",
"Ligue 1": "fr.1",
}
season = "2024-25"
base = "https://raw.githubusercontent.com/openfootball/football.json/master"
for name, code in leagues.items():
url = f"{base}/{season}/{code}.json"
resp = requests.get(url)
if resp.status_code == 200:
data = resp.json()
total = len(data["matches"])
played = sum(1 for m in data["matches"] if m.get("score", {}).get("ft"))
print(f"{name}: {played}/{total} matches played")
else:
print(f"{name}: not available for {season}")
获取并解析(Node.js)
const url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json";
const res = await fetch(url);
const data = await res.json();
console.log(`League: ${data.name}`);
console.log(`Matches: ${data.matches.length}`);
data.matches.slice(0, 10).forEach((m) => {
const ft = m.score?.ft;
if (ft) {
console.log(` ${m.date} ${m.team1} ${ft[0]}-${ft[1]} ${m.team2}`);
}
});
获取并解析(bash + jq)
# Get all results for a specific team
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" \
| jq -r '.matches[]
| select(.team1 == "Liverpool FC" or .team2 == "Liverpool FC")
| select(.score.ft)
| "\(.date) \(.team1) \(.score.ft[0])-\(.score.ft[1]) \(.team2)"'
比较交锋结果(Python)
import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
team_a = "Arsenal FC"
team_b = "Liverpool FC"
h2h = [m for m in data["matches"]
if {m["team1"], m["team2"]} == {team_a, team_b}
and m.get("score", {}).get("ft")]
for m in h2h:
ft = m["score"]["ft"]
ht = m["score"].get("ht", ["?", "?"])
print(f"{m['date']}: {m['team1']} {ft[0]}-{ft[1]} {m['team2']} (HT: {ht[0]}-{ht[1]})")
汇总多个赛季的统计数据(Python)
import requests
base = "https://raw.githubusercontent.com/openfootball/football.json/master"
seasons = ["2022-23", "2023-24", "2024-25"]
team = "Manchester City FC"
all_results = {"W": 0, "D": 0, "L": 0, "GF": 0, "GA": 0}
for season in seasons:
resp = requests.get(f"{base}/{season}/en.1.json")
if resp.status_code != 200:
continue
data = resp.json()
for m in data["matches"]:
ft = m.get("score", {}).get("ft")
if not ft:
continue
if m["team1"] == team:
gf, ga = ft
elif m["team2"] == team:
ga, gf = ft
else:
continue
all_results["GF"] += gf
all_results["GA"] += ga
if gf > ga:
all_results["W"] += 1
elif gf == ga:
all_results["D"] += 1
else:
all_results["L"] += 1
print(f"{team} across {', '.join(seasons)}:")
print(f" W{all_results['W']} D{all_results['D']} L{all_results['L']}")
print(f" Goals: {all_results['GF']} scored, {all_results['GA']} conceded")
查找高比分比赛(bash + jq)
# Find all matches with 5+ total goals in the Premier League 2024/25
curl -s "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json" \
| jq -r '.matches[]
| select(.score.ft)
| select((.score.ft[0] + .score.ft[1]) >= 5)
| "\(.date) \(.team1) \(.score.ft[0])-\(.score.ft[1]) \(.team2) (Total: \(.score.ft[0] + .score.ft[1]))"'
获取特定比赛日的结果(Python)
import requests
url = "https://raw.githubusercontent.com/openfootball/football.json/master/2024-25/en.1.json"
data = requests.get(url).json()
matchday = "Matchday 38"
matches = [m for m in data["matches"] if m["round"] == matchday]
print(f"--- {matchday} ---")
for m in matches:
ft = m.get("score", {}).get("ft")
if ft:
print(f" {m['date']} {m.get('time', '')} {m['team1']} {ft[0]}-{ft[1]} {m['team2']}")
else:
print(f" {m['date']} {m.get('time', '')} {m['team1']} vs {m['team2']}")
其他仓库(源数据)
football.json 文件由各国家/地区仓库中的纯文本 Football.TXT 源文件自动生成:
| 仓库 | 内容 | GitHub URL |
|---|---|---|
england | EPL、英冠、英甲、英乙 | openfootball/england |
deutschland | 德甲、德乙、德丙、德国杯 | openfootball/deutschland |
espana | 西甲、西乙 | openfootball/espana |
italy | 意甲、意乙、意大利杯 | openfootball/italy |
france | 法甲、法乙 | openfootball/europe(位于 /europe) |
worldcup | FIFA 世界杯(2022、2018、2014 等) | openfootball/worldcup |
euro | Euro 2024、2020、2016 等 | openfootball/euro |
champions-league | UCL 和 Europa League | openfootball/champions-league |
clubs | 俱乐部和体育场元数据 | openfootball/clubs |
world | 北美、亚洲、非洲、澳大利亚的联赛 | openfootball/world |
各国家/地区仓库也提供自己的 GitHub Pages JSON 镜像。例如:
https://openfootball.github.io/england/2024-25/1-premierleague.json
你可以使用 fbtxt2json CLI 工具自行将 Football.TXT 源文件转换为 JSON:
# Convert a single league file
fbtxt2json england/2025-26/1-premierleague.txt -o en.1.json
# Convert an entire country repo at once
fbtxt2json . -o ./_site
速率限制
GitHub 未公布原始内容的具体速率限制,但一般建议如下:
| 指南 | 建议 |
|---|---|
| 轮询间隔 | 对同一文件的请求间隔 ≥ 60 秒 |
| 并发请求 | 保持在合理范围内(< 20 个并发请求) |
| 缓存 | 在本地缓存响应 — 数据很少变化 |
| 未经身份验证的 GitHub API | 每个 IP 每小时 60 次请求(仅适用于 API 端点,不适用于原始内容) |
提示: 比赛结束后,比赛数据不会再变化,因此可以积极缓存历史赛季的数据。只需轮询当前赛季以获取更新。
错误处理
| HTTP 状态 | 含义 | 操作 |
|---|---|---|
| 200 | 成功 | 解析 JSON |
| 404 | 未找到文件 | 检查赛季、联赛代码或 URL 拼写 |
| 429 | 超出速率限制 | 等待一段时间后重试 |
| 5xx | 服务端错误 | 使用指数退避策略重试 |
提示
- 无需身份验证 — 所有数据均完全公开,可立即开始获取。
- 访问前先检查
score— 未来或尚未进行的比赛不会包含score字段。 - 单独检查
ht— 部分比赛有ft数据,但没有ht数据。 - 球队名称包含后缀 — 例如,
"Arsenal FC"、"Manchester United FC"、"Borussia Dortmund"。请使用完全匹配。 - 球队名称因联赛而异 — 德国球队使用德语名称(
"FC Bayern München"),英格兰球队使用英语名称("Arsenal FC")。 status字段很少出现 — 它会出现在经行政裁定的比赛中(例如"awarded")。- 尽可能积极地缓存 — 已结束的赛季不会变化,只有当前赛季会更新。
- 根据数据构建表格 — 数据集提供原始比赛结果;积分榜、状态、交锋记录等需要自行计算。
- 交叉参照联赛 — 获取多个联赛文件,以便比较不同国家的数据。
- 公有领域(CC0) — 可不受任何限制地随意使用这些数据。
- 不要直接编辑 JSON — 如果要贡献内容,请编辑各国家仓库中的 Football.TXT 源文件;JSON 会自动生成。
- 时间字段为当地时间 —
time值表示比赛场馆所在地的当地开球时间。 - 比分格式为
[home, away]—score.ft[0]始终是team1(主队)的进球数,score.ft[1]始终是team2(客队)的进球数。
更新日志
- 0.1.0 — 首次发布,提供联赛数据访问、JSON 架构文档和常见用法示例。