首页 > 编程语言 >puppeteer( Nodejs 版 selenium )快速入门

puppeteer( Nodejs 版 selenium )快速入门

时间:2022-12-20 17:04:57浏览次数:67  
标签:const Nodejs await selenium Puppeteer puppeteer page browser


puppeteer 官网:​​https://pptr.dev/​​ Puppeteer 中文文档 (与官

Puppeteer 中文文档 :​​https://learnku.com/docs/puppeteer/3.1.0​

Puppeteer v1.5.0 中文翻peteer api 与 教程:​​https://pptr.dev/#?product=Puppeteer&version=v1.6.0&show=api-class-puppeteer​

github 地址 以及 doc :​​https://github.com/GoogleChrome/puppeteer​

Puppeteer的入门教端神器安利之 Puppeteer:​​https://jeffjade.com/2017/12/17/134-kinds-of-toss-using-puppeteer/​​ Puppeteer初探--爬取并生成《ES6标准入

详解 Puppeteer 入门教程:​https://www.jb51.net/article/139808.htm

puppete

爬虫利器 Puppeteer 实战:​​https://www.jianshu.com/p/a9a55c03f768​​​ puppeteer 爬虫
Puppeteer之爬虫入门:​​​https://www.e-learn.cn/content/qita/845998​​​ Puppeteer 实战
puppeteer实战之网页爬虫,模拟操作
puppeteer破解滑动验证码方法:​​​http://www.php.cn/js-tutorial-387019.html​​​ Node:使用Puppeteer完成一次复杂的爬虫:​​https://www.jianshu.com/p/97eeffa3bf3a​


 

 

API 文档

完整 ​​API 文档​​​ 和 ​​例子​​.

 

 

Puppeteer 出现的背景

 

Chrome59 (linux、macos)、 Chrome60(windows)之后,Chrome自带​​headless(无界面)模式​​很方便做自动化测试或者爬虫。但是如何和 headless 模式的 Chrome 交互则是一个问题。通过启动 Chrome 时的命令行参数仅能实现简易的启动时初始化操作。Selenium、Webdriver 等是一种解决方案,但是往往依赖众多,不够扁平。

puppeteer( Nodejs 版 selenium )快速入门_lua

Puppeteer 是谷歌官方出品的一个通过 DevTools 协议 控制 headless Chrome 的 Node 库。可以通过 Puppeteer 的提供的 api 直接控制 Chrome 模拟大部分用户操作来进行 UI Test 或者 作为 爬虫 访问页面 来 收集数据

​Puppeteer​​​(中文翻译”木偶”) 是 Google Chrome 团队官方的无界面(Headless)Chrome 工具,它是一个 ​​Node​​​ 库,提供了一个高级的 API 来控制 ​​DevTools协议上的无头版​​​ Chrome 。也可以配置为使用完整(非无头)的 Chrome。​​Chrome​​ 素来在浏览器界稳执牛耳,因此,Chrome Headless 必将成为 web 应用自动化测试的行业标杆。使用 ​​Puppeteer​​,相当于同时具有 Linux 和 Chrome 双端的操作能力,应用场景可谓非常之多。此仓库的建立,即是尝试各种折腾使用 GoogleChrome Puppeteer;以期在好玩的同时,学到更多有意思的操作。

 

 

Puppeteer 是什么,以及能做些什么

 

Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.

简而言之,这货是一个提供高级API的node库,能够通过devtool控制headless模式的chrome或者chromium,它可以在headless模式下模拟任何的人为操作。

 

你可以在浏览器中手动完成的大部分事情都可以使用 ​​Puppeteer​​ 完成!你可以从以下几个示例开始:

  • 生成页面的截图和PDF。
  • 抓取SPA并生成预先呈现的内容(即“SSR”)。
  • 从网站抓取你需要的内容。
  • 自动表单提交,UI测试,键盘输入等
  • 创建一个最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试。
  • 捕获您的网站的时间线跟踪,以帮助诊断性能问题。

总之:chrome 浏览器能干的事情 puppeteer 都能干。puppeteer 通俗来说就是一个 headless chrome浏览器 (当然你也可以配置成有UI的,默认是没有的)。既然是浏览器,那么我们手工可以在浏览器上做的事情 Puppeteer 都能胜任, 另外,Puppeteer 翻译成中文是”木偶”意思,所以听名字就知道,操纵起来很方便,你可以很方便的操纵她去实现:
1) 生成网页截图或者 PDF 
2) 高级爬虫,可以爬取大量异步渲染内容的网页 
3) 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试 
4) 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题如果你用过 PhantomJS 的话,你会发现她们有点类似,但Puppeteer是Chrome官方团队进行维护的,用俗话说就是”有娘家的人“,前景更好。

备注: 鉴于 ​​Puppeteer​​​ 需要 ​​Chromium​​​,但,即便处于 Science 上网的姿态, 也会遇到 Chromium 无法成功下载的问题;所以在最新的修改中,已经其替换为 ​​puppeteer-core​​​ (默认情况下不下载 Chromium,使用时需要确保您安装的 ​​puppeteer-core​​ 版本与您要连接的浏览器兼容)。在实际使用时候,即便已然按照说明操作,但依旧会报如下错误:

Error: Chromium revision is not downloaded. Run “npm install” or “yarn install”

因此只好采取手动下载 ​​Chromium​​​ 的方式解决;因此在运行此仓库时候,您需要在 ​​Puppeteer API Tip-Of-Tree​​​ 根据指定 Puppeteer 下载对应 Chromium,然后放置到项根目录即可(项目中已对各不同系统做了适配,国内用户可以在 ​​Taobao Mirrors​​ 根据系统按需下载)

 

 

Puppeteer 架构图

 

架构图:

puppeteer( Nodejs 版 selenium )快速入门_lua_02

 

  • Puppeteer 通过 devTools 与 browser 通信
  • Browser 一个可以拥有多个页面的浏览器(chroium)实例
  • Page 至少含有一个 Frame 的页面
  • Frame 至少还有一个用于执行 javascript 的执行环境,也可以拓展多个执行环境

 

 

 

环境和安装

 

Puppetee r本身依赖 6.4 以上的Node,但是为了异步超级好用的 ​​async/await​​,推荐使用7.6版本以上的Node。另外headless Chrome本身对服务器依赖的库的版本要求比较高,centos服务器依赖偏稳定,v6很难使用headless Chrome,提升依赖版本可能出现各种服务器问题(包括且不限于无法使用ssh),最好使用高版本服务器。

要在项目中使用 ​​Puppeteer​​​,只需要运行如下命令安装即可;不过要注意的是:​​Puppeteer​​ 至少需要 Node v6.4.0,如要使用 async / await,只有 Node v7.6.0 或更高版本才支持;另外,安装 ​​Puppeteer​​ 时,它会下载最新版本的 Chromium(〜71Mb Mac,〜90Mb Linux,〜110Mb Win),保证与 API 协同工作。

Puppeteer 因为是一个 npm 的包,所以安装很简单:npm i puppeteer    或者    yarn add puppeteer

Puppeteer 安装时自带一个最新版本的Chromium,可以通过设置环境变量或者 npm config 中的PUPPETEER_SKIP_CHROMIUM_DOWNLOAD 跳过下载。如果不下载的话,启动时可以通过 puppeteer.launch([options]) 配置项中的 executablePath 指定 Chromium 的位置。

 

 

Puppeteer 轻松入门

 

运行环境查看 Puppeteer 的官方 API 你会发现满屏的 async, await 之类,这些都是 ES7 的规范,所以你需要: Nodejs 的版本不能低于 v7.6.0, 需要支持 async, await.
需要最新的 chrome driver,

基本用法先开看看官方的入门的 DEMO

const puppeteer = require('puppeteer'); 

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

上面这段代码就实现了网页截图,先大概解读一下上面几行代码: 

  • 1. 先通过 puppeteer.launch() 创建一个浏览器实例 Browser 对象
  • 2. 然后通过 Browser 对象创建页面 Page 对象
  • 3. 然后 page.goto() 跳转到指定的页面
  • 4. 调用 page.screenshot() 对页面进行截图

下面就介绍一下 puppeteer 的常用的几个 API。

 

 

 

示例 1

Puppeteer 类似其他框架,通过操作 Browser 实例 来操作浏览器作出相应的反应。

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://rennaiqian.com');
await page.screenshot({path: 'example.png'});
await page.pdf({path: 'example.pdf', format: 'A4'});
await browser.close();
})();

上述代码通过puppeteer的launch方法生成了一个browser的实例,对应于浏览器,launch方法可以传入配置项,比较有用的是在本地调试时传入{headless:false}可以关闭headless模式。

const browser = await puppeteer.launch({headless:false})

browser.newPage方法可以打开一个新选项卡并返回选项卡的实例page,通过page上的各种方法可以对页面进行常用操作。上述代码就进行了截屏和打印pdf的操作。

一个很强大的方法是 page.evaluate(pageFunction, ...args),可以向页面注入我们的函数,这样就有了无限可能。

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('http://rennaiqian.com');

// Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio
};
});

console.log('Dimensions:', dimensions);
await browser.close();
})();

需要注意的是evaluate方法中是无法直接使用外部的变量的,需要作为参数传入,想要获得执行的结果也需要return出来。因为是一个开源一个多月的项目,现在项目很活跃,所以使用时自行查找​​api​​才能保证参数、使用方法不会错。

 

示例 2

对于如何使用 ​​Puppeteer​​​,这非常之容易;如下简易的示例,即实现了:导航到 ​​https://example.com​​ 并将截屏保存为 example.png;

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch(); // 创建浏览器实例
const page = await browser.newPage(); // 创建新的浏览器页面
await page.goto('https://example.com'); // 页面访问地址 http://example.com
await page.screenshot({ path: 'example.png' }); // 页面截图 example.png

await browser.close(); // 关闭浏览器
})();

Puppeteer 设置浏览器页面为 800像素 x 600像素, 屏幕截图也依据这个大小. 如你需要调整页面大小,可以通过 ​​Page.setViewport()​​.

更多示例可参考 ​​GoogleChrome Puppeteer Usage​​​;在略为熟悉 ​​Puppeteer的 Api​​​ 之后,即可用来她操纵浏览器,来为你做些你想搞的事儿;不过值得一提的是,她现在还处于开发阶段,随着版本的更替,Api 接口也有可能会跟着略有变动。​​Toss Puppeteer​​,这是在 Github 创建的一个仓库,以承载尝试使用 GoogleChrome Puppeteer 做的各种的折腾,具体如下:

 

示例 3

举例 - 创建PDF.

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com', { waitUntil: 'networkidle2' });
await page.pdf({ path: 'hn.pdf', format: 'A4' });

await browser.close();
})();

上例中waitUntil表示等待的时长,参数定义在这里​​waitUntil​​ - 搜索waitUntil
​​​Page.pdf()​​ 访问这里有更多关于创建PDF的信息.

 

示例 4

举例 - 通过页面上下文 (context) 获取页面信息

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');

// Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => { // 通过evaluate执行页面js
return {
width: document.documentElement.clientWidth, // 页面宽度
height: document.documentElement.clientHeight, // 页面高度
deviceScaleFactor: window.devicePixelRatio // 设备像素比
};
});

console.log('Dimensions:', dimensions);

await browser.close();
})();

访问 ​​Page.evaluate()​​​ 获得更多关于 ​​evaluate​​​ 和相关功能例如 ​​evaluateOnNewDocument​​​and ​​exposeFunction​​的介绍。

 

 

调试技巧

 

  1. 显示界面 - 最直观的调试方法就是看到界面上发生了什么. 通过创建完整浏览器来实现,选项 ​​headless: false​​:

const browser = await puppeteer.launch({headless: false});

  1. 让执行慢下来 - ​​slowMo​​ 选项 可以指定毫秒值,让 Puppeteer 的执行慢下来 ,也对调试有帮助

const browser = await puppeteer.launch({
headless: false,
slowMo: 250 // slow down by 250ms
});

  1. 获取Console的输出 - 你既可以监听 ​​console​​​ 事件, 也可以通过 ​​page.evaluate()​​来打印。

page.on('console', msg => console.log('PAGE LOG:', ...msg.args));

await page.evaluate(() => console.log(`url is ${location.href}`));

  1. 启用详细日志 - 所有API调用和内部协议交互都会被记录在 ​​puppeteer​​​ 名字空间的 ​​debug​​ 模式下.

# 所有详细的日志
env DEBUG="puppeteer:*" node script.js

# 通过名字空间来控制调试日志的输出
env DEBUG="puppeteer:*,-puppeteer:protocol" node script.js # 除了protocol外的所有消息
env DEBUG="puppeteer:session" node script.js # 只需要protocol session 消息
env DEBUG="puppeteer:mouse,puppeteer:keyboard" node script.js # 只输出鼠标和键盘日志

# Protocol 的交互消息会很多. 这里的例子说明了如何过滤掉所有Netwok的消息。
env DEBUG="puppeteer:*" env DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

自定义运行的 Chromium

默认情况下, Puppeteer 会选择自行选择下载 Chromium 来确保其API 在当前环境下正常运行. 如果确认需要运行不同版本的 Chromium, 在创建浏览器的时候传入executablePath参数,值为目标浏览器的可执行路径:

const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});

 

 

额外的例子

 

这些例子从 ​​Issue​​ 页面归纳而来,如果有额外的需要请留言。

  1. 如何模拟页面点击?
    通过以下page的接口, 相关 ​​​issue​

page.mouseMoved(x, y, options = {})
page.mousePressed(x, y, options = {})
page.mouseReleased(x, y, options = {})
page.tap(x, y, options = {})
page.touchmove()
page.touchend()

  1. 如何上下翻动页面?
    通过调用page.evaluate中的 window.scrollBy来实现, 相关 ​​​issue​

page.evaluate(_ => { window.scrollBy(0, window.innerHeight);

  1. 避免页面ssl认证错误信息
    通过puppeteer option ​​​ignoredHTTPErrors​​ 实现
  2. page.evalute 能否返回page DOM?
    你可以传入 ObjectHandle到page.evaluate中成为DOM元素,但当DOM被返回的时候则成 为对应的 ObjectHandle. ​​​issue​​ 如果需要返回,也可以返回实际需要的值,例如:

const list = await page.evaluateHandle(() => {
return Array.from(document.getElementsByTagName('a')).map(a => a.href);
});
console.log(await list.jsonValue());

相关 ​​iusse​

  1. 如何读取和设置cookies?
    通过page.setCookie 和 page.cookies 接口。 目前有一些关于该功能的使用问题, 相关 ​​​issue​
  2. 如何上传文件?
    通过elementHandle.uploadFile(...filePaths) 接口。 目前只支持 input type="file" 类
    型的文件提交。 相关​​​issue​
  3. 如何获得页面html代码?
    通过 ​​​page.content()​
  4. 如何关闭javascript弹框
    通过 dialog.accept, 相关 ​​​issue​

page.on('dialog', dialog => {
dialog.accept('test');
});

  1. 如何监控页面的网络请求?

const page = await browser.newPage();
await page.setRequestInterceptionEnabled(true);

page.on('request', request => {
request.continue(); // pass it through.
});

page.on('response', response => {
const req = response.request();
console.log(req.method, response.status, req.url);
});

  1. 如何输入内容?
    方法1 page.type

// ...
await page.focus('#lst-ib')
page.type('China')
// ...

方法2 page.evaluate 后 element.value =

await page.evaluate((a, b) => {
document.querySelector('#a').value = a;
document.querySelector('#b').value = b;
document.querySelector('#c').click();
}, a, b);

  1. 如何在页面中不同的Frame中切换
    通过page.frames()获得frame的数组,使用 iframe.$ 来获得对应frame中的handle
    例如:

const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.setContent('<iframe></iframe>');

// the page.frames()[0] is always a main frame.
const iframe = page.frames()[1];
// fetch the body element of the iframe
const body = await iframe.$('body');
// ...
// do something with `body`..
// ...
browser.close();

  1. 获取element中的自定义属性值
    通过page.evaluate 然后使用object.getAttribute

await page.evaluate( (obj) => {
return obj.getAttribute('data-src');
}, imgurlEle);

 

 

 

爬虫实践

 

很多网页通过user-agent来判断设备,可以通过page.emulate(options)来进行模拟。options有两个配置项,一个为userAgent,另一个为viewport可以设置宽度(width)、高度(height)、屏幕缩放(deviceScaleFactor)、是否是移动端(isMobile)、有无touch事件(hasTouch)。

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];

puppeteer.launch().then(async browser => {
const page = await browser.newPage();
await page.emulate(iPhone);
await page.goto('https://www.example.com');
// other actions...
await browser.close();
});

上述代码则模拟了iPhone6访问某网站,其中devices是puppeteer内置的一些常见设备的模拟参数。

很多网页需要登录,有两种解决方案:

  1. 让puppeteer去输入账号密码
    常用方法:点击可以使用page.click(selector[, options])方法,也可以选择聚焦page.focus(selector)。
    输入可以使用page.type(selector, text[, options])输入指定的字符串,还可以在options中设置delay缓慢输入更像真人一些。也可以使用keyboard.down(key[, options])来一个字符一个字符的输入。
  2. 如果是通过cookie判断登录状态的可以通过page.setCookie(...cookies),想要维持cookie可以定时访问。

 

Tip:有些网站需要扫码,但是相同域名的其他网页却有登录,就可以尝试去可以登录的网页登录完利用cookie访问跳过扫码。

 

 

简单例子

 

示例代码:

const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
await page.goto('https://baidu.com');
await page.type('#kw', 'puppeteer', {delay: 100});
page.click('#su')
await page.waitFor(1000);
const targetLink = await page.evaluate(() => {
return [...document.querySelectorAll('.result a')].filter(item => {
return item.innerText && item.innerText.includes('Puppeteer的入门和实践')
}).toString()
});
await page.goto(targetLink);
await page.waitFor(1000);
browser.close();
})()

运行截图:

puppeteer( Nodejs 版 selenium )快速入门_Chrome_03

 

 

 

标签:const,Nodejs,await,selenium,Puppeteer,puppeteer,page,browser
From: https://blog.51cto.com/csnd/5956119

相关文章

  • Selenium2.0中文在线文档项目,求翻译达人
    前一阵子在学习selenium2.0,发现网上很多资料都是selenium1.0的且部分信息不准确,无奈只能去官方看英文文档。费劲巴拉的看完了后,就有想法把selenium2.0的文档进行中文翻译,并......
  • 【Selenium :3种等待方式详解】
    应用场景自动化打开一个网页的时候,内部网页元素加载完全有一点的延迟性,因此在做Web端的自动化测试的时候,一般都需要在测试case时加入一些等待操作。我们常用等待操作有......
  • 【Selenium : 文件操作】
    一、前言文件操作是Web端自动化中比较常用的一个操作,一般文件操作包含:上传、下载WebDriver仅仅提供了下载文件相关的API,上传文件的API并没实现,需要我们自己去实现;而且......
  • nodejs 调用adb拨号
      asyncfunctionexec(adbCmd:string){letadbPath='D:\\prog\\adb\\windows\\adb.exe'letcmdMsg=awaitnewPromise((resolve,reject)=>{cons......
  • nodejs读取excel
     //importpuppeteerfrom'puppeteer'//https://github.com/SheetJS/sheetjsimportreaderfrom'xlsx'constfile=reader.readFile('D:\\doc\\名单.xlsx',{c......
  • nodejs 拦截接口数据
     importpuppeteerfrom'puppeteer'constbrowser=awaitpuppeteer.launch({headless:false})constpage=awaitbrowser.newPage()awaitpage.setDe......
  • nodejs 执行sql
    importsqlfrom'mssql'asyncfunctionquery(sqlTxt:string){letconfig="Server=localhost,1433;Database=db1;UserId=sa;Password=sa;Trusted_Connection=T......
  • Java Selenium封装--RemoteWebElement
    packagecom.selenium.driver;importjava.sql.SQLException;importjava.util.List;importorg.json.JSONException;importorg.openqa.selenium.By;importorg.openqa.sel......
  • selenium webdriver的各种driver
    selenium官方加上第三方宣布支持的驱动有很多种;除了PC端的浏览器之外,还支持iphone、android的driver;大概记录一下selenium支持的各种driver的用途与说明。selenium可支持的P......
  • selenium之relative_locator相对定位
    relative_locator 是4.0后增加的一种定位方式(2021.10.13)相对定位提供了上下左右附近五种位置定位的方式工作中慎用!!!relative.pyfromseleniumimportwebdriverf......