Puppeteer爬虫故障:赛事分配错误且比赛记录重复求助
问题排查与代码优化建议
问题根源分析
- 比赛重复&分类错误:遍历赛事元素时,你通过
page.$$(".Ip")获取全站所有比赛元素,而非当前赛事节点下的子比赛。这导致每个赛事类别都会把所有比赛重复添加一次,既造成数据重复,又让非当前赛事的比赛被错误归类。 - 选择器错误:
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
相关产品推荐
相关产品推荐

