大家好,我是若川。欢迎加我微信 ruochuan12,长期交流学习。今天推荐神器puppeteer,我猜有挺多人不知道。文章不长,看完有空也可以试玩。

我18年也写过一篇puppeteer爬取生成pdf的文章,时间真快。前端使用puppeteer 爬虫生成《React.js 小书》PDF并合并

点击下方卡片关注我、加个星标,或者查看源码等系列文章。学习源码整体架构系列、年度总结、JS基础系列

一、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实例。

const path = require('path');
const puppeteer = require('puppeteer');const chromiumPath = path.join(__dirname, '../', 'chromium/chromium/chrome.exe');async function main() {// 启动chrome浏览器const browser = await puppeteer.launch({// 指定该浏览器的路径executablePath: chromiumPath,// 是否为无头浏览器模式,默认为无头浏览器模式headless: false});
}main();

3.2 访问页面

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

async function main() {// 启动chrome浏览器// ……// 在一个默认的浏览器上下文中被创建一个新页面const page1 = await browser.newPage();// 空白页访问该指定网址await page1.goto('https://51yangsheng.com');// 创建一个匿名的浏览器上下文const browserContext = await browser.createIncognitoBrowserContext();// 在该上下文中创建一个新页面const page2 = await browserContext.newPage();page2.goto('https://www.baidu.com');
}main();

3.3 设备模拟

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

async function main() {// 启动浏览器// 设备模拟:模拟一个iPhone X// user agentawait 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')// 视口(viewport)模拟await page1.setViewport({width: 375,height: 812});// 访问某页面
}main();

3.4 获取DOM节点

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

async function main() {// 启动chrome浏览器const browser = await puppeteer.launch({// 指定该浏览器的路径executablePath: chromiumPath,// 是否为无头浏览器模式,默认为无头浏览器模式headless: false});// 在一个默认的浏览器上下文中被创建一个新页面const page1 = await browser.newPage();// 空白页访问该指定网址await page1.goto('https://www.baidu.com');// 等待title节点出现await page1.waitForSelector('title');// 用page自带的方法获取节点const titleDomText1 = await page1.$eval('title', el => el.innerText);console.log(titleDomText1);// 百度一下// 用js获取节点const titleDomText2 = await page1.evaluate(() => {const titleDom = document.querySelector('title');return titleDom.innerText;});console.log(titleDomText2);
}main();

3.5 监听请求和响应

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

async function main() {// 启动chrome浏览器const browser = await puppeteer.launch({// 指定该浏览器的路径executablePath: chromiumPath,// 是否为无头浏览器模式,默认为无头浏览器模式headless: false});// 在一个默认的浏览器上下文中被创建一个新页面const page1 = await browser.newPage();page1.on('request', request => {if (request.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') {console.log(request.resourceType());console.log(request.method());console.log(request.headers());}});page1.on('response', response => {if (response.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') {console.log(response.status());console.log(response.headers());}})// 空白页刚问该指定网址await page1.goto('https://www.baidu.com');
}main();

3.6 拦截某一请求

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

async function main() {// 启动chrome浏览器const browser = await puppeteer.launch({// 指定该浏览器的路径executablePath: chromiumPath,// 是否为无头浏览器模式,默认为无头浏览器模式headless: false});// 在一个默认的浏览器上下文中被创建一个新页面const page1 = await browser.newPage();// 拦截请求开启await page1.setRequestInterception(true);// true开启,false关闭page1.on('request', request => {if (request.url() === 'https://s.bdstatic.com/common/openjs/amd/eslx.js') {// 终止该请求request.abort();console.log('该请求被终止!!!');}else {// 继续该请求request.continue();}});// 空白页访问该指定网址await page1.goto('https://www.baidu.com');
}main();

3.7 截图

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

async function main() {// 启动浏览器,访问页面的操作// 截屏操作,使用Page.screenshot函数// 截取整个页面:Page.screenshot函数默认截取整个页面,加上fullPage参数就是全屏截取await page1.screenshot({path: '../imgs/fullScreen.png',fullPage: true});// 截取屏幕中一个区域的内容await page1.screenshot({path: '../imgs/partScreen.jpg',type: 'jpeg',quality: 80,clip: {x: 0,y: 0,width: 375,height: 300}});browser.close();
}main();

3.8 生成pdf

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

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


最近组建了一个江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你进群。


················· 若川出品 ·················

今日话题

一直涨粉很乏力,公众号不写原创,平时转载文章,活下来艰难。想着破局,但平时工作又忙,写原创文章艰难。只能暂时少接公众号广告了,能接广告变现有时是更新的动力啊,以后的路难走啊。同时深知写原创重要,但运营也很重要。原创、高质量和每天更新,这三点靠个人只能做到两点。欢迎分享、收藏、点赞、在看我的公众号文章~

一个愿景是帮助5年内前端人走向前列的公众号

可加我个人微信 ruochuan12,长期交流学习

推荐阅读

我在阿里招前端,我该怎么帮你?(现在还能加我进模拟面试群)

如何拿下阿里巴巴 P6 的前端 Offer

点击方卡片关注我、加个星标,或者查看源码等系列文章。
学习源码整体架构系列、年度总结、JS基础系列

前端工程师的一大神器——puppeteer相关推荐

  1. 摹客,前端工程师必备开发神器

    工欲善其事,必先利其器! 相信每个前端都经历过用PS手动切图的原始手法,有时候偷懒,还会直接用QQ截图,现在想想真是初生牛犊不怕虎,怎么方便怎么来~ 当时就在想,如果能有一款神器,帮我解放切图这种&q ...

  2. 前端工程师有哪些面试技巧值得掌握?

    这段时间受到疫情的影响,本身做java开发的,面试了入职了一个外包公司的前端岗位,入职属于驻场开发的那种,前几周基本没啥事,一般经理会让你刷题,到了驻场那边需要机试过关才能在那边开发,这边在牛客网,L ...

  3. js define函数_不夸张,这真的是前端圈宝藏书!360前端工程师Vue.js源码解析

    优秀源代码背后的思想是永恒的.普适的. 这些年来,前端行业一直在飞速发展.行业的进步,导致对从业人员的要求不断攀升.放眼未来,虽然仅仅会用某些框架还可以找到工作,但仅仅满足于会用,一定无法走得更远.随 ...

  4. 阿里P8前端工程师:如何成为一名优秀的前端工程师!

    前后端分离的开发模式让前端开发者的地位日益提升,待遇水涨船高,这又吸引了一拨人慕名学习前端课程,希望能在前端领域大展宏图. 但一个残酷的现实是市场上不缺普通前端开发,缺的是掌握专业技能的优秀前端工程师 ...

  5. 前端工程师做事的三重境界:我的进阶之路

    共 2835 字,读完需 5 分钟.写作本文的目的:构建自己关于前端工程师成长过程的认知模型,从自己的视角来分析 Programmer.Developer.Enginner 的能力结构与工程师成长过程 ...

  6. 一个合格的中级前端工程师需要掌握的技能笔记(下)

    Github来源:一个合格的中级前端工程师需要掌握的技能 | 求星星 ✨ | 给个❤️关注,❤️点赞,❤️鼓励一下作者 大家好,我是魔王哪吒,很高兴认识你~~ 哪吒人生信条:如果你所学的东西 处于喜欢 ...

  7. 万字启程——零基础~前端工程师_养成之路001篇

    目录 什么是前端 什么是后端 前端和后端的区别 前端工程师职责 后端工程师职责 前端的核心技术 HTML CSS JavaScript RESTful结构 特点 HTTP请求方式有哪些 目前最火的前端 ...

  8. 前端工程师的出路在哪里? 未来前端的发展方向和岗位

    阿里妹导读:很多童鞋在上次的问卷调查里表示,希望多推出一些前端方向的内容.今天为大家分享一篇关于前端工程师职业发展的文章,抛砖引玉,期待与大家一起交流探讨. 我是成曰,目前在蚂蚁金服数据平台部任职前端 ...

  9. 前端工程师的未来在哪里?

    阿里妹导读:很多童鞋在上次的问卷调查里表示,希望多推出一些前端方向的内容.今天为大家分享一篇关于前端工程师职业发展的文章,抛砖引玉,期待与大家一起交流探讨. 文章作者,目前在蚂蚁金服数据平台部任职前端 ...

最新文章

  1. Python学习之路—2018/6/20
  2. Host is not allowed to connect to this MySQL server解决方法
  3. Day 26: TogetherJS —— 让我们一起来编程!
  4. WIN10 OpenGL GLFW+GLAD 开发环境搭建
  5. ITK:在矢量图像上执行注册
  6. db2 springboot 整合_[SpringBoot]快速配置多数据源(整合MyBatis)
  7. c语言程序设计 第三版 哈工大,c语言程序设计 哈工大 苏小红 第三章习题
  8. 三星Galaxy Z海报曝光 采用双铰链三折叠设计
  9. python 函数调用之后,赋值不变,只是引用。全局变量和局部变量(一分钟读懂)
  10. 活动推荐 | 首届“中新人工智能高峰论坛”,与周志华、李德毅等大咖对话未来...
  11. 写出线程同步相关的方法,以银行账号存储款为例
  12. 开关电源测试软件有哪些,开关电源的测试项目大全,你确定都知道?
  13. 购买域名后如何使用?
  14. Unity3D MineCraft 我的世界 用Unity3D制作类似MineCraft我的世界的游戏:各种树
  15. Gazebo [Err] [REST.cc:205] Error in REST request 问题的解决
  16. 如何用计算机做音乐,怎么制作音乐-手把手教你用废旧物品DIY音乐道具,超好玩!...
  17. Android Studio学习笔记
  18. LZO--实时数据压缩库
  19. 燕十八redis 微博地址
  20. 基于PHP+MySQL的学生信息管理系统(源码)

热门文章

  1. python中fetchall函数_python中查询数据库时fetchone()函数和fetchall()函数的区别
  2. VS2017 调用Tesseract
  3. 雨棚板弹性法计算简图_钢结构工程量计算、报价要点
  4. 56、servlet3.0-与SpringMVC整合分析
  5. 1185 威佐夫游戏 V2
  6. Could NOT find SDL_image (missing:SDL_IMAGE_LIBRARIES SDL_IMAGE_INCLUDE_DIRS)
  7. [HNOI2008]玩具装箱toy(dp+斜率优化)
  8. 微信支付现金红包接口(转)
  9. php pcntl 多进程学习
  10. C#加密解密DES字符串转