mcpField
O
openfootball

openfootball

github.com/outsharp数据与数据库4131 次安装32 周前更新
代码仓库

关于 openfootball

openfootball 提供免费的公共领域足球比赛数据,以预生成的 JSON 文件发布,覆盖多个国家的联赛和赛事。开发者可按赛季和联赛代码获取数据,无需 API 密钥或身份验证。

主要功能

  1. 01提供多联赛及赛事的比赛数据
  2. 02通过赛季和联赛代码获取 JSON
  3. 03包含赛程、球队与比分字段
  4. 04支持 GitHub 原始链接及 Pages 镜像
  5. 05数据为公共领域且无需认证

适用场景

  1. 01获取某联赛某赛季的比赛与结果
  2. 02筛选特定球队或比赛轮次
  3. 03基于比分数据计算联赛积分榜
  4. 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]
      }
    }
  ]
}
顶层字段
字段类型描述
namestring易读的联赛名称和赛季
matchesarray比赛对象数组
比赛对象字段
字段类型必填描述
roundstring是轮次/比赛日名称(例如 "Matchday 1"、"Round of 16")
datestring是YYYY-MM-DD 格式的比赛日期
timestring否HH:MM 格式的开球时间(24 小时制,当地时间)
team1string是主队名称
team2string是客队名称
scoreobject否比分对象(尚未进行的未来比赛中不存在)
statusstring否特殊状态(例如,"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
englandEPL、英冠、英甲、英乙openfootball/england
deutschland德甲、德乙、德丙、德国杯openfootball/deutschland
espana西甲、西乙openfootball/espana
italy意甲、意乙、意大利杯openfootball/italy
france法甲、法乙openfootball/europe(位于 /europe)
worldcupFIFA 世界杯(2022、2018、2014 等)openfootball/worldcup
euroEuro 2024、2020、2016 等openfootball/euro
champions-leagueUCL 和 Europa Leagueopenfootball/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 架构文档和常见用法示例。

评论

支持 Markdown