欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Puppeteer使用

时间:2023-05-27
Puppeteer 概念:

headless browser(无头浏览器):

是一种在无界面的环境中运行浏览器,与正常浏览器的区别

直接通过命令行或者程序语言操作没有界面,少了加载 css/js、渲染页面的工作,比真实浏览器更快,更稳定

Puppeteer: 是 Chrome 开发团队在 2017 年发布的一个 Node.js 包,用来模拟 Chrome 浏览器的运行

Selenium: 2004年就发布了,支持多种浏览器,多编程语言

Puppeteer & Selenium 对比

功能:

网页截图或者生成 PDF爬取 SPA 或 SSR 网站UI 自动化测试,模拟表单提交,键盘输入,点击等行为捕获网站的时间线,帮助诊断性能问题创建一个最新的自动化测试环境,使用最新的 js 和最新的 Chrome 浏览器运行测试用例测试 Chrome 扩展程序 实例:

截图 或 生成PDF。

const puppeteer = require('puppeteer');(async () => { // 生成browser实例 const browser = await puppeteer.launch(); // 调出界面配置 // const browserConfig = { // headless: false // }; // const browser = await puppeteer.launch(browserConfig); // 解析一个新的页面。页面是在默认浏览器上下文创建的 const page = await browser.newPage(); await page.setViewport({ width: 1000, height: 500 }); await page.goto('https://www.jianshu.com/p/c269277ca2d4'); // 生成图片 await page.screenshot({ path: 'images/example.png' }); // 生成pdf await page.pdf({ path: 'page.pdf' }); // 截全屏 await page.screenshot({ path: 'images/homepage.png', fullPage: true }) // 截取对应选择器部分 await page.goto('https://www.baidu.com'); let clip = await page.evaluate(() => { let { x, y, width, height } = document.getElementById('form').getBoundingClientRect(); return { x, y, width, height }; }); await page.screenshot({ path: 'images/baidu.png', clip: clip //设置clip 属性 }); await browser.close();})();

生成页面 或 爬虫

// 生成页面const Koa = require('koa');const fs = require('fs');const puppeteer = require('puppeteer');const app = new Koa();const baseUrl = 'http://www.baidu.com';//这里是真实SPA页面的地址app.use(async (ctx, next) => { let browser = await puppeteer.launch({ dumpio: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], timeout: 10000 }); const page = await browser.newPage(); try { let myUrl = baseUrl + ctx.url; await page.goto(myUrl); //到指定页面的网址. await page.waitFor(5000); } catch (err) { await page.close(); await browser.disconnect(); console.log('出现错误:' + err); // 这里捕捉到错误 `error` } let html = await page.content() ctx.type = "text/html;charset=utf-8"; ctx.body = html.replace('', 'Puppeteer test'); await page.close(); await browser.close();});app.listen('3388');console.log('3388端口爬虫代理程序已启动');

const puppeteer = require("puppeteer");const fs = require("fs");const path = require("path");const getNewList = async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("http://news.baidu.com/"); //等待“国内”导航按钮出现 await page.waitForSelector("#channel-all > div > ul > li:nth-child(3) > a"); //点击“国内”导航按钮,进入国内新闻页面 await page.click("#channel-all > div > ul > li:nth-child(3) > a"); //等待“即时新闻列表”出现 await page.waitForSelector("#instant-news > ul"); //通过evaluate函数执行自定义的js代码获取要爬取的数据 const newList = await page.evaluate(() => { //创建一个空数组接收爬取的数据 let data = []; //获取所有即时新闻列表li元素 const elements = document.querySelectorAll("#instant-news > ul > li"); //利用循环将即时新闻列表的标题和链接地址添加到一个数组中 for (let i = 0; i < elements.length; i++) { //获取新闻的标签 let title = elements[i].innerText; //获取新闻的链接地址 let url = elements[i].firstChild.getAttribute('href'); //将获取到的标题和链接地址添加到数组中 data.push({ title, url }); } //返回数组 return data; }); //关闭浏览器实例 await browser.close(); //返回爬取的数据 return newList;}//执行函数获取爬取的数据getNewList().then(res => { //将爬取的数据转为json格式 let list = JSON.stringify(res); //指定存储数据的json文件 let file = path.join(__dirname, "newList.json"); //将爬取的数据写入json文件 fs.writeFile(file, list, err => { if (err) { console.log(err); } else { console.log("success"); } })})

自动提交表单,进行 UI 测试,键盘输入等。

const puppeteer = require("puppeteer");(async () => { const browser = await puppeteer.launch({ slowMo: 100, //放慢速度 headless: false, defaultViewport: { width: 1440, height: 780 }, ignoreHTTPSErrors: false, //忽略 https 报错 args: ['--start-fullscreen'] //全屏打开页面 }); const page = await browser.newPage(); await page.goto('https://www.baidu.com'); const element = await page.$('#kw'); await element.type('Puppeteer', { delay: 20 }); const okButtonElement = await page.$('#su'); //等待页面跳转完成,一般点击某个按钮需要跳转时,都需要等待 page.waitForNavigation() 执行完毕才表示跳转成功 await Promise.all([ okButtonElement.click(), page.waitForNavigation() ]); // await page.close(); // await browser.close();})();

拦截请求

const puppeteer = require("puppeteer");(async () => { const browser = await puppeteer.launch({ headless: false, }); 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://www.baidu.com');})();

注入脚本

const puppeteer = require('puppeteer');(async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('https://www.baidu.com'); await page.addscriptTag({ url: 'https://code.jquery.com/jquery-3.2.1.min.js' }); // await page.close(); // await browser.close();})();

捕获网站的 timeline trace,用来帮助分析性能问题。

const puppeteer = require('puppeteer');(async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 开始跟踪 await page.tracing.start({ path: 'trace.json' }); await page.goto('https://www.baidu.com'); await page.waitForSelector('title'); // 结束跟踪 await page.tracing.stop(); // 各种加载时间 const loadMetrics = await page.evaluate(() => JSON.stringify(window.performance)); console.info(JSON.parse(loadMetrics)); // 运行时间 Performance.getMetrics const metrics = await page.metrics(); console.info('运行时间>>>', metrics); await browser.close();})();

跟踪文件可以在 chrome://tracing 中打开分析

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。