学会“读网页”:生成式 AI 在足球赛事信息整理中的实战

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时计算 Flink 版,1000CU*H 3个月
简介: 本文介绍了一个足球比赛信息提取教程,利用生成式AI从ESPN、虎扑、腾讯体育等网站抓取比赛报道,抽取比分、关键事件和球员表现等信息。步骤包括采集、清洗、分块、调用LLM抽取、校验与落地,以及可视化。需要准备Python环境、安装依赖库,并遵循合规性。提供了示例代码,演示如何从网页抓取文本并调用LLM接口获得结构化输出。

背景(为什么要这样做)

对于足球迷、资讯编辑与数据分析师来说,最快、最准确把握一场比赛的核心信息至关重要:比分、关键事件(进球、点球、红黄牌、换人、判罚争议等)、以及球员表现。传统基于规则的爬虫在面对不同媒体页面与频繁改版时常显笨拙:XPath/正则需要频繁维护,动态加载内容常常漏抓。

引入生成式 AI(Large Language Models, LLM)后,我们可以把抓到的比赛报道或直播实录交给模型,让它“读懂”文章并输出结构化结果(JSON),同时生成简明的自然语言摘要,极大提高抽取的鲁棒性与可读性。本教程以实战角度,演示如何抓取 ESPN、虎扑、腾讯体育 三类站点关于五大联赛(英超、西甲、德甲、意甲、法甲)的比赛报道,并用 AI 总结比分、关键事件与球员表现。

环境准备(快速清单)

  • Python 3.9+
  • 安装必要依赖:
pip install requests beautifulsoup4 playwright
playwright install

(若使用外部 LLM SDK,再安装对应库;若只做静态抓取可不安装 Playwright)

  • 代理(示例:爬虫代理)—— 生产环境请用你自己的凭证并通过环境变量或密钥管理存储:
    • 域名:proxy.16yun.cn(示例)
    • 端口:3100
    • 用户名:16YUN、密码:16IP(示例,请替换)
  • 目标站点示例:
    • ESPN 足球:https://www.espn.com/soccer/
    • 虎扑足球:https://soccer.hupu.com/
    • 腾讯体育足球频道:https://sports.qq.com/soccer/(站点结构会变,按实际页面定位)

高层流程(核心步骤)

  1. 采集(抓取):通过代理请求或用 Playwright 渲染页面,获得完整 HTML/文本。
  2. 清洗(预处理):去除脚本、广告、无关导航文本,合并段落,获得可读文本片段。
  3. 分块:将长文本按模型上下文限制切分(保留比赛关键段落完整性)。
  4. 调用 LLM 抽取:把文本与明确的 prompt 一起发给 LLM,要求返回结构化 JSON(例如:比赛基本信息、事件列表、球员表现)。
  5. 校验与落地:对 LLM 返回做 schema 校验(例如:比分格式、时间合法性),保存到数据库或 JSON 文件;对低置信结果标注回流以便人工复核并改进 prompt。
  6. 可视化/下游:生成比分时间线、关键事件标签云、球员评分面板等。

关键设计要点(实践建议)

  • 多来源聚合:同一场比赛建议抓取赛后报道、赛事直播页面与赛后评论三类页面,合并信息能提高完整性与准确度。
  • Prompt 设计:在 prompt 中提供明确返回 schema(要求只输出 JSON 且字段名固定),并给出示例。
  • 后验校验:用正则或简单规则验证日期/分钟格式、进球数是否一致,防止 hallucination。
  • 费用与性能策略:先用轻量模型做命中过滤(是否为目标联赛/是否为比赛报道),再将真正需要深度解析的文本送入大型模型,节省调用成本。
  • 合规性:遵循目标站点的 robots.txt 与版权/转载规则;对含个人信息的内容注意合规与隐私。

示例代码(精炼版,易读为主)

下面给出一个精简、可运行的示例骨架,演示从网页抓文本并调用伪 LLM 接口获得结构化输出。请把伪接口替换成你实际使用的 LLM SDK 或公司内部服务;把代理凭证替换为生产凭证。

# file: football_ai_pipeline.py
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import json, time, os

# ---设置代理(亿牛云示例) ---
PROXY_HOST = os.getenv("PROXY_HOST", "proxy.16yun.cn")
PROXY_PORT = os.getenv("PROXY_PORT", "3100")
PROXY_USER = os.getenv("PROXY_USER", "16YUN")
PROXY_PASS = os.getenv("PROXY_PASS", "16IP")
proxy_url = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
proxies = {
   "http": proxy_url, "https": proxy_url}

HEADERS = {
   
    "User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                   "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120 Safari/537.36")
}

def fetch_html(url, use_proxy=True, timeout=15):
    kwargs = {
   "headers": HEADERS, "timeout": timeout}
    if use_proxy:
        kwargs["proxies"] = proxies
    resp = requests.get(url, **kwargs)
    resp.raise_for_status()
    return resp.text

def extract_text(html):
    soup = BeautifulSoup(html, "lxml")
    for tag in soup(["script", "style", "noscript", "header", "footer", "aside"]):
        tag.decompose()
    texts = [s.strip() for s in soup.stripped_strings]
    return "\n".join(texts)

def call_llm_for_match(text_snippet):
    """
    将文本片段送给 LLM 并返回结构化字典。
    在此用示例返回占位数据;生产环境替换为真实 API 调用并处理返回结果。
    """
    # 示例返回结构(实际按你的 schema 定制)
    return {
   
        "league": "英超",
        "home_team": "曼联",
        "away_team": "利物浦",
        "score": "2-1",
        "events": [
            {
   "minute": 14, "type": "goal", "team": "曼联", "player": "拉什福德"},
            {
   "minute": 46, "type": "goal", "team": "利物浦", "player": "萨拉赫"},
            {
   "minute": 78, "type": "goal", "team": "曼联", "player": "B费"}
        ],
        "player_summary": "拉什福德状态出色,门将几次关键扑救,替补球员改变了战局。"
    }

def process_match_url(url):
    html = fetch_html(url)
    text = extract_text(html)
    # 若文本过长,可切分并合并 LLM 输出
    snippet = text[:5000]  # 示例截断,按模型上下文调整
    result = call_llm_for_match(snippet)
    # 后验简单校验(示例)
    if "score" in result:
        pass  # 在此做正则或数值校验
    return result

if __name__ == "__main__":
    urls = [
        "https://www.espn.com/soccer/report?gameId=xxxx",  # 替换为实际赛报链接
        "https://soccer.hupu.com/games/xxxx",
        "https://sports.qq.com/a/xxxx.htm"
    ]
    results = []
    for u in urls:
        try:
            r = process_match_url(u)
            results.append(r)
        except Exception as e:
            print("抓取/解析失败:", u, e)
        time.sleep(1.5)
    with open("matches_aggregated.json", "w", encoding="utf-8") as f:
        json.dump(results, f, ensure_ascii=False, indent=2)

常见问题与排查建议

  • 页面是空白或只剩壳:多数是前端渲染,改用 Playwright/Selenium 或分析 XHR 请求直接调用后端接口。
  • 抓到的“报道”是简短新闻稿,细节不足:同时抓取直播实录(live blog)或赛后深度评述页,合并信息。
  • LLM 输出里出现“虚构”事件:增加 prompt 约束(要求基于给定文本输出),并对关键字段做规则校验;对低置信度结果人工复核。
  • 被目标站点限制访问:降低请求速率、使用合规的代理池、并遵守站点授权与版权政策。
相关文章
|
7天前
|
人工智能 运维 安全
|
4天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
569 20
|
12天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
927 109
|
5天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。