如何使用Puppeteer获取div子元素 解决img选择器匹配报错问题
问题原因
你遇到的报错除了元素未完成加载的原因外,还有两处代码写法的问题:
- 直接链式调用
ElementHandle.$()后执行$eval(),如果前一步$()未匹配到元素,后续调用会直接抛出异常 - 拼写错误:获取文本的属性写为
texContent,正确应为textContent
修复方案
1. 调整页面加载等待策略
修改page.goto的配置,等待页面网络空闲后再执行后续逻辑,避免动态渲染的元素还未插入DOM:
await page.goto(url, { waitUntil: 'networkidle2', // 网络连接数少于2个时认为加载完成,适合动态内容页面 timeout: 30000 })
2. 增加元素等待逻辑
在获取目标元素前先等待对应的选择器匹配到元素,同时做异常捕获避免单个元素获取失败中断整个流程。你可以在ElementHandle的上下文中调用waitForSelector,仅在当前父元素范围内等待子元素渲染,避免全局匹配的问题。
3. 完整修改后的代码
const puppeteer = require('puppeteer'); const url = 'https://example.com/'; //browser initialization async function initBrowser() { const browser = await puppeteer.launch({ headless: false, }); return browser; } async function getPage(browser) { const page = await browser.newPage(); // 调整goto的等待策略 await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 }); // 先等待父元素渲染完成再获取列表 await page.waitForSelector('div.class', { timeout: 10000 }); return page; } async function getNewMessage(page) { const els = await page.$$('div.class'); for (let i = 0; i < els.length; i++) { try { // 在当前父div范围内等待img元素渲染完成 await els[i].waitForSelector('div.class2 img', { timeout: 5000 }); const imgSrc = await els[i].$eval('div.class2 img', (el) => el.src); console.log(imgSrc); // 修正拼写错误:texContent -> textContent const link = await els[i].$eval('div.class3', (elem) => elem.textContent.trim()); console.log(link); } catch (err) { // 单个元素获取失败时打印日志不中断循环 console.log(`第${i+1}个div元素获取失败:`, err.message); } } } async function loading() { const browser = await initBrowser(); const page = await getPage(browser); await getNewMessage(page); // 运行完成后关闭浏览器 await browser.close(); } loading();
如果你的页面是滚动加载更多的动态场景,还可以在获取元素前增加对应的滚动逻辑,触发元素渲染后再执行获取操作。
内容的提问来源于stack exchange,提问作者Croicco
相关产品推荐
相关产品推荐

