在 Puppeteer 中,page.$$(selector)
是一个用于在页面上选择多个元素的方法,它返回一个由 ElementHandle
组成的数组(Promise<Array<ElementHandle>>
)。与 page.$$eval()
不同,page.$$()
不会自动执行回调函数 ,而是返回可进一步操作的 ElementHandle
对象。
基本语法
javascript
const elements = await page.$$(selector);
-
selector
: CSS 选择器(如'a'
,'.class'
,'#id'
)。 -
返回值 :
Promise<Array<ElementHandle>>
,解析为匹配的所有元素的ElementHandle
数组。
核心用途
-
获取元素列表:选择多个元素后,可以遍历或单独操作。
-
结合其他方法 :对每个元素执行点击、输入、截图等操作(需配合
ElementHandle
的方法)。
常见用法示例
1. 获取所有链接的 ElementHandle
javascript
const links = await page.$$('a'); // 获取所有 <a> 元素
console.log(links.length); // 输出匹配的元素数量
2. 遍历元素并操作
javascript
const buttons = await page.$$('button');
for (const button of buttons) {
await button.click(); // 点击每个按钮
await page.waitForTimeout(500); // 可选:延迟
}
3. 提取元素属性(需结合 evaluate
)
javascript
const elements = await page.$$('img');
const srcList = await Promise.all(
elements.map(img => img.evaluate(el => el.src))
);
console.log(srcList); // 输出所有图片的 src 属性
4. 过滤可见元素
javascript
const allLinks = await page.$$('a');
const visibleLinks = [];
for (const link of allLinks) {
const isVisible = await link.evaluate(el =>
el.offsetWidth > 0 && el.offsetHeight > 0
);
if (isVisible) visibleLinks.push(link);
}
console.log(visibleLinks.length);
与 page.$$eval()
的区别
方法 | 返回值 | 适用场景 |
---|---|---|
page.$$(selector) |
ElementHandle[] (可进一步操作) |
需要逐个操作元素(如点击、截图) |
page.$$eval() |
直接返回回调函数的结果 | 快速提取数据或批量修改属性 |
示例对比:
javascript
// 使用 $$eval 直接提取文本
const texts = await page.$$eval('a', els => els.map(el => el.textContent));
// 使用 $$ 获取 ElementHandle 后提取文本
const links = await page.$$('a');
const texts = await Promise.all(
links.map(link => link.evaluate(el => el.textContent))
);
注意事项
-
元素可能动态加载 :建议先使用
page.waitForSelector
确保元素存在:javascript
await page.waitForSelector('a'); const links = await page.$$('a');
-
ElementHandle
需手动释放 :长时间运行的脚本应调用elementHandle.dispose()
防止内存泄漏。 -
性能优化 :如果只需提取数据,
$$eval
比$$
+evaluate
更高效。
高级用法
与 page.waitForXPath
结合(XPath 选择器)
javascript
const items = await page.$x('//div[@class="item"]'); // XPath 选择
for (const item of items) {
await item.click();
}
截图多个元素
javascript
const images = await page.$$('img');
for (let i = 0; i < images.length; i++) {
await images[i].screenshot({ path: `image_${i}.png` });
}
总结
-
page.$$()
适合需要对元素逐个操作的场景(如点击、截图、动态判断)。 -
page.$$eval()
适合快速提取数据或批量修改属性。 -
如果遇到元素选择问题,可结合
page.waitForSelector
或调整选择器(如:visible
伪类模拟)。