如何使用Puppeteer获取指定类名元素数组并遍历子元素提取数据
解决方法
你用page.$$获取到的是ElementHandle数组,本身支持查询子元素,问题出在后续的调用方式,以下是可直接运行的完整实现方案:
核心逻辑说明
ElementHandle实例自身携带$和$$方法,调用这两个方法即可从当前元素的子节点中匹配选择器,而非从整个文档根节点匹配。所有DOM属性的读取都需要通过page.evaluate执行,不可直接在Node侧读取代理对象的属性。
完整代码示例
const puppeteer = require('puppeteer'); (async () => { // 启动浏览器 const browser = await puppeteer.launch({ headless: 'new' }); const page = await browser.newPage(); // 跳转目标页面,等待网络空闲 await page.goto('https://altadefinizione.sale/?s=matrix', { waitUntil: 'networkidle2' }); // 你原本获取卡片数组的代码是正确的 const cardHandles = await page.$$('.col-lg-3.col-md-4.col-xs-4.mb-30'); const extractResult = []; // 遍历每个卡片提取信息 for (const card of cardHandles) { // 从当前卡片下查询子元素 const coverImgHandle = await card.$('img'); const titleHandle = await card.$('a h3'); const detailLinkHandle = await card.$('a'); // 提取对应属性,加空判避免部分卡片结构异常报错 const coverImgUrl = coverImgHandle ? await page.evaluate(el => el.src, coverImgHandle) : null; const titleText = titleHandle ? await page.evaluate(el => el.textContent.trim(), titleHandle) : null; const detailPageUrl = detailLinkHandle ? await page.evaluate(el => el.href, detailLinkHandle) : null; extractResult.push({ title: titleText, cover: coverImgUrl, detailUrl: detailPageUrl }); // 手动销毁handle释放内存,非必需但推荐 await coverImgHandle?.dispose(); await titleHandle?.dispose(); await detailLinkHandle?.dispose(); } // 输出最终提取结果 console.log(extractResult); // 关闭浏览器 await browser.close(); })();
常见踩坑提醒
- 不要混淆
page.$和elementHandle.$:前者是从整个页面匹配元素,后者是从当前元素的子节点匹配 - 所有DOM属性、文本的读取必须放到
page.evaluate的回调中执行,ElementHandle只是Node侧的代理对象,本身不携带任何DOM属性 - 遇到结构不固定的场景一定要加空判断,避免单条数据异常导致整个爬取流程中断
内容的提问来源于stack exchange,提问作者nikxtr
相关产品推荐
相关产品推荐

