You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer爬虫故障:赛事分配错误且比赛记录重复求助

问题排查与代码优化建议

问题根源分析

  1. 比赛重复&分类错误:遍历赛事元素时,你通过page.$$(".Ip")获取全站所有比赛元素,而非当前赛事节点下的子比赛。这导致每个赛事类别都会把所有比赛重复添加一次,既造成数据重复,又让非当前赛事的比赛被错误归类。
  2. 选择器错误:matchTime = await matchElements[j].$(".qs", ".vs")写法无效,$方法仅接受单个选择器,多个选择器需合并为.qs, .vs或用其他方式处理。

优化后的代码

const puppeteer = require("puppeteer");

async function openPage() {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();

  await page.setViewport({ width: 1000, height: 926 });
  // 等待网络空闲,确保页面资源加载完成
  await page.goto("https://www.livescore.com/en/", { waitUntil: "networkidle2" });

  return page;
}

async function scrapeData(page) {
  let content = [];

  await page.waitForSelector(".Gd");
  const compElements = await page.$$(".Gd");

  for (let i = 0; i < compElements.length; i++) {
    const compName = await compElements[i].$(".Hd");
    if (!compName) continue;

    const currentComp = await compName.evaluate(node => node.textContent.trim());
    console.log(`爬取赛事:${currentComp}`);

    // 关键修改:从当前赛事节点下获取对应比赛,而非全局
    const matchElements = await compElements[i].$$(".Ip");

    for (let j = 0; j < matchElements.length; j++) {
      const matchElement = matchElements[j];
      // 封装文本获取函数,处理元素不存在的情况
      const getText = async (selector) => {
        try {
          return await matchElement.$eval(selector, node => node.textContent.trim());
        } catch (e) {
          return null;
        }
      };

      const homeTeam = await getText(".vp");
      const awayTeam = await getText(".wp");
      const homeScore = await getText(".Cp");
      const awayScore = await getText(".Dp");
      // 修复多选择器写法
      const matchTime = await getText(".qs, .vs");

      if (homeTeam && awayTeam && homeScore && awayScore) {
        content.push({
          matchTime,
          homeTeam,
          awayTeam,
          homeScore,
          awayScore,
          competition: currentComp,
        });
      }
    }
  }

  // 可选:基于比赛唯一标识去重
  const uniqueContent = [...new Map(content.map(item => 
    [`${item.homeTeam}-${item.awayTeam}-${item.matchTime}`, item]
  )).values()];

  return uniqueContent;
};

(async () => {
  const page = await openPage();
  const dataScraped = await scrapeData(page);
  console.log(dataScraped);
  await page.browser().close();
})();

核心优化点说明

  • 赛事与比赛关联:通过compElements[i].$$(".Ip")从当前赛事节点下获取比赛,确保每个比赛只归属对应的赛事,彻底解决分类错误和重复问题。
  • 选择器修复:合并比赛时间的多选择器,封装文本获取函数避免元素不存在导致的报错。
  • 加载稳定性提升:goto时添加networkidle2等待策略,确保页面完全加载后再爬取。
  • 可选去重:用Map基于主队+客队+比赛时间的组合去重,处理页面本身可能存在的重复条目。

内容的提问来源于stack exchange,提问作者anon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 19:42:01