news 2026/4/18 15:22:56

Puppeteer 实践笔记

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Puppeteer 实践笔记

概念理解

Puppeteer 是一个 Node.js 库,提供了高级 API 来控制无头(headless)Chrome 或 Chromium 浏览器。它通过 Chrome DevTools Protocol(CDP)与浏览器通信,可以实现页面自动化、爬虫、性能测试等功能。

Puppeteer 默认会安装对应版本的浏览器,如果只是想使用 Puppeteer 提供的高级 API 去控制浏览器 ,可以直接使用puppeteer-core而不是puppeteerpuppeteer具体安装的浏览器版本可以查看 支持的浏览器。

核心概念

  • Browser(浏览器实例):通过puppeteer.launch()创建的浏览器实例,可以管理多个页面。
  • Page(页面实例):代表浏览器中的一个标签页,每个页面都是独立的执行环境。
  • ElementHandle(元素句柄):通过选择器获取的 DOM 元素引用,可以对其进行操作。
  • CDP(Chrome DevTools Protocol):Chrome 开发者工具协议,Puppeteer 通过该协议与浏览器通信。

应用场景

  • 自动化脚本操作:自动化表单填写、页面操作等。
  • 爬虫:抓取网页数据,处理动态内容。
  • 自动化测试:端到端测试、UI 测试。
  • 性能分析:页面性能监控、性能报告生成,小推一下自己在维护的 MCP Server 项目 puppeteer-debugger-mcp-server。
  • 截图和 PDF 生成:页面截图、PDF 导出。

基础使用

创建浏览器实例

constbrowser=awaitpuppeteer.launch({headless:'new',defaultViewport:{width:1920,height:1080,},executablePath:path.resolve(EXCUTABLE_PATH),});// 关闭浏览器awaitbrowser.close();

参数说明

  • headless:无头浏览器设置,可选值:
    • false:显示浏览器窗口。
    • 'new':启用新的无头浏览器模式(推荐)。
    • true:已废弃,因为旧版无头浏览器存在各种问题。
    • 无头浏览器(不显示浏览器页面)有更少的内存占用和 CPU 消耗,适合命令行环境,但可能触发反爬机制,需要手动添加userAgent等参数。
  • defaultViewport:浏览器内的页面视窗大小。
  • executablePath:浏览器的运行路径,不填则使用 Puppeteer 安装时自带的 Chromium 浏览器。

创建页面实例

constpage=awaitbrowser.newPage();// 关闭页面awaitpage.close();

执行操作后,Puppeteer 会在当前浏览器内新建一个页面,每个page代表一个标签页,每个标签页的操作都是独立开的。

页面跳转

awaitpage.goto(url,options);

参数说明

  • url:要跳转的页面地址
  • options(可选):配置选项,如waitUntil(等待条件)、timeout(超时时间)等

元素操作

选中元素

Puppeteer 提供了两种方式来选中和操作元素:

1. 使用 CDP 协议选中元素
constelementHandle=awaitpage.$(selector);

Puppeteer 调用底层 CDP 协议去选中元素,会根据元素类型返回相应的ElementHandle对象,此时可以直接使用对象来进行元素相关操作。

2. 使用 JavaScript 代码操作 DOM
constresult=awaitpage.evaluate(()=>{returndocument.querySelector(selector);});

page.evaluate()是在页面内执行代码的函数,通过返回值来获取元素或执行操作。

注意page.evaluate()内部是一个独立于 Node.js 进程的浏览器环境,外部变量无法直接在函数内使用,需要通过page.evaluate()的第二个参数传入:

constname='Aliex';awaitpage.evaluate((name)=>{console.log(name);},name);

输入内容

awaitpage.type(selector,text,options);

参数说明

  • selector:被输入的元素选择器。
  • text:输入到浏览器中的内容。
  • options(可选):配置选项,如输入延迟等。

page.type()可以模拟键盘操作,在特定元素中键入内容。也可以模拟键盘快捷键操作。

点击元素

awaitpage.click(selector,options);

参数说明

  • selector:被点击的元素选择器。
  • options(可选):配置选项,如点击次数、延迟等。

通过该方法可以点击页面上的元素,不过有时行不通,需要借助page.evaluate()这种原生操作去实现点击。

等待操作

由于页面加载会涉及很多脚本执行,通常需要一些等待操作来确保页面或元素已加载完成。Puppeteer 提供了各种环境下的waitFor函数供我们使用。

等待一段时间

awaitpage.waitForTimeout(timeout);

可以控制一定的等待时间,在这之后才继续执行后面的函数。

等待元素存在于页面

awaitpage.waitForSelector(selector,options);

可用于等待当前页面元素出现,支持 query 选择方式。

但在测试中发现有时候会选不到相应的元素,所以可以使用另外一种方式:

awaitpage.waitForFunction(()=>{returndocument.querySelector(selector);});

waitForFunction()是一种较为灵活的等待方式,我们可以用它来等待元素加载完毕,或者实现一些其他操作,例如等待元素显示出来:

awaitpage.waitForFunction(()=>{returndocument.querySelector(selector).style.display!=='none';});

只要返回的结果为true,函数就会停止继续等待。

等待页面加载完毕

awaitpage.waitForNavigation(options);

可以等待页面加载完毕后再执行后面的函数,即页面左上角的刷新图标停止转动之后,才执行后面的代码。

设置等待超时时间

有时候因为网络问题导致出现网卡的情况,会导致等待时间过长。Puppeteer 本身会在等待超过 30s 之后停止等待,因此在需要的情况下,可以重新设置超时等待时间:

page.setDefaultTimeout(timeout);

等待网络请求

waitForRequest()是 Puppeteer 中的一个方法,用于等待特定的请求发出:

awaitpage.waitForRequest(urlOrPredicateOrPattern,options);

参数说明

  • urlOrPredicateOrPattern:可接受字符串、正则表达式或预定义的请求匹配器函数来指定需要等待的请求。
  • options(可选):可传递一个对象来指定附加选项,如超时时间等。

示例用法

// 等待特定 URL 的请求awaitpage.waitForRequest('https://example.com/api/data');// 使用正则表达式awaitpage.waitForRequest(/api/data$/);// 使用自定义匹配器函数awaitpage.waitForRequest((request)=>request.url().includes('api')&&request.method()==='POST');

在上述示例中,waitForRequest()会等待发出匹配条件的请求。一旦请求被发出,waitForRequest()会立即返回。

高级技巧

文件上传

如果页面比较遵守 W3C 开发规范,通常上传元素会使用<input type="file" />去实现。这时就可以通过 Puppeteer 原生的元素获取方式来进行文件上传:

constvideoInputHandle=awaitpage.$(inputSelector);// uploadFile 是 ElementHandle input 对象特有的方法awaitvideoInputHandle.uploadFile(path);

参数说明

  • path:需要上传的本地文件路径,不支持网络文件。

这样就可以触发本地上传功能。

将函数注入到页面内

使用page.exposeFunction()将本地函数暴露到页面的window对象上:

// 注入函数awaitpage.exposeFunction('handleMutation',(str)=>{console.log('DOM mutated!',str);console.log(page);// 这里可以拿到外部内容});awaitpage.evaluate(()=>{constobserver=newMutationObserver(()=>{window.handleMutation('params');// 可以传递参数到注入的函数中});observer.observe(document.querySelector('.element-class'),{childList:true,subtree:true,attributes:true,});});

页面跳转时注入/执行代码

在页面跳转时调用page.evaluate(),可能会因为 page 的上下文环境不同,导致代码执行崩溃。

解决方式是保存 URL 地址,在执行之前进行比较判断:

consturl1=page.url();// ... 其他操作consturl2=page.url();// 避免执行时上下文环境不同导致 Puppeteer 崩溃if(url1===url2){awaitpage.evaluate(fn);}

清空浏览器 Cookie

利用 CDP (Chrome DevTools Protocol) 清除 Cookie

constpage=awaitbrowser.newPage();constclient=awaitpage.target().createCDPSession();awaitclient.send('Network.clearBrowserCookies');

提升浏览器运行性能

constbrowser=awaitpuppeteer.launch({headless:'new',defaultViewport:{width:1920,height:1080,},args:['--disable-gpu','--disable-dev-shm-usage','--disable-setuid-sandbox','--no-first-run','--no-sandbox','--no-zygote',],});

这些参数可以禁用一些不必要的功能,减少资源消耗,提升浏览器运行性能。

分支流程处理

当有两个 Puppeteer 异步流程时,可以使用Promise.any()来实现异步分支:

constres=awaitPromise.any([page.waitForNavigation(),page.waitForTimeout(15000),]);

这样可以实现 “等待导航完成或超时 15 秒” 的逻辑。

思考

1. 为什么需要使用无头浏览器模式?

无头浏览器模式(headless)不显示浏览器窗口,有更少的内存占用和 CPU 消耗,适合在服务器环境或命令行界面中使用。但可能会触发一些网站的反爬机制,需要手动添加userAgentviewport等参数来模拟真实浏览器。

2.page.evaluate()page.$()的区别是什么?

  • page.$()使用 CDP 协议选中元素,返回ElementHandle对象,可以直接调用 Puppeteer 提供的方法进行操作。
  • page.evaluate()在页面内执行 JavaScript 代码,可以访问页面的 DOM 和全局对象,但返回的是序列化后的值,无法直接操作 DOM 元素。

3. 如何避免页面跳转时的上下文丢失问题?

在页面跳转时,页面的上下文环境会发生变化,如果在跳转过程中调用page.evaluate()可能会失败。解决方式是保存跳转前后的 URL,在执行代码前比较 URL 是否一致,或者使用page.waitForNavigation()等待跳转完成后再执行操作。

总结

  • Puppeteer 核心概念:通过 Browser、Page、ElementHandle 等对象实现对浏览器的控制,使用 CDP 协议与浏览器通信。
  • 基础操作:创建浏览器实例、新建页面、页面跳转、元素操作(选中、输入、点击)是 Puppeteer 的基础功能。
  • 等待机制:提供了多种等待函数(waitForSelectorwaitForNavigationwaitForFunction等)来确保页面或元素已加载完成。
  • 高级技巧:文件上传、函数注入、性能优化、分支流程处理解决复杂场景下的问题。
  • 注意事项:需要注意页面上下文环境的变化、无头浏览器可能触发反爬机制、等待超时等问题。

参考内容

  • Puppeteer 官方文档
  • Chrome DevTools Protocol
  • Puppeteer性能优化与执行速度提升
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 6:38:24

解锁AMD性能潜力:SMUDebugTool新手入门完全指南

解锁AMD性能潜力&#xff1a;SMUDebugTool新手入门完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitcode.…

作者头像 李华
网站建设 2026/4/18 6:39:40

城通网盘终极解决方案:3分钟搞定免费直链下载

城通网盘终极解决方案&#xff1a;3分钟搞定免费直链下载 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 还在为城通网盘的广告弹窗和繁琐验证而烦恼吗&#xff1f;每天面对强制等待时间、反复跳转页面…

作者头像 李华
网站建设 2026/4/18 6:40:11

城通网盘直链解析技术深度解析:突破下载限制的智能解决方案

城通网盘作为国内广泛使用的文件存储服务&#xff0c;其下载限制一直是用户面临的痛点。ctfileGet项目通过创新的多节点架构和智能解析机制&#xff0c;为技术用户提供了稳定可靠的文件获取工具。本文将深入探讨该工具的核心技术实现和实际应用场景。 【免费下载链接】ctfileGe…

作者头像 李华
网站建设 2026/4/17 21:59:21

Sunshine游戏串流终极完全指南:从零构建个人云游戏平台

Sunshine游戏串流终极完全指南&#xff1a;从零构建个人云游戏平台 【免费下载链接】Sunshine Sunshine: Sunshine是一个自托管的游戏流媒体服务器&#xff0c;支持通过Moonlight在各种设备上进行低延迟的游戏串流。 项目地址: https://gitcode.com/GitHub_Trending/su/Sunsh…

作者头像 李华
网站建设 2026/4/18 6:39:39

城通网盘智能下载加速终极指南:3分钟解锁高速直连方案

还在为城通网盘的龟速下载而烦恼吗&#xff1f;想要彻底告别限速时代&#xff0c;享受真正的智能下载加速体验吗&#xff1f;今天我将为你分享一套完整的城通网盘提速方案&#xff0c;通过直连技术让你的下载速度实现质的飞跃。这套基于开源工具的方法&#xff0c;操作简单&…

作者头像 李华
网站建设 2026/4/18 6:42:56

MouseTester专业鼠标性能测试工具完全使用手册

MouseTester专业鼠标性能测试工具完全使用手册 【免费下载链接】MouseTester 项目地址: https://gitcode.com/gh_mirrors/mo/MouseTester 想要精准评估鼠标性能表现&#xff1f;MouseTester专业鼠标性能测试工具为你提供全面的解决方案。这款基于C#开发的开源工具能够深…

作者头像 李华