
本文深入探讨了Puppeteer库中`.$eval()`和`.$$eval()`这两个核心DOM操作方法的正确使用方式。我们将通过实际代码示例,详细阐述它们在处理单个和多个DOM元素时的差异与最佳实践,并展示如何利用这些方法进行复杂的网页自动化,如模拟打字测试,涵盖请求拦截、元素交互及结果捕获等进阶技巧,旨在提升开发者在网页抓取和自动化任务中的效率与准确性。
在前端自动化和网页抓取领域,Puppeteer是一个功能强大的库,它提供了高级API来控制Chrome或Chromium。其中,page.$eval()、elementHandle.$eval()以及page.$$eval()、elementHandle.$$eval()是与页面DOM交互的核心方法。理解它们之间的区别和正确用法,对于高效地进行DOM查询和数据提取至关重要。
.$eval()方法用于在页面上下文中对匹配指定选择器的第一个元素执行一个函数。它的回调函数接收一个DOM元素作为参数,允许你直接操作或提取该元素的属性。
基本用法示例:
假设我们想从ID为#words的容器中获取第一个div元素的HTML内容:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://monkeytype.com/', { waitUntil: 'domcontentloaded' });
// 等待 #words 元素出现
const wordsSelector = await page.waitForSelector('#words');
// 使用 .$eval 获取第一个 div 的 innerHTML
const innerHtml = await wordsSelector.$eval('div', element => element.innerHTML);
console.log(innerHtml); // 预期输出:<letter>i</letter><letter>n</letter>...
await browser.close();
})();在这个例子中,wordsSelector.$eval('div', ...)会在#words元素内部查找第一个div,并将其作为element参数传递给回调函数。回调函数返回该元素的innerHTML。
.$$eval()方法则用于在页面上下文中对匹配指定选择器的所有元素执行一个函数。与.$eval()不同,它的回调函数接收一个DOM元素数组作为参数。这是初学者常犯错误的地方,误以为回调函数接收的是单个元素。
常见错误示例:
尝试像.$eval()那样直接访问words.innerHTML会导致错误,因为words此时是一个数组:
ECTouch移动商城系统
ECTouch是上海商创网络科技有限公司推出的一套基于 PHP 和 MySQL 数据库构建的开源且易于使用的移动商城网店系统!应用于各种服务器平台的高效、快速和易于管理的网店解决方案,采用稳定的MVC框架开发,完美对接ecshop系统与模板堂众多模板,为中小企业提供最佳的移动电商解决方案。ECTouch程序源代码完全无加密。安装时只需将已集成的文件夹放进指定位置,通过浏览器访问一键安装,无需对已有
0
查看详情
// 错误示例:
// const wordsSelector = await page.waitForSelector('#words');
// console.log(await wordsSelector.$$eval('div', words => words.innerHTML));
// 这里的 'words' 是一个数组,没有 innerHTML 属性正确用法示例:
要正确使用.$$eval(),你需要遍历这个元素数组,并对每个元素执行操作。通常,我们会使用Array.prototype.map()方法来提取每个元素的所需属性。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const url = "https://monkeytype.com/";
await page.goto(url, { waitUntil: "domcontentloaded" });
// 假设页面有隐私政策弹窗,需要点击拒绝
const rejectAllButton = await page.waitForSelector(".rejectAll");
if (rejectAllButton) {
await rejectAllButton.click();
}
// 等待激活的单词元素出现
await page.waitForSelector("#words .word.active");
const wordsEl = await page.$("#words");
// 使用 $$eval 获取所有 .word 元素的 innerHTML
const wordsInnerHtmlArray = await wordsEl.$$eval(".word", els =>
els.map(el => el.innerHTML) // 遍历数组,提取每个元素的 innerHTML
);
console.log(wordsInnerHtmlArray); // 预期输出:['<letter>w</letter>...', '<letter>o</letter>...']
// 最佳实践:如果只需要纯文本,推荐使用 .textContent
const wordsTextContentArray = await wordsEl.$$eval(".word", els =>
els.map(el => el.textContent.trim()) // 提取纯文本并去除空白
);
console.log(wordsTextContentArray); // 预期输出:['word1', 'word2', ...]
await browser.close();
})();在这个修正后的例子中,els是一个DOM元素数组。我们通过els.map(el => el.innerHTML)遍历这个数组,为每个元素提取innerHTML,最终得到一个包含所有innerHTML字符串的数组。
提示:innerHTML vs textContent
当你的目标是获取元素的纯文本内容时,强烈建议使用element.textContent而不是elem
ent.innerHTML。textContent只返回元素及其后代节点的文本内容,不包含任何HTML标签,这通常更符合数据抓取的需求,并且可以避免不必要的解析和潜在的安全问题。
为了更全面地展示.$eval()和.$$eval()的实际应用,我们来看一个模拟打字测试的复杂场景。这个例子不仅会使用到上述方法,还会涉及请求拦截、元素交互和结果捕获。
const puppeteer = require("puppeteer");
let browser;
(async () => {
browser = await puppeteer.launch({ headless: true }); // 设置 headless: false 可观察浏览器操作
const [page] = await browser.pages();
const url = "https://monkeytype.com/";
// 1. 设置请求拦截以优化性能和稳定性
await page.setRequestInterception(true);
const allowedDomains = [
"https://monkeytype.com",
"https://www.monkeytype.com",
"https://api.monkeytype.com",
"https://fonts.google", // 允许加载字体文件
];
page.on("request", request => {
if (allowedDomains.some(domain => request.url().startsWith(domain))) {
request.continue();
} else {
request.abort(); // 阻止加载其他不必要的资源,如广告、分析脚本等
}
});
// 2. 导航到目标页面并等待DOM加载完成
await page.goto(url, { waitUntil: "domcontentloaded" });
// 3. 处理隐私政策弹窗(如果存在)
const rejectAllButton = await page.waitForSelector(".rejectAll");
if (rejectAllButton) {
await rejectAllButton.click();
}
// 4. 等待打字测试区域加载完成,确保单词可见
await page.waitForSelector("#words .word.active");
const wordsContainer = await page.$("#words"); // 获取单词容器的 ElementHandle
// 5. 模拟打字过程
try {
for (;;) { // 无限循环,直到没有活动的单词或出现错误
// 使用 .$eval 获取当前活动单词的纯文本
const activeWord = await wordsContainer.$eval(".word.active", el =>
el.textContent.trim()
);
console.log(`正在输入: ${activeWord}`);
// 使用 ElementHandle.type() 模拟键盘输入
await wordsContainer.type(activeWord + " "); // 输入单词并加上空格
}
} catch (err) {
// 当没有 .word.active 元素时,.$eval 会抛出错误,表示打字测试可能已完成
console.log("打字测试可能已完成或遇到其他错误:", err.message);
}
// 6. 捕获测试结果
const results = await page.waitForSelector("#result");
// 将结果区域滚动到视图中,以便截图
await results.evaluate(el => el.scrollIntoView());
// 截图保存结果
await results.screenshot({ path: "typing-results.png" });
console.log("打字测试结果已保存到 typing-results.png");
})()
.catch(err => console.error("发生错误:", err))
.finally(() => browser?.close()); // 无论成功失败,确保关闭浏览器实例代码解析:
.$eval() 和 .$$eval() 是 Puppeteer 中用于在浏览器上下文中执行J*aScript并与DOM交互的强大工具。.$eval() 适用于单个元素的查询和操作,而 .$$eval() 则处理元素集合,通常需要结合 map 方法来提取每个元素的数据。通过掌握这些方法,并结合请求拦截、等待机制和错误处理等最佳实践,开发者可以构建出高效、稳定且功能强大的网页自动化和数据抓取解决方案。
以上就是Puppeteer中.$eval()与.$$eval()的高效使用指南的详细内容,更多请关注其它相关文章!
# javascript
# 免费网站可以自己优化吗
# 罗甸短视频营销推广
# 方法来
# 中对
# 多个
# 在这个
# 遍历
# 选择器
# 第一个
# 是一个
# 加载
# 回调
# google
# css
# word
# java
# html
# 前端
# go
# 浏览器
# 回调函数
# 工具
# ai
# 区别
# pc网站优化有哪些
# 菏泽网站优化与推广
# 参展商营销推广方式
# 有经验的聊城网站建设
# 邵阳seo网站优化技巧
# 常德网站建设招聘
# 忠县怎么推广外贸网站
# 服装店网站推广方案
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
小红书如何引流到私信?引流到私信有用吗?
Golang如何使用gRPC拦截器实现日志收集_Golang gRPC拦截器日志收集实践
网站体验不好=浪费钱:如何提升-用户体验效果差
J*aScript包管理器_Npm与Yarn对比
快手极速版在线体验区 快手极速版网页体验入口
抖音小程序怎么开通?小程序开通条件是什么?
MacBook Pro词典使用指南
如何查询国外邮政编码_国外邮政编码查询的多种有效途径
如何外贸网站设计-能留住客户提升用户体验!
百度网盘网页入口链接分享 百度网盘官网入口网页登录
电脑开不了机怎么办 电脑无法开机的解决方法
Lar*el如何创建自定义的辅助函数(Helpers)_Lar*el全局函数定义与加载方法
可米酷漫画在线阅读入口_ 可米酷漫画官网直达链接
风车动漫官网首页入口登录 风车动漫在线观看正版地址
大众点评了却看不到是怎么回事
iPhone 15 Pro如何查看存储空间占用_iPhone 15 Pro存储空间查看教程
win11如何运行chkdsk命令 Win11检查和修复磁盘逻辑错误教程【修复】
Dash应用中自定义HTML页面标题与网站图标(F*icon)的实用指南
word文档行距怎么调?word文档调行距的操作步骤
如何在解析前预检查XML文件的完整性? 比如检查文件大小或特定结束标签
悟空浏览器如何恢复关闭的标签页 悟空浏览器撤销关闭网页快捷键设置
《爱南宁》认证电动车方法
嘀嗒顺风车如何开具电子发票
163邮箱网页版官方登录入口 163邮箱网页版访问页面
在XML中嵌入二进制数据(如图片)的最佳实践是什么? Base64编码与解析注意事项
PHP安全加载非公开目录图片与动态内容类型处理指南
《微信》视频号原创声明开启方法
QQ阅读小说搜索入口地址_QQ阅读小说搜索入口地址搜索在线阅读
《宝可梦大集结》S4冠军之路开始时间介绍
Chart.js 教程:自定义插件实现图表与图例间距调整
qq音乐官方网站入口_qq音乐在线听歌网页版链接
《优志愿》修改手机号方法
《火花chat》搜索好友方法
mysql导入sql文件能分批导入吗_mysql分批次导入大sql文件的实用技巧
Fedora怎么安装 Fedora Workstation安装步骤
基于键值条件高效映射 Pandas DataFrame 多列数据
WooCommerce 新客户订单自动添加管理员备注教程
咸鱼怎么设置仅粉丝可见的动态_咸鱼动态粉丝可见设置方法
c++20的指定初始化(Designated Initializers)怎么用_c++ C风格结构体初始化
mysql怎么查询数据_mysql基础查询语句使用教程
《浙里办》电子发票开具方法
《绝区零》2.3前瞻|直播|内容介绍
Microsoft Edge网页字体太淡看不清怎么办_Microsoft Edge字体渲染优化技巧
英雄联盟争者留名活动介绍
SQLAlchemy 2.0 与 Pydantic 模型类型安全集成指南
悟空浏览器网页版链接 悟空浏览器网页版最新有效地址
J*aScript桌面应用_Electron多进程架构实战
餐馆菜篮选购指南
《随手记》启用语音备注方法
以下哪一个是适应长期护理制度发展而设立的新职业
2025-12-08
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。