文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

前端工程师的一大神器—Puppeteer

2024-12-02 22:08

关注

本文主要讲述一下Google出版并一直在不断维护的神器puppeteer,通过学习本文你将了解其基本使用和常用功能。

一、Puppeteer简介

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome,利用Puppeteer可以获取页面DOM节点、网络请求和响应、程序化操作页面行为、进行页面的性能监控和优化、获取页面截图和PDF等,利用该神器就可以操作Chrome浏览器玩出各种花样。

二、Puppeteer核心组成结构

Puppeteer的结构也反映了浏览器的结构,其核心结构如下所示:

  1. Browser:这是一个浏览器实例,可以拥有浏览器上下文,可通过 puppeteer.launch 或 puppeteer.connect 创建一个 Browser 对象。
  2. BrowserContext:该实例定义了一个浏览器上下文,可拥有多个页面,创建浏览器实例时默认会创建一个浏览器上下文(不能关闭),此外可以利用 browser.createIncognitoBrowserContext()创建一个匿名的浏览器上下文(不会与其它浏览器上下文共享cookie/cache).
  3. Page:至少包含一个主框架,除了主框架外还有可能存在其它框架,例如iframe。
  4. Frame:页面中的框架,在每个时间点,页面通过page.mainFrame()和frame.childFrames()方法暴露当前框架的细节。对于该框架中至少有一个执行上下文
  5. ExecutionCOntext:表示一个JavaScript的执行上下文。
  6. Worker:具有单个执行上下文,便于与 WebWorkers 交互。

三、基本使用和常用功能

该神器整体使用起来比较简单,下面就开始我们的使用之路。

3.1 启动Browser

核心函数就是异步调用puppeteer.launch()函数,根据相应的配置参数创建一个Browser实例。

  1. const path = require('path'); 
  2. const puppeteer = require('puppeteer'); 
  3.  
  4. const chromiumPath = path.join(__dirname, '../''chromium/chromium/chrome.exe'); 
  5.  
  6. async function main() { 
  7.     // 启动chrome浏览器 
  8.     const browser = await puppeteer.launch({ 
  9.         // 指定该浏览器的路径 
  10.         executablePath: chromiumPath, 
  11.         // 是否为无头浏览器模式,默认为无头浏览器模式 
  12.         headless: false 
  13.     }); 
  14.  
  15. main(); 

3.2 访问页面

访问页面首先需要创建一个浏览器上下文,然后基于该上下文创建一个新的page,最后指定要访问的网址。

  1. async function main() { 
  2.     // 启动chrome浏览器 
  3.     // …… 
  4.  
  5.     // 在一个默认的浏览器上下文中被创建一个新页面 
  6.     const page1 = await browser.newPage(); 
  7.  
  8.     // 空白页访问该指定网址 
  9.     await page1.goto('https://51yangsheng.com'); 
  10.  
  11.     // 创建一个匿名的浏览器上下文 
  12.     const browserContext = await browser.createIncognitoBrowserContext(); 
  13.     // 在该上下文中创建一个新页面 
  14.     const page2 = await browserContext.newPage(); 
  15.     page2.goto('https://www.baidu.com'); 
  16.  
  17. main(); 

3.3 设备模拟

经常需要不同类型的机型的浏览结果,此时就可以采用设备模拟实现,下面模拟一个iPhone X的设备的浏览器结果

  1. async function main() { 
  2.     // 启动浏览器 
  3.  
  4.     // 设备模拟:模拟一个iPhone X 
  5.     // user agent 
  6.     await page1.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
  7.     // 视口(viewport)模拟 
  8.     await page1.setViewport({ 
  9.         width: 375, 
  10.         height: 812 
  11.     }); 
  12.      
  13.     // 访问某页面 
  14.  
  15. main(); 

3.4 获取DOM节点

获取DOM节点有两种方式,一种方式是直接调用page所带的原生函数,另一种是通过执行js代码获取。

  1. async function main() { 
  2.     // 启动chrome浏览器 
  3.     const browser = await puppeteer.launch({ 
  4.         // 指定该浏览器的路径 
  5.         executablePath: chromiumPath, 
  6.         // 是否为无头浏览器模式,默认为无头浏览器模式 
  7.         headless: false 
  8.     }); 
  9.  
  10.     // 在一个默认的浏览器上下文中被创建一个新页面 
  11.     const page1 = await browser.newPage(); 
  12.  
  13.     // 空白页访问该指定网址 
  14.     await page1.goto('https://www.baidu.com'); 
  15.  
  16.     // 等待title节点出现 
  17.     await page1.waitForSelector('title'); 
  18.  
  19.     // 用page自带的方法获取节点 
  20.     const titleDomText1 = await page1.$eval('title', el => el.innerText); 
  21.     console.log(titleDomText1);// 百度一下 
  22.  
  23.     // 用js获取节点 
  24.     const titleDomText2 = await page1.evaluate(() => { 
  25.         const titleDom = document.querySelector('title'); 
  26.         return titleDom.innerText; 
  27.     }); 
  28.     console.log(titleDomText2); 
  29.  
  30. main(); 

3.5 监听请求和响应

下面就来监听一下百度中某一js脚本的请求和响应,request事件是监听请求,response事件是监听响应。

  1. async function main() { 
  2.     // 启动chrome浏览器 
  3.     const browser = await puppeteer.launch({ 
  4.         // 指定该浏览器的路径 
  5.         executablePath: chromiumPath, 
  6.         // 是否为无头浏览器模式,默认为无头浏览器模式 
  7.         headless: false 
  8.     }); 
  9.  
  10.     // 在一个默认的浏览器上下文中被创建一个新页面 
  11.     const page1 = await browser.newPage(); 
  12.  
  13.     page1.on('request', request => { 
  14.         if (request.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') { 
  15.             console.log(request.resourceType()); 
  16.             console.log(request.method()); 
  17.             console.log(request.headers()); 
  18.         } 
  19.     }); 
  20.  
  21.     page1.on('response', response => { 
  22.         if (response.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') { 
  23.             console.log(response.status()); 
  24.             console.log(response.headers()); 
  25.         } 
  26.     }) 
  27.  
  28.     // 空白页刚问该指定网址 
  29.     await page1.goto('https://www.baidu.com'); 
  30.  
  31. main(); 

3.6 拦截某一请求

默认情况下request事件只有只读属性,不能够拦截请求,若想拦截该请求则需要通过page.setRequestInterception(value)启动请求拦截器,然后利用request.abort, request.continue 和 request.respond 方法决定该请求的下一步操作。

  1. async function main() { 
  2.     // 启动chrome浏览器 
  3.     const browser = await puppeteer.launch({ 
  4.         // 指定该浏览器的路径 
  5.         executablePath: chromiumPath, 
  6.         // 是否为无头浏览器模式,默认为无头浏览器模式 
  7.         headless: false 
  8.     }); 
  9.  
  10.     // 在一个默认的浏览器上下文中被创建一个新页面 
  11.     const page1 = await browser.newPage(); 
  12.  
  13.     // 拦截请求开启 
  14.     await page1.setRequestInterception(true);// true开启,false关闭 
  15.     page1.on('request', request => { 
  16.         if (request.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') { 
  17.             // 终止该请求 
  18.             request.abort(); 
  19.             console.log('该请求被终止!!!'); 
  20.         } 
  21.         else { 
  22.             // 继续该请求 
  23.             request.continue(); 
  24.         } 
  25.     }); 
  26.  
  27.     // 空白页访问该指定网址 
  28.     await page1.goto('https://www.baidu.com'); 
  29.  
  30. main(); 

3.7 截图

截图是一个很有用的功能,通过截取就可以保存一份快照,方便后期问题的排查。(注:在无头模式下进行截图,否则截的图可能有问题)

  1. async function main() { 
  2.     // 启动浏览器,访问页面的操作 
  3.      
  4.     // 截屏操作,使用Page.screenshot函数 
  5.     // 截取整个页面:Page.screenshot函数默认截取整个页面,加上fullPage参数就是全屏截取 
  6.     await page1.screenshot({ 
  7.         path: '../imgs/fullScreen.png'
  8.         fullPage: true 
  9.     }); 
  10.  
  11.     // 截取屏幕中一个区域的内容 
  12.     await page1.screenshot({ 
  13.         path: '../imgs/partScreen.jpg'
  14.         type: 'jpeg'
  15.         quality: 80, 
  16.         clip: { 
  17.             x: 0, 
  18.             y: 0, 
  19.             width: 375, 
  20.             height: 300 
  21.         } 
  22.     }); 
  23.  
  24.     browser.close(); 
  25.  
  26. main(); 

3.8 生成pdf

除了利用截图保留快照外,还可以使用pdf保留快照。

  1. async function main() { 
  2.     // 启动浏览器,访问页面的操作 
  3.      
  4.     // 根据网页内容生成pdf文件,使用Page.pdf——注意:必须在无头模式下才可以调用 
  5.     await page1.pdf({ 
  6.         path: '../pdf/baidu.pdf' 
  7.     }); 
  8.  
  9.     browser.close(); 
  10.  
  11. main(); 

本文转载自微信公众号「前端点线面」

 

来源:前端点线面内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯