使用PuppeteerSharp实现后台页面截图
1. 前言
最新在项目中遇到了一个在后台自动给页面截图的需求, 由于项目是基于.NET Core的, 最后使用PuppeteerSharp实现了该功能。
2. 什么是PuppeteerSharp
2.1 Puppeteer
Puppeteer是一个Node库,它提供了高级API来通过DevTools协议控制Chrome或Chromium 。Puppeteer默认情况下无头运行,但可以配置为运行完整(无头)的Chrome或Chromium。
Github: https://github.com/puppeteer/puppeteer
2.2 PuppeteerSharp
Puppeteer Sharp是Puppeteer的.NET 移植, 是一个NetStandard 2.0库,最低支持的平台版本是.NET Framework 4.6.1和.NET Core 2.0。
Github: https://github.com/hardkoded/puppeteer-sharp
2.3 实现的功能
您可以在浏览器中手动执行的大多数操作都可以使用Puppeteer或PuppeteerSharp完成!
- 生成页面的屏幕截图和PDF。
- 爬取SPA(单页应用程序)并生成预渲染的内容(即“ SSR”(服务器端渲染))。
- 自动进行表单提交,UI测试,键盘输入等。
- 创建最新的自动化测试环境。使用最新的JavaScript和浏览器功能,直接在最新版本的Chrome中运行测试。
- 捕获站点的时间线跟踪,以帮助诊断性能问题。
- 测试Chrome扩展程序。
3. 如何使用
3.1 安装SDK包
dotnet add package PuppeteerSharp
3.2 引用命名空间
using PuppeteerSharp;
3.3 代码
/// <summary>
/// 页面截图
/// </summary>
/// <param name="outputFile">图片保存的物理路径</param>
/// <param name="pageUrl">需要截图的页面地址</param>
/// <param name="width">页面宽度</param>
/// <param name="height">页面高度</param>
/// <param name="sleepTime">等待页面打开的时间, 单位毫秒</param>
/// <param name="executablePath">Chrome安装路径</param>
/// <param name="isNeedDownload">是否需要下载Chromium</param>
/// <returns></returns>
public static async Task GetScreenShot(string outputFile, string pageUrl, int width = 0, int height = 0, int sleepTime = 0, string executablePath = "", bool isNeedDownload = false)
{
if (isNeedDownload)
{
var result = await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);
}
var launchOptions = new LaunchOptions()
{
Headless = true
};
if(!string.IsNullOrEmpty(executablePath))
{
//@"C:\Program Files\Google\Chrome\Application\chrome.exe"
launchOptions.ExecutablePath = executablePath;
}
using (Browser browser = await Puppeteer.LaunchAsync(launchOptions))
{
try
{
using (var page = await browser.NewPageAsync())
{
if (width > 0 && height > 0)
{
await page.SetViewportAsync(new ViewPortOptions
{
Width = width,
Height = height
});
}
if (sleepTime > 0)
{
//超时时间比等待时间多加几秒
await page.GoToAsync(pageUrl, 0);
System.Threading.Thread.Sleep(sleepTime);
}
else
{
var navOptions = new NavigationOptions
{
WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
};
await page.GoToAsync(pageUrl, navOptions);
}
//将页面保存为图片
await page.ScreenshotAsync(outputFile, new ScreenshotOptions() { FullPage = true, Type = ScreenshotType.Png });
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (!browser.IsClosed)
{
await browser.CloseAsync();
}
}
}
}
PuppeteerSharp可以Headless的方式打开服务器上已经安装的Chrome, 也可以在第一次运行的时候下载Chromium, 一般建议现在服务器上安装Chrome, 因为自动下载Chromium的地址是被屏蔽的。
另外,我在这里使用sleepTime的原因是,我的页面是一致在后台调用接口刷新的, 所以PuppeteerSharp无法判断页面已经加载完成, 正常情况下可以不使用这个参数。
最后,尽量即时的调用browser.CloseAsync(), 否则在服务器上会发现Chrome进程会越来越多。
4. 遇到的异常
博主基于BackgroundService实现了后台服务, 托管在IIS中, 最后发布到服务器端的时候, 出现了异常: System.IO.FileNotFoundException: Failed to launch browser! path to executable does not exist
最后的解决方案是,使用WorkerService实现了Window服务,运行起来就OK了。