Puppeteer爬取页面时丢失HTML中数字(如21、22)问题求助
问题分析与解决办法
你遇到的核心问题是:页面原始HTML里明明包含球员编号(21、22这类数字),但用Puppeteer爬取时数字直接消失,只剩•字符。大概率是页面加载完成后,内置的JavaScript脚本修改了DOM,把数字文本节点移除了,也可能是网站的反爬机制检测到爬虫后篡改了内容。
验证思路
- 禁用JavaScript验证:先在Puppeteer里禁用JS再爬取,看数字是否能正常显示:
const browser = await puppeteer.launch({ args: ['--no-javascript'] }); // 或者在已打开的页面中设置 await page.setJavaScriptEnabled(false);
如果禁用JS后能拿到数字,就可以确定是页面脚本删除了数字。
- 监控DOM变化:如果禁用JS导致页面布局混乱无法提取内容,用MutationObserver监控编号节点的变化,追踪是谁在修改DOM:
await page.evaluate(() => { const targetNode = document.querySelector('.roster__player__header_jnumber'); const observer = new MutationObserver((mutations) => { mutations.forEach(mutation => { if (mutation.type === 'childList') { console.log('编号节点被修改:', mutation); } }); }); observer.observe(targetNode, { childList: true, subtree: true }); }); // 等待页面加载完成后再查看日志 await page.waitForTimeout(2000);
解决办法
如果确认是脚本删除了数字,有两种可行的应对方式:
- 提前提取内容:赶在页面脚本修改DOM之前完成提取。可以在页面DOM刚加载完成时立刻执行提取逻辑:
await page.goto('你的目标URL', { waitUntil: 'domcontentloaded' }); const data = await page.evaluate(() => { const playerNodes = document.querySelectorAll('.roster__player'); return Array.from(playerNodes).map(playerNode => ({ name: playerNode.querySelector('.roster__player__header__heading')?.textContent?.trim(), position: playerNode.querySelector('.roster__player__header_position')?.textContent?.trim(), // 直接取编号节点下的第一个文本节点,赶在脚本删除它之前拿到 number: playerNode.querySelector('.roster__player__header_jnumber')?.childNodes[0]?.textContent?.trim(), profileImage: playerNode.querySelector('.roster__player__bust')?.getAttribute('src'), url: playerNode.querySelector('a')?.getAttribute('href'), })); });
- 从接口直接获取:如果页面的球员数据是通过API接口加载的,用Puppeteer拦截XHR/fetch请求,直接从接口返回的JSON数据里提取编号,这种方式比解析DOM更可靠。
另外,如果是CSS把数字视觉隐藏但DOM里仍存在的情况,可以通过遍历节点的所有文本子节点来拼接内容:
number: Array.from(playerNode.querySelector('.roster__player__header_jnumber')?.childNodes || []) .filter(node => node.nodeType === Node.TEXT_NODE) .map(node => node.textContent.trim()) .join(''),
内容的提问来源于stack exchange,提问作者Arnaldo Lucien
相关产品推荐
相关产品推荐

