使用Puppeteer爬取页面遇Node不可点击/非元素错误求助
问题描述
使用Puppeteer编写网页爬取代码时,遇到错误:Node is either not clickable or is not an element。尝试过page.goto和page.click两种方式,也更换了querySelector()、querySelectorAll()的选择器路径,但问题仍未解决。
出错代码如下:
const puppeteer = require(`puppeteer`); (async () => { const browser = await puppeteer.launch({headless:false}) const page = await browser.newPage() await page.goto('https://www.agsvyazi.ru/beeline/numbers/index.page.0.htm',{waitUntil: 'load'}) let pages = 131; let idx = 0; const allPhns = []; while(pages > idx){ await new Promise(resolve => setTimeout(resolve, 3000)); let arr = await page.evaluate(() => { let elem = Array.from(document.querySelectorAll("div.fl.number-table"), el => el.innerText) return elem }) allPhns.push(...arr) await page.goto(document.querySelector('div.listing a:last-child').href, {waitUntil: 'load'}) idx +=1 } console.log(allPhns) })()
问题分析与修复
核心错误原因
代码中await page.goto(document.querySelector('div.listing a:last-child').href)存在致命问题:document是浏览器页面上下文的专属对象,无法直接在Node.js主进程(Puppeteer运行环境)中调用,直接访问会导致找不到目标元素,触发报错。
修复步骤
- 分离上下文获取链接:通过
page.evaluate()在浏览器上下文内获取下一页的href,再将结果带回Node.js主进程调用page.goto()。 - 替换固定延迟为元素等待:用
page.waitForSelector()替代setTimeout,确保分页元素完全渲染后再操作,避免因网络或渲染延迟导致元素找不到。 - 添加边界判断:处理最后一页无下一页链接的情况,防止循环报错。
修正后的代码
const puppeteer = require(`puppeteer`); (async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('https://www.agsvyazi.ru/beeline/numbers/index.page.0.htm', { waitUntil: 'domcontentloaded' }); let pages = 131; let idx = 0; const allPhns = []; while (pages > idx) { // 等待号码表格加载完成,确保能正常提取数据 await page.waitForSelector('div.fl.number-table'); // 提取当前页面的号码数据 const arr = await page.evaluate(() => { return Array.from(document.querySelectorAll("div.fl.number-table"), el => el.innerText.trim()); }); allPhns.push(...arr); // 最后一页无需跳转,直接退出循环 if (idx === pages - 1) break; // 等待分页链接加载,获取下一页地址 await page.waitForSelector('div.listing a:last-child'); const nextPageUrl = await page.evaluate(() => { const nextLink = document.querySelector('div.listing a:last-child'); return nextLink ? nextLink.href : null; }); // 无下一页链接时退出循环 if (!nextPageUrl) break; await page.goto(nextPageUrl, { waitUntil: 'domcontentloaded' }); idx += 1; } console.log(allPhns); await browser.close(); // 爬取完成后关闭浏览器进程 })();
额外优化说明
- 将
waitUntil: 'load'替换为domcontentloaded,跳过非必要资源加载,提升爬取效率。 - 使用
page.waitForSelector()确保元素渲染完成,比固定延迟更适配不同网络环境。 - 添加
browser.close()避免浏览器进程残留占用资源。
内容的提问来源于stack exchange,提问作者N9ter
相关产品推荐
相关产品推荐

