世界杯小组赛阶段,最适合做技术文章的方向,不是单纯预测谁赢,而是把赛果变成结构化数据。

比如 Group C 目前有四支球队:

  • 巴西
  • 摩洛哥
  • 海地
  • 苏格兰

首轮赛果已经出现:

  • 巴西 1-1 摩洛哥
  • 苏格兰 1-0 海地

接下来还有:

  • 巴西 vs 海地
  • 苏格兰 vs 摩洛哥

如果只是写球评,很容易变成主观判断。
但如果用 Python 处理,就可以自动生成:

  • 小组积分榜
  • 净胜球
  • 进球数
  • 球队排名
  • 下一场比赛压力
  • Markdown 分析报告

这篇文章就用 Python 写一个简单脚本。

注意:本文只做数据整理和内容辅助分析,不涉及博彩、赔率、下注,也不保证任何比赛结果。


一、需求拆解

我们要实现 4 个功能:

  1. 录入小组球队
  2. 录入已结束比赛结果
  3. 自动计算积分榜
  4. 根据下一场对阵生成赛前压力分析

积分规则按常见足球小组赛规则:

  • 胜:3 分
  • 平:1 分
  • 负:0 分

排序规则先简化为:

  1. 积分
  2. 净胜球
  3. 进球数

实际世界杯还会涉及更多细则,比如相互战绩、公平竞赛积分等。本文为了演示代码逻辑,先实现最常用的前三项。


二、定义数据结构

先创建一个文件:

worldcup_group_analyzer.py

写入基础数据结构:

from dataclasses import dataclass
from typing import Dict, List, Optional


@dataclass
class MatchResult:
    home: str
    away: str
    home_goals: Optional[int]
    away_goals: Optional[int]


@dataclass
class TeamStanding:
    team: str
    played: int = 0
    wins: int = 0
    draws: int = 0
    losses: int = 0
    goals_for: int = 0
    goals_against: int = 0
    points: int = 0

    @property
    def goal_diff(self) -> int:
        return self.goals_for - self.goals_against

这里有两个核心类:

  • MatchResult:保存比赛结果
  • TeamStanding:保存球队积分数据

home_goalsaway_goalsOptional[int],是为了兼容未开赛比赛。未开赛时可以设置为 None


三、更新积分榜

接下来写一个函数,根据赛果更新两支球队的积分。

def apply_match_result(
    standings: Dict[str, TeamStanding],
    match: MatchResult
) -> None:
    if match.home_goals is None or match.away_goals is None:
        return

    home_team = standings[match.home]
    away_team = standings[match.away]

    home_team.played += 1
    away_team.played += 1

    home_team.goals_for += match.home_goals
    home_team.goals_against += match.away_goals

    away_team.goals_for += match.away_goals
    away_team.goals_against += match.home_goals

    if match.home_goals > match.away_goals:
        home_team.wins += 1
        away_team.losses += 1
        home_team.points += 3
    elif match.home_goals < match.away_goals:
        away_team.wins += 1
        home_team.losses += 1
        away_team.points += 3
    else:
        home_team.draws += 1
        away_team.draws += 1
        home_team.points += 1
        away_team.points += 1

这段逻辑很直观:

  • 如果比赛还没开赛,不处理
  • 如果主队进球更多,主队加 3 分
  • 如果客队进球更多,客队加 3 分
  • 如果平局,双方各加 1 分

四、生成积分榜

接下来根据全部赛果生成积分榜。

def build_standings(
    teams: List[str],
    matches: List[MatchResult]
) -> List[TeamStanding]:
    standings = {
        team: TeamStanding(team=team)
        for team in teams
    }

    for match in matches:
        apply_match_result(standings, match)

    return sorted(
        standings.values(),
        key=lambda item: (item.points, item.goal_diff, item.goals_for),
        reverse=True
    )

排序规则是:

points > goal_diff > goals_for

也就是先看积分,再看净胜球,再看进球数。


五、判断下一场压力

世界杯小组赛第二轮很关键。

如果首轮只拿 1 分,第二轮就需要尽量争胜。
如果首轮输了,第二轮压力会明显变大。
如果首轮赢了,第二轮可能争取提前建立出线优势。

写一个简单压力判断函数:

def get_pressure_label(team: TeamStanding) -> str:
    if team.played == 0:
        return "尚未出场,需要观察首战表现"

    if team.points == 0:
        return "抢分压力高,下一场不能再轻易丢分"

    if team.points == 1:
        return "需要争胜,平局只能勉强维持局面"

    if team.points == 3:
        return "形势较好,赢球有机会掌握出线主动权"

    return "出线形势较稳,但仍需关注净胜球"

这不是严格数学出线模型,而是内容创作里常用的“压力标签”。

它适合生成赛前文章里的判断句。


六、生成 Markdown 报告

为了方便发 CSDN、公众号或头条,可以直接生成 Markdown。

def generate_markdown_report(
    group_name: str,
    standings: List[TeamStanding],
    next_matches: List[MatchResult]
) -> str:
    lines = [
        f"# {group_name} 小组积分榜与赛前压力分析",
        "",
        "## 一、当前积分榜",
        "",
        "| 排名 | 球队 | 场次 | 胜 | 平 | 负 | 进球 | 失球 | 净胜球 | 积分 |",
        "|---|---|---:|---:|---:|---:|---:|---:|---:|---:|",
    ]

    for index, team in enumerate(standings, start=1):
        lines.append(
            f"| {index} | {team.team} | {team.played} | {team.wins} | "
            f"{team.draws} | {team.losses} | {team.goals_for} | "
            f"{team.goals_against} | {team.goal_diff} | {team.points} |"
        )

    lines.extend([
        "",
        "## 二、下一场比赛压力分析",
        "",
    ])

    standings_map = {team.team: team for team in standings}

    for match in next_matches:
        home = standings_map[match.home]
        away = standings_map[match.away]

        lines.append(f"### {match.home} vs {match.away}")
        lines.append("")
        lines.append(f"- {match.home}:{get_pressure_label(home)}")
        lines.append(f"- {match.away}:{get_pressure_label(away)}")
        lines.append("")

        if home.points > away.points:
            lines.append(
                f"{match.home}当前积分更高,比赛目标是扩大优势;"
                f"{match.away}则需要通过抢分改变小组局势。"
            )
        elif home.points < away.points:
            lines.append(
                f"{match.away}当前积分更高,心理压力相对较小;"
                f"{match.home}更需要主动争取结果。"
            )
        else:
            lines.append(
                "双方积分接近,这场比赛更可能直接影响小组排名和后续出线主动权。"
            )

        lines.append("")

    lines.extend([
        "## 三、说明",
        "",
        "本文脚本只用于世界杯小组赛数据整理和赛前内容分析,"
        "不构成任何比分保证,也不涉及博彩、下注或赔率建议。",
    ])

    return "\n".join(lines)

七、完整代码

下面是完整可运行代码。

from dataclasses import dataclass
from typing import Dict, List, Optional


@dataclass
class MatchResult:
    home: str
    away: str
    home_goals: Optional[int]
    away_goals: Optional[int]


@dataclass
class TeamStanding:
    team: str
    played: int = 0
    wins: int = 0
    draws: int = 0
    losses: int = 0
    goals_for: int = 0
    goals_against: int = 0
    points: int = 0

    @property
    def goal_diff(self) -> int:
        return self.goals_for - self.goals_against


def apply_match_result(
    standings: Dict[str, TeamStanding],
    match: MatchResult
) -> None:
    if match.home_goals is None or match.away_goals is None:
        return

    home_team = standings[match.home]
    away_team = standings[match.away]

    home_team.played += 1
    away_team.played += 1

    home_team.goals_for += match.home_goals
    home_team.goals_against += match.away_goals

    away_team.goals_for += match.away_goals
    away_team.goals_against += match.home_goals

    if match.home_goals > match.away_goals:
        home_team.wins += 1
        away_team.losses += 1
        home_team.points += 3
    elif match.home_goals < match.away_goals:
        away_team.wins += 1
        home_team.losses += 1
        away_team.points += 3
    else:
        home_team.draws += 1
        away_team.draws += 1
        home_team.points += 1
        away_team.points += 1


def build_standings(
    teams: List[str],
    matches: List[MatchResult]
) -> List[TeamStanding]:
    standings = {
        team: TeamStanding(team=team)
        for team in teams
    }

    for match in matches:
        apply_match_result(standings, match)

    return sorted(
        standings.values(),
        key=lambda item: (item.points, item.goal_diff, item.goals_for),
        reverse=True
    )


def get_pressure_label(team: TeamStanding) -> str:
    if team.played == 0:
        return "尚未出场,需要观察首战表现"

    if team.points == 0:
        return "抢分压力高,下一场不能再轻易丢分"

    if team.points == 1:
        return "需要争胜,平局只能勉强维持局面"

    if team.points == 3:
        return "形势较好,赢球有机会掌握出线主动权"

    return "出线形势较稳,但仍需关注净胜球"


def generate_markdown_report(
    group_name: str,
    standings: List[TeamStanding],
    next_matches: List[MatchResult]
) -> str:
    lines = [
        f"# {group_name} 小组积分榜与赛前压力分析",
        "",
        "## 一、当前积分榜",
        "",
        "| 排名 | 球队 | 场次 | 胜 | 平 | 负 | 进球 | 失球 | 净胜球 | 积分 |",
        "|---|---|---:|---:|---:|---:|---:|---:|---:|---:|",
    ]

    for index, team in enumerate(standings, start=1):
        lines.append(
            f"| {index} | {team.team} | {team.played} | {team.wins} | "
            f"{team.draws} | {team.losses} | {team.goals_for} | "
            f"{team.goals_against} | {team.goal_diff} | {team.points} |"
        )

    lines.extend([
        "",
        "## 二、下一场比赛压力分析",
        "",
    ])

    standings_map = {team.team: team for team in standings}

    for match in next_matches:
        home = standings_map[match.home]
        away = standings_map[match.away]

        lines.append(f"### {match.home} vs {match.away}")
        lines.append("")
        lines.append(f"- {match.home}:{get_pressure_label(home)}")
        lines.append(f"- {match.away}:{get_pressure_label(away)}")
        lines.append("")

        if home.points > away.points:
            lines.append(
                f"{match.home}当前积分更高,比赛目标是扩大优势;"
                f"{match.away}则需要通过抢分改变小组局势。"
            )
        elif home.points < away.points:
            lines.append(
                f"{match.away}当前积分更高,心理压力相对较小;"
                f"{match.home}更需要主动争取结果。"
            )
        else:
            lines.append(
                "双方积分接近,这场比赛更可能直接影响小组排名和后续出线主动权。"
            )

        lines.append("")

    lines.extend([
        "## 三、说明",
        "",
        "本文脚本只用于世界杯小组赛数据整理和赛前内容分析,"
        "不构成任何比分保证,也不涉及博彩、下注或赔率建议。",
    ])

    return "\n".join(lines)


def main() -> None:
    teams = ["巴西", "摩洛哥", "海地", "苏格兰"]

    played_matches = [
        MatchResult(home="巴西", away="摩洛哥", home_goals=1, away_goals=1),
        MatchResult(home="苏格兰", away="海地", home_goals=1, away_goals=0),
    ]

    next_matches = [
        MatchResult(home="巴西", away="海地", home_goals=None, away_goals=None),
        MatchResult(home="苏格兰", away="摩洛哥", home_goals=None, away_goals=None),
    ]

    standings = build_standings(teams, played_matches)
    report = generate_markdown_report(
        group_name="世界杯 Group C",
        standings=standings,
        next_matches=next_matches
    )

    output_file = "group_c_report.md"

    with open(output_file, "w", encoding="utf-8") as file:
        file.write(report)

    print(report)
    print(f"\n报告已生成:{output_file}")


if __name__ == "__main__":
    main()

八、运行脚本

python worldcup_group_analyzer.py

运行后会生成:

group_c_report.md

终端输出示例:

# 世界杯 Group C 小组积分榜与赛前压力分析

## 一、当前积分榜

| 排名 | 球队 | 场次 | 胜 | 平 | 负 | 进球 | 失球 | 净胜球 | 积分 |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|
| 1 | 苏格兰 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 3 |
| 2 | 摩洛哥 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
| 3 | 巴西 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
| 4 | 海地 | 1 | 0 | 0 | 1 | 0 | 1 | -1 | 0 |

## 二、下一场比赛压力分析

### 巴西 vs 海地

- 巴西:需要争胜,平局只能勉强维持局面
- 海地:抢分压力高,下一场不能再轻易丢分

双方积分接近,这场比赛更可能直接影响小组排名和后续出线主动权。

### 苏格兰 vs 摩洛哥

- 苏格兰:形势较好,赢球有机会掌握出线主动权
- 摩洛哥:需要争胜,平局只能勉强维持局面

苏格兰当前积分更高,比赛目标是扩大优势;摩洛哥则需要通过抢分改变小组局势。

九、这个脚本适合怎么扩展?

1. 支持更多小组

现在代码只写了 Group C。

后续可以把数据拆成 JSON:

{
  "Group C": {
    "teams": ["巴西", "摩洛哥", "海地", "苏格兰"],
    "matches": [
      ["巴西", "摩洛哥", 1, 1],
      ["苏格兰", "海地", 1, 0]
    ]
  }
}

这样每天只维护数据,不用改核心代码。

2. 增加真实比赛指标

除了比分,还可以加入:

  • 射门数
  • 射正数
  • 控球率
  • 角球
  • 黄牌
  • 犯规
  • xG
  • 门将扑救

这样可以从“小组积分榜工具”扩展成“赛后复盘工具”。

3. 自动生成不同平台文案

可以继续加平台参数:

python worldcup_group_analyzer.py --platform csdn
python worldcup_group_analyzer.py --platform zhihu
python worldcup_group_analyzer.py --platform toutiao

CSDN 输出技术解释。
知乎输出观点分析。
今日头条输出大众化看点。
公众号输出完整复盘。

这就是把世界杯热点变成一个可复用内容系统,而不是每天临时拍脑袋。

更多推荐