Puppeteer 学习笔记及基本用法

  • Puppeteer 安装
  • 语法
    • 基本语法
      • API 分层结构
      • 加载导航页面
      • 等待元素、请求、响应
      • 自定义等待
      • 元素定位
      • 用户模拟操作
    • 请求拦截
    • 获取 WebSocket 响应
    • 植入 JavaScript 代码
    • 页面性能分析
    • 文件的上传和下载
    • 跳转新 tab 页处理
    • 模拟不同的设备
    • 模拟键盘

Puppeteer 安装

  • 安装第三方库:puppeteer

    npm i puppeteer
    
  • 安装谷歌 Chromium:若 npm 安装失败,需要手动下载 chromium 并解压至相应文件夹

语法

基本语法

API 分层结构

  • Browser: 对应一个浏览器实例,一个 Browser 可以包含多个 BrowserContext
  • BrowserContext: 对应浏览器一个上下文会话,就像我们打开一个普通的 Chrome 之后又打开一个隐身模式的浏览器一样,BrowserContext 具有独立的 Session(cookie 和 cache 独立不共享),一个 BrowserContext 可以包含多个 Page
  • Page:表示一个 Tab 页面,通过 browserContext.newPage()/browser.newPage() 创建,browser.newPage() 创建页面时会使用默认的 BrowserContext,一个 Page 可以包含多个 Frame
  • Frame: 一个框架,每个页面有一个主框架(page.MainFrame()),也可以多个子框架,主要由 iframe 标签创建产生的
  • ExecutionContext: 是 javascript 的执行环境,每一个 Frame 都一个默认的 javascript 执行环境
  • ElementHandle: 对应 DOM 的一个元素节点,通过该该实例可以实现对元素的点击,填写表单等行为,我们可以通过选择器,xPath 等来获取对应的元素
  • JsHandle:对应 DOM 中的 javascript 对象,ElementHandle 继承于 JsHandle,由于我们无法直接操作 DOM 中对象,所以封装成 JsHandle 来实现相关功能
  • CDPSession:可以直接与原生的 CDP 进行通信,通过 session.send 函数直接发消息,通过 session.on 接收消息,可以实现 Puppeteer API 中没有涉及的功能
  • Coverage:获取 JavaScript 和 CSS 代码覆盖率
  • Tracing:抓取性能数据进行分析
  • Response: 页面收到的响应
  • Request: 页面发出的请求
const puppeteer = require('puppeteer');(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.goto('https://www.baidu.com');await page.close();await browser.close();
})();

puppeteer 提供了两种方法用于创建一个 Browser 实例:

  • puppeteer.connect :连接一个已经存在的 Chrome 实例
  • puppeteer.launch : 每次都启动一个 Chrome 实例

puppeteer.launch() 的参数解释:其使用字典进行配置输入

  • headless: 是否使用浏览器界面启动,turnfalse

    • 默认为 turn 无头浏览器,不展示浏览器页面
    • 设置 false 参数,展示浏览器页面
  • **executablePath:**指定浏览器执行地址
  • timeout: 等待浏览器实例启动的最长时间(以毫秒为单位)。默认为30000(30秒)。设置为 0 禁用超时
  • slowMo: 放慢浏览器执行速度,方便测试观察
  • args: 传递给浏览器实例的其余参数
    • 例如:窗口最大化:['--start-maximized']
  • ignoreHTTPSErrors:false 表示忽略 https 报错

加载导航页面

  • page.goto 打开新页面

  • page.goBack 回退到上一个页面

  • page.goForward 前进到下一个页面

  • page.reload 重新加载页面

  • page.waitForNavigation 等待页面跳转

 Pupeeteer 中的基本上所有的操作都是异步的,以上几个 API 都涉及到关于打开一个页面,什么情况下才能判断这个函数执行完毕呢,这些函数都提供了两个参数 waitUtil 和 timeout , waitUtil 表示直到什么出现就算执行完毕,timeout 表示如果超过这个时间还没有结束就抛出异常。

等待元素、请求、响应

  • page.waitForXPath 等待 XPath 对应的元素出现,返回对应的 ElementHandle 实例

  • page.waitForSelector 等待选择器对应的元素出现,返回对应的 ElementHandle 实例

  • page.waitForResponse 等待某个响应结束,返回 Response 实例

  • page.waitForRequest 等待某个请求出现,返回 Request 实例

自定义等待

  • page.waitForFunction 等待在页面中自定义函数的执行结果,返回 JsHandle 实例
  • page.waitFor 设置等待时间,实在没办法的做法

元素定位

  • page.$('#uniqueId') 获取某个选择器对应的第一个元素
  • page.$$('div') 获取某个选择器对应的所有元素
  • page.$x('//img') 获取某个 XPath 对应的所有元素
  • page.waitForXPath('//img') 等待某个 XPath 对应的元素出现
  • page.waitForSelector('#uniqueId') 等待某个选择器对应的元素出现

用户模拟操作

  • elementHandle.click() 点击某个元素
  • elementHandle.tap() 模拟手指触摸点击
  • elementHandle.focus() 聚焦到某个元素
  • elementHandle.hover() 鼠标 hover 到某个元素上
  • elementHandle.type('hello') 在输入框输入文本

请求拦截

我们可以在监听 Page 的 request 事件,并进行请求拦截,前提是要开启请求拦截 page.setRequestInterception(true)

(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();const blockTypes = new Set(['image', 'media', 'font']);await page.setRequestInterception(true); //开启请求拦截page.on('request', request => {const type = request.resourceType();const shouldBlock = blockTypes.has(type);if(shouldBlock){//直接阻止请求return request.abort();}else{//对请求重写return request.continue({//可以对 url,method,postData,headers 进行覆盖headers: Object.assign({}, request.headers(), {'puppeteer-test': 'true'})});}});await page.goto('https://demo.youdata.com');await page.close();await browser.close();
})();

page 页面上都提供的触发事件:

  • page.on('close') 页面关闭
  • page.on('console') console API 被调用
  • page.on('error') 页面出错
  • page.on('load') 页面加载完
  • page.on('request') 收到请求
  • page.on('requestfailed') 请求失败
  • page.on('requestfinished') 请求成功
  • page.on('response') 收到响应
  • page.on('workercreated') 创建 webWorker
  • page.on('workerdestroyed') 销毁 webWorker

获取 WebSocket 响应

Puppeteer 目前没有提供原生的用于处理 WebSocket 的 API 接口,但是我们可以通过更底层的 Chrome DevTool Protocol (CDP) 协议获得

(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();//创建 CDP 会话let cdpSession = await page.target().createCDPSession();//开启网络调试,监听 Chrome DevTools Protocol 中 Network 相关事件await cdpSession.send('Network.enable');//监听 webSocketFrameReceived 事件,获取对应的数据cdpSession.on('Network.webSocketFrameReceived', frame => {let payloadData = frame.response.payloadData;if(payloadData.includes('push:query')){//解析payloadData,拿到服务端推送的数据let res = JSON.parse(payloadData.match(/\{.*\}/)[0]);if(res.code !== 200){console.log(`调用websocket接口出错:code=${res.code},message=${res.message}`);}else{console.log('获取到websocket接口数据:', res.result);}}});await page.goto('https://netease.youdata.163.com/dash/142161/reportExport?pid=700209493');await page.waitForFunction('window.renderdone', {polling: 20});await page.close();await browser.close();
})();

植入 JavaScript 代码

await page.evaluate(() => {// document.getElementById("#menus").classList.add("menus-show");// let menus = document.querySelector('#menus') as HTMLDivElement// menus.classList.add('menus-show')// console.log(menus)let button = document.querySelector('#all_menus_item') as HTMLDivElementbutton.addEventListener('click', function(){console.log("点击【全部产品】")})})

有哪些函数可以在浏览器环境中执行代码:

  • page.evaluate(pageFunction[, ...args]) 在浏览器环境中执行函数
  • page.evaluateHandle(pageFunction[, ...args]) 在浏览器环境中执行函数,返回 JsHandle 对象
  • page.$$eval(selector, pageFunction[, ...args]) 把 selector 对应的所有元素传入到函数并在浏览器环境执行
  • page.$eval(selector, pageFunction[, ...args]) 把 selector 对应的第一个元素传入到函数在浏览器环境执行
  • page.evaluateOnNewDocument(pageFunction[, ...args]) 创建一个新的 Document 时在浏览器环境中执行,会在页面所有脚本执行之前执行
  • page.exposeFunction(name, puppeteerFunction) 在 window 对象上注册一个函数,这个函数在 Node 环境中执行,有机会在浏览器环境中调用 Node.js 相关函数库

页面性能分析

Puppeteer 提供了对页面性能分析的工具,目前功能还是比较弱的,只能获取到一个页面性能执行的数据

(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();await page.tracing.start({path: './files/trace.json'});await page.goto('https://www.google.com');await page.tracing.stop();/*continue analysis from 'trace.json'*/browser.close();
})();

文件的上传和下载

(async () => {const browser = await puppeteer.launch();const page = await browser.newPage();//通过 CDP 会话设置下载路径const cdp = await page.target().createCDPSession();await cdp.send('Page.setDownloadBehavior', {behavior: 'allow', //允许所有下载请求downloadPath: 'path/to/download'  //设置下载路径});//点击按钮触发下载await (await page.waitForSelector('#someButton')).click();//等待文件出现,轮训判断文件是否出现await waitForFile('path/to/download/filename');//上传时对应的 inputElement 必须是<input>元素let inputElement = await page.waitForXPath('//input[@type="file"]');await inputElement.uploadFile('/path/to/file');browser.close();
})();

跳转新 tab 页处理

let page = await browser.newPage();
await page.goto(url);
let btn = await page.waitForSelector('#btn');
//在点击按钮之前,事先定义一个 Promise,用于返回新 tab 的 Page 对象
const newPagePromise = new Promise(res => browser.once('targetcreated', target => res(target.page()))
);
await btn.click();
//点击按钮后,等待新tab对象
let newPage = await newPagePromise;

模拟不同的设备

Puppeteer 提供了模拟不同设备的功能,其中 puppeteer.devices 对象上定义很多设备的配置信息,这些配置信息主要包含 viewport 和 userAgent,然后通过函数 page.emulate 实现不同设备的模拟

const puppeteer = require('puppeteer');
const iPhone = puppeteer.devices['iPhone 6'];
puppeteer.launch().then(async browser => {const page = await browser.newPage();await page.emulate(iPhone);await page.goto('https://www.google.com');await browser.close();
});

模拟键盘

// 模拟键盘“回车”键
await page.keyboard.press('Enter');

Puppeteer 学习笔记及基本用法相关推荐

  1. 情态动词学习笔记(4) 基本用法:建议和忠告

    情态动词学习笔记(4) 基本用法:建议和忠告 could 表建议 it is a nice day. we could go for a walk. 今天天气不错,我们可以出去散步 shall用于第一 ...

  2. socket编程学习笔记:部分函数用法以及accept函数问题

    学习笔记:socket编程部分函数用法 socket()函数: bind()函数: listen()函数: accept()函数: connect()函数: socket()函数: socket函数对 ...

  3. SQL学习笔记 where子句用法,like关键字 嵌套查询

    where子句 比较运算符: < , <= , > , >= , = , != , !< , !> .  text , ntext , image .型数据不可用. ...

  4. 学习笔记之awk用法

               文本处理三剑客之awk 1. 首先简要总结一些文本处理三剑客: grep族:文本过滤工具 sed:行编辑工具 2. 下面就来看看awk是什么? awk现在linux上用的是GNU ...

  5. 学习笔记之sed用法

                          Sed命令用法 sed是文本三剑客之一 sed是什么? Sed:行编辑工具,处理一行文本.一次从文本中读取一行,将这一行放在自己的模式空间中,如果能被sed ...

  6. java学习笔记(五)----super用法,final用法,抽象类,接口

    子类不会继承父类的构造方法,在子类的构造方法中可使用super(参数列表)调用父类的构造方法. class Person { String name;   int age;   public Pers ...

  7. Boostrap学习笔记一: popover用法

    最近在自学java web基础,搭建自己的页面时候用到了Boostrap的JS库.由于之前没有接触过JQuery,所以用起来磕磕绊绊,所以在这里简单记一下Boostrap中我用到的JS 插件的一些用法 ...

  8. Puppeteer学习笔记 (2)- Puppeteer的安装

    本文链接:https://www.cnblogs.com/hchengmx/p/11009849.html 1. node的下载安装 由于puppeteer是nodejs的一个库,所以首先需要安装no ...

  9. lambda表达式浅析【C++学习笔记】

    lambda表达式浅析[C++学习笔记] 基本用法: auto f = [/*捕获列表*/](/*参数*/)->int /*后置返回值类型*/{/** 函数体*/}; 捕获列表: [] : 不捕 ...

最新文章

  1. mysql设计规范和原则
  2. C++类模板(二)用类模板实现可变长数组
  3. 稍等片刻 正在提取文件_电脑文件误删除并且清空了回收站,怎么恢复文件?教你一招!...
  4. HTML5-WebSocket实现对服务器CPU实时监控
  5. web----DNS解析
  6. 怎样在html中实现图层重叠,javascript – 在HTML5画布中实现图层
  7. SQLiteOpenHelper使用详解
  8. 研究相机和IMU坐标系变换
  9. Bootstrap 按钮菜单的尺寸
  10. 射手科技公开课第一辑 『项目管理和代码规范』
  11. 时光邮局互助排单匹配系统软件开发
  12. java 网络爬虫_使用Java实现网络爬虫
  13. winamp 珍藏_Winamp发生了什么,您现在可以使用吗?
  14. 工具 - 屏幕录像专家7.5注册机
  15. 人不成熟的几大特征-----海尔集团CEO张瑞敏演讲稿
  16. 关于Tween的几个注意事项
  17. 男大学生眼中的完美女大学生(转载)
  18. 一个公司有m名推销员,他们都推销n种不同的产品。其中m>=l;m<=100,n>=l,n<=10。每天,每个推销员都要为售出的每一种产品交上来一个卡片。
  19. 产品有复杂的卡扣倒扣,我们如何设计模具结构?
  20. 狗狗图片识别分类的CNN(卷积网络)实现

热门文章

  1. java编写自动化脚本生成apk_Unity3D研究院之Android全自动打包生成apk(六十九)
  2. python 材料科学与工程专业_2020年最全的python的就业方向+清华计算机社流出上千集编程资料...
  3. python虚拟环境-conda
  4. Python编程基础:第五十二节 高阶函数High Order Functions
  5. Python编程基础:第二十九节 异常Exception
  6. java 四种实现延迟加载的方法
  7. [Security] Automatically adding CSRF tokens to ajax calls when using jQuery--转
  8. haproxy配置文件详解--转
  9. DALSA线阵CCD相机开发 之 opencv读取图片
  10. .如何在Linux上安装Postman应用程序?