本文目录导读:

要制作一个显示低平球传中次数的实用脚本,我需要先确认您使用的数据源(如 StatsBomb、Wyscout、Opta 或普通的比赛 CSV 数据),因为“低平球”在不同数据源中的字段定义不同。
我可以先给您一个通用且最常用的 Python 脚本框架(适用于 Wyscout 或 StatsBomb 格式),并提供一个基于现场观感(通过视频时间戳或手动输入)的极简脚本。
由于没有具体数据文件,我假设您使用的是Wyscout 事件数据(这是目前最流行的免费公开数据集格式),其中传球类型用 tags 表示,高度用 104(低平球)标识。
以下是两个实用脚本,您可以根据您手里的数据形态选择:
处理 Wyscout / StatsBomb 事件数据(JSON 格式)
此脚本会统计指定球队(或全部球队)在比赛中低平球传中的具体次数,并打印出每一次的详细位置。
import json
from collections import Counter
# ------------------ 配置区 ------------------
# 请将您的数据文件放在同目录下,并修改文件名
EVENT_FILE = "events.json"
# 球队名称(如果只想统计某队,填 None 则统计所有球队)
TARGET_TEAM = None # "Liverpool" 或 "FC Barcelona"
# 传中事件子类型(Wyscout 中传中是 8,Open Play 是 1)
CROSS_SUBTYPE = 8
# ------------------ 核心代码 ------------------
def load_events(path):
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
def is_low_cross(event):
"""
判断是否为低平球传中:
1. 必须是传中 (subtype 或 eventName 为 Cross)
2. 传球高度 tag 必须为 104 (Low)
"""
# ---- 处理 Wyscout 格式 ----
if 'subEventId' in event:
if event['subEventId'] != CROSS_SUBTYPE:
return False
# 检查 tags 是否包含精准/低平球 (id=104)
tags = [tag['id'] for tag in event.get('tags', [])]
# 104 在 Wyscout 中代表 "Low" (贴地飞行)
return 104 in tags
# ---- 处理 StatsBomb 格式 ----
if event.get('type', {}).get('name') == 'Pass':
if event.get('pass', {}).get('height', {}).get('name') == 'Ground Pass':
pass_type = event.get('pass', {}).get('type', {}).get('name')
if pass_type == 'Cross':
return True
return False
def main():
events = load_events(EVENT_FILE)
# 提取比赛 ID (如果有)
match_ids = set(e.get('matchId', 'Unknown') for e in events)
low_crosses = []
for ev in events:
# 过滤球队
team_name = ev.get('team', {}).get('name', 'Unknown')
if TARGET_TEAM and team_name != TARGET_TEAM:
continue
if is_low_cross(ev):
# 提取关键信息
info = {
'match': ev.get('matchId', 'N/A'),
'team': team_name,
'player': ev.get('player', {}).get('name', 'Unknown'),
'minute': ev.get('minute', 0) + ev.get('second', 0)/60,
'x': ev.get('positions', [{}])[0].get('x', 0) if ev.get('positions') else None,
'y': ev.get('positions', [{}])[0].get('y', 0) if ev.get('positions') else None,
'outcome': 'Successful' if 1801 in [t['id'] for t in ev.get('tags', [])] else 'Unsuccessful'
}
low_crosses.append(info)
# ----- 输出结果 -----
print(f"\n📊 数据统计:共发现 {len(low_crosses)} 次低平球传中\n")
print("-" * 60)
for i, cross in enumerate(low_crosses, 1):
print(f"{i:2d}. 第{cross['minute']:.0f}分钟 | {cross['team']} | "
f"{cross['player']} | 位置({cross['x']}, {cross['y']}) | {cross['outcome']}")
# 按队伍统计
print("\n📈 球队低平球传中次数:")
team_counts = Counter(c['team'] for c in low_crosses)
for team, count in team_counts.most_common():
print(f" {team}: {count} 次")
if __name__ == "__main__":
main()
极简通用版(手动录入比赛事件,适用于任何数据)
如果您没有现成的 JSON 数据文件,或者您是在看视频录像时手动记录,可以用这个交互式脚本,每次按回车记录一次,自动计数:
import sys
def run_tracker():
"""交互式低平球传中计数器(适合边看比赛边按)"""
print("⚽ 低平球传中计数器")
print("按 [Y] 记录一次,按 [C] 查看统计,按 [Ctrl+C] 退出\n")
count = 0
details = []
while True:
try:
cmd = input(">>> ").strip().lower()
if cmd == 'y':
count += 1
minute = input(" 分钟数(如45.3): ")
details.append(f" {len(details)+1:2d}. 第{minute}分钟")
print(f" ✅ 已记录!当前总数: {count}")
elif cmd == 'c':
print(f"\n📊 总计: {count} 次")
for d in details:
print(d)
print()
except KeyboardInterrupt:
print(f"\n\n最终结果:共 {count} 次低平球传中")
break
if __name__ == "__main__":
run_tracker()
如何选择?
| 场景 | 推荐方案 |
|---|---|
| 已有 Wyscout 或 StatsBomb 的 JSON 事件文件 | 方案一 |
| 只有 普通 CSV 表格(列如 Time, Event, Height) | 把方案一稍作修改,将 JSON 解析改为 csv.DictReader(可留言我帮您改) |
| 纯人工观赛,没有数据文件 | 方案二 |
重点提醒(数据字段问题)
- Wyscout:低平球标签
104,传中事件 ID 为8。 - StatsBomb:
height=Ground Pass且pass.type=Cross。 - 如果您手里的数据是 Opta 格式,字段名通常会叫
Pass.Height(值包含Ground)和Pass.Type(值包含Cross),请告诉我具体字段名,我可以立刻调整。
如果有具体的数据文件样例(前几行),您可以直接贴到评论区,我帮您把脚本改到完全匹配、直接可跑!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播