puppeteer实现网页截图

上周接到接到一个需求,将某个页面整体截图,并定时发送邮件。

这里我将其拆解成三个大步骤:

1、实现页面整体截图

2、发送邮件

3、定时发送

本文主要记录实现截图过程中遇到的一些问题和整体复盘。

一、实现过程中遇到的问题

1、页面中存在竖向滚动,如何截全屏?

涉及知识点: puppeteer 模拟滚动

实现过程中参考了 Puppeteer前端检测最佳实践 - 知乎 这篇回答中的答案。

前期尝试 通过配置 fullPage 为 true, 结果发现没有成功。

  await page.screenshot({path: 'pics/demo1.png', fullPage: true});

后来发现,设置的视口高度要和全屏高度一致。 而想要得到全屏高度,则需要找到页面中的滚动元素,得到其滚动高度。

在参考文中,使用了计算的方式找到滚动元素,而在我们项目中,滚动元素是固定的,因此,直接计算滚动元素高度即可。

/** 获取无头浏览器打开页面的 某dom 高度 */
export const calHeight = async (page: any, dom: string) => {
  const scrollHeight = await page.$eval(dom, el => el.scrollHeight);
  return scrollHeight;
};

在获得滚动高度后,还有仍需注意的一点。这里只是滚动高度,全局是大于滚动高度的。

在这里插入图片描述

如上图所示,puppeteer的视口是从页面左上角开始计算的,而一般情况下,页面的滚动都是内容区滚动,上面置顶。

因此,需要将viewPort的height 计算为 滚动部分高度+ 固定部分高度。截图可以选择只截滚动内容。只需要设置clip 中的 x 和 y 即可。

这部分的核心代码如下:

// 引入puppeteer设置
const puppeteer = require('puppeteer');
// 启动浏览器
const browser = await puppeteer.launch();
//创建新页面
const page = await browser.newPage();
// 设置cookies
cookies && await page.setCookie(...cookies);
// 跳转url
  const response = await page.goto(url, {
    waitUntil: 'networkidle0',
    timeout: timeout || 120000
  });
// 设置视口高度
await page.setViewport({ width, height: height + y + 20 });
// 设置截图位置
await page.screenshot({ path: shotPath, clip: { x, y, height: height, width: width }, });

2、页面中局部存在横向滚动,如何实现截全屏?

解决了竖向的滚动问题,但是,在页面中,是仍然存在局部滚动。

请添加图片描述
如上图所示,因页面中存在表格,表格内是存在局部滚动的。这种情况下,我在控制台找到了可以获得实际表格宽度的元素。而每个表格中都有这个元素,就可以在找到所有表格宽度后,取最大值。这样就可以截取整屏宽度啦。

/** 获取无头浏览器打开页面的 某dom 宽度 */
export const calWidth = async (page: any, dom: string) => {
  let maxWidth = 0;
  const width = await page.$$eval(dom, el => el.map(e => e.clientWidth));
  width.forEach(w => maxWidth = w > maxWidth ? w : maxWidth);
  return maxWidth;
};

3、页面中局部存在竖向滚动,如何实现截全屏?

局部竖向滚动指的表格的竖向滚动,这是因为开发表格组件过程中,固定了表格组件的高度。

因此,在渲染的时候,只需要更改表格高度即可。 于是,问题就变成了,

如何通过url传递参数,改变页面渲染?

1、取到url中的参数

2、改变表格高度

项目中使用的vue框架,vue 获取url 参数的方式是:

  /** 事件ID */
  get urlTableHeight () {
    const height = this.$route.query.tableHeight as string;
    return height ? parseInt(height) : '';
  }

而改变表格高度通过组件传参完成。

4、截图的时候,如何保证页面中所有数据已经加载完成?

因为页面存在加载时长和懒加载等问题,必须保证,页面中所有数据均已加载完成才能进行截图。

通过两步来实现:

① 跳转url的时候,添加 waitUntil:‘networkkidle0’ 的参数。networkkidle0 的意思是 在 500ms 内没有网络连接时就算成功(全部的request结束),才认为导航结束。

② 由于我们的这个数据实在太多了,可能在限定时间内依然没有加载完,因此,又使用了pendingXHR 来进行双重保障。

最终代码为:

/** 获取具体的页面响应 */
export const getPageResponse = async (url: string, _page?: any, timeout?: number, waitXhrAll = true, cookies?: Array<{ name: string, value: string, domain: string }>) => {
  let pendingXHR;
  const page = _page || await getBrowserPage(cookies);
  if (!page) return null;

  if (waitXhrAll) {
    pendingXHR = new PendingXHR(page);
  }

  const response = await page.goto(url, {
    waitUntil: 'networkidle0',
    timeout: timeout || 120000
  });

  if (response.status() !== 200) {
    logger(`跳转到${url}失败`, 'error');
    return null;
  }

  // 等当前的xhr请求都返回
  waitXhrAll && await pendingXHR.waitForAllXhrFinished();

  return response;
};

二、整体复盘

1、代码结构

在review过程中,组长告诉我,虽然完成了截图功能的开发,但是整体代码没有复用性,排查问题也比较困难。

整个截图过程是主要包括如下几个事情的:

① 创建页面

② 获取页面内容

③ 截图

而最开始,我是把这些代码全部写在了一个函数中,虽然后期的确是复用这个大函数完成,但是这些代码全部融在一个函数中,即难阅读,也难以排查问题。

最好的办法是将其进行函数拆分。

函数拆分过程中,一个技巧就是,要注意函数的命名,入参,出参。

通过函数命名就能知道,这个函数做了什么。 通过入参的命名知道需要传递什么参数,通过出参明确函数返回什么。

2、异常处理

还有一个问题就是,在开发过程中,不注意异常处理。

前端代码中,往往都是业务代码,并且排查可以通过界面排查,但是后端代码,感觉需要详细的异常处理,不然很难排查问题。

那么,问题就来了,什么时候需要抛出异常呢?

需要抛出异常的三种情况:

①不可控因素 ②不可完全预测异常

①② 常出现在调用第三方库的时候

③ 希望带上异常调用栈

错误日志记录

常常在业务代码使用,譬如在定义post接口的返回的时候,返回为 {data: any, error: Error | null})。

在明确下层调用者的情况下,返回明确的错误,能降低理解成本。

在不明确调用者的情况下,譬如多数框架,均是向上抛出异常。


明确的返回,是错误;异常处理的返回结果;
异常,就是未知的

三、参考链接

1、puppeteer api文档:https://zhaoqize.github.io/puppeteer-api-zh_CN/#?product=Puppeteer&version=v14.4.1&show=api-overview​​​​​​​

2、获取元素宽高:css宽高

3、 url传参:Vue 路由组件传参的 8 种方式 - SegmentFault 思否

4、滚动问题:Puppeteer前端检测最佳实践 - 知乎

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实现网页的自动化测试,可以采用以下步骤: 1.选择适合的测试框架:根据自己的需求和技术水平,选择适合自己的测试框架,比如Selenium、Puppeteer、Playwright等。 2.安装测试工具:根据选择的测试框架,安装相应的测试工具和依赖,如webdriver、Chrome或Firefox浏览器驱动等。 3.编写测试脚本:使用编程语言编写测试脚本,包括测试用例、测试数据和断言。测试脚本可以通过模拟用户交互操作来验证网页功能的正确性。 4.运行测试:将测试脚本运行起来,测试工具会模拟用户的操作来执行测试用例,并对网页进行自动化测试。 5.分析测试结果:对测试结果进行分析和归档,以便及时发现问题并进行修复。 总之,网页自动化测试可以提高测试效率和测试质量,减少手动测试的工作量和人为错误。 ### 回答2: 网页自动化测试是指利用自动化工具和技术对网页进行自动化测试,以验证网页的功能和性能。下面是实现网页自动化测试的步骤: 1. 定义测试用例:根据需求和功能,确定要测试的目标和步骤,并编写测试用例。 2. 选择自动化测试工具:根据需要选择合适的自动化测试工具,如Selenium、Cypress等。 3. 编写测试脚本:使用选择的自动化测试工具,根据测试用例编写测试脚本。测试脚本可以使用多种编程语言来实现,如Java、Python等。 4. 配置测试环境:设置测试环境,包括浏览器版本、操作系统等。 5. 运行测试脚本:执行编写好的测试脚本,进行网页自动化测试。测试脚本会模拟用户在浏览器中的操作,如点击、输入文本等。 6. 验证测试结果:根据预期结果,对比实际结果,判断测试是否通过。如果测试不通过,可以根据日志或错误信息进行问题定位。 7. 输出测试报告:生成测试报告,记录测试的结果、错误和其他指标,以便分析和改进。 8. 执行持续集成:将网页自动化测试集成到持续集成流程中,提高测试效率和质量。可以通过Jenkins等工具实现持续集成。 总结起来,实现网页的自动化测试需要明确测试目标、选择合适的自动化测试工具,编写测试脚本,配置测试环境,执行测试脚本,验证测试结果,并生成测试报告。通过持续集成,可以实现自动化测试的自动执行。 ### 回答3: 网页的自动化测试是指通过使用自动化工具或脚本,对网页的功能、性能、用户体验等进行自动化测试。实现网页的自动化测试主要包括以下几个步骤: 1. 确定测试需求:根据项目需求和功能模块划分,确定需要进行自动化测试的主要功能和场景。 2. 选择自动化测试工具:根据项目的特点和测试需求,选择适合的自动化测试工具。常用的工具包括Selenium、Junit、TestNG等,可以根据项目需求选择合适的工具。 3. 编写测试脚本:根据测试需求和选定的自动化测试工具,编写相应的测试脚本。测试脚本应包含测试用例的输入数据、预期结果以及相关的操作步骤。 4. 配置测试环境:为了有效地进行自动化测试,需要搭建相应的测试环境。包括安装配置自动化测试工具、浏览器驱动等。 5. 执行测试脚本:根据测试需求,执行编写好的测试脚本。可以通过命令行或测试框架来执行脚本,检查测试结果是否与预期一致。 6. 分析测试结果:根据测试执行结果,对错误或异常进行分析和定位。可以通过测试报告、日志等方式来查看测试结果。如果有错误或异常,需要进行修复或重新执行测试。 7. 集成到自动化测试平台:如果项目需要长期的自动化测试,可以将自动化测试脚本集成到自动化测试平台中,实现自动化测试任务的调度、管理和监控。 总结而言,实现网页的自动化测试需要明确测试需求、选择合适的自动化测试工具、编写测试脚本、搭建测试环境等。通过执行测试脚本、分析测试结果,并将自动化测试融入到自动化测试平台中,可以提高测试效率和质量,同时节省人力成本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值