首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >学会“读网页”:生成式 AI 在足球赛事信息整理中的实战

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

原创
作者头像
jackcode
发布2025-09-15 11:22:42
发布2025-09-15 11:22:42
12300
代码可运行
举报
文章被收录于专栏:爬虫资料爬虫资料
运行总次数:0
代码可运行

背景(为什么要这样做)

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

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

环境准备(快速清单)

  • Python 3.9+
  • 安装必要依赖:
代码语言:bash
复制
pip install requests beautifulsoup4 playwright
playwright install

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

  • 代理(示例:爬虫代理)—— 生产环境请用你自己的凭证并通过环境变量或密钥管理存储:
代码语言:python
代码运行次数:0
运行
复制
域名:`proxy.16yun.cn`(示例)
端口:`3100`
用户名:`16YUN`、密码:`16IP`(示例,请替换)
代码语言:python
代码运行次数:0
运行
复制
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 或公司内部服务;把代理凭证替换为生产凭证。

代码语言:python
代码运行次数:0
运行
复制
# 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 约束(要求基于给定文本输出),并对关键字段做规则校验;对低置信度结果人工复核。
  • 被目标站点限制访问:降低请求速率、使用合规的代理池、并遵守站点授权与版权政策。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景(为什么要这样做)
  • 环境准备(快速清单)
  • 高层流程(核心步骤)
  • 关键设计要点(实践建议)
  • 示例代码(精炼版,易读为主)
  • 常见问题与排查建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档