PuppeteerSharp是一个基于.NET的库,提供了对Puppeteer的C#支持,用于自动化,可用于测试、截图、爬虫等任务。
官网:Puppeteer Sharp(感觉文章中有些代码段没有更新,直接用会有报错)。
本篇文章是对HTML截图的实现,无需在页面或容器中展示html中的实际内容。请前往NuGet中自行下载PuppeteerSharp库(本次演示用的是20.0.5版本),并在代码中引用。
//razor中使用
@using PuppeteerSharp
@using PuppeteerSharp.Media
或
//cs中使用
using PuppeteerSharp;
using PuppeteerSharp.Media;
注意PuppeteerSharp库20.0.5版本的依赖性:
1、razor添加一个截图按钮
<Button OnClick="OnClickToTakeAnScreenshot">截图</Button>
如果需要加载展示html的内容,可以使用iframe:
<iframe id="iframeHtml" src="./files/xxx.html" style="width:100%;height:100%;"></iframe>
2、注入IWebHostEnvironment和DownloadService
//用于找WebRootPath
[Inject]
[NotNull]
private IWebHostEnvironment _env { get; set; }
//用于下载截取后的图片
[Inject]
[NotNull]
private DownloadService _downloadService { get; set; }
3、生成HTML文件路径和截图后图片存放路径
//files在wwwroot目录下面
string htmlPath = Path.Combine(_env.WebRootPath, "files/xxx.html");
string imagePath = Path.Combine(_env.WebRootPath, "files/screenshot.png");
4、下载和管理浏览器的可执行文件
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
DownloadAsync方法默认下载Chrome浏览器的可执行文件,并且会校验目标文件是否存在,如果存在则不会重新下载,下载并解压成功后,会自动创建两个目录:
由于存在网络问题,下载失败后,可以多尝试几次。
5、创建无头浏览器和page实例
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true //无头浏览器配置
});
var page = await browser.NewPageAsync();
6、读取和加载HTML文件
await page.GoToAsync(htmlPath);
//等待几秒,确保html中的内容加载完毕
Thread.Sleep(3000);
await等待GoToAsync方法只是让html文件读取完,但是里面的数据填充、渲染等还另外需要时间,最好等待几秒(根据html文件大小自行计算),让里面的内容加载完成,再进行后面的操作,否则截的图会有内容缺失。
7、开启视窗模式(如有需要,可自行添加和修改)
await page.SetViewportAsync(new ViewPortOptions
{
Width = 1000,
Height = 800
});
需要设置视窗的宽度和高度,相当于限定了加载html的父容器尺寸,转为特定宽高。如果没有这段代码,默认是全屏。
8、截取特定的区域(如有需要,可自行添加和修改)
// 定义要截取的区域
var clip = new Clip
{
X = 150, // 截图区域的左上角 X 坐标
Y = 150, // 截图区域的左上角 Y 坐标
Width = 500, // 截图区域的宽度
Height = 350 // 截图区域的高度
};
9、截取并保存
await page.ScreenshotAsync(imagePath, new ScreenshotOptions
{
Clip = clip
});
10、下载截取的图片
await using var stream = File.OpenRead(imagePath);
DownloadOption downloadOption = new DownloadOption();
downloadOption.FileName = Path.GetFileName(imagePath);
downloadOption.FileStream = stream;
await _downloadService.DownloadFromStreamAsync(downloadOption);
截图按钮OnClickToTakeAnScreenshot的完整方法代码如下:
@using PuppeteerSharp
@using PuppeteerSharp.Media
<div>
<Button OnClick="OnClickToTakeAnScreenshot">截图</Button>
</div>
@code {
[Inject]
[NotNull]
protected IWebHostEnvironment _env { get; set; }
[Inject]
[NotNull]
protected DownloadService _downloadService { get; set; }
private async Task OnClickToTakeAnScreenshot()
{
try
{
string htmlPath = Path.Combine(_env.WebRootPath, "files/xxx.html");
string imagePath = Path.Combine(_env.WebRootPath, "files/screenshot.png");
var browserFetcher = new BrowserFetcher();
await browserFetcher.DownloadAsync();
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true
});
var page = await browser.NewPageAsync();
await page.GoToAsync(htmlPath);
Thread.Sleep(3000);
await page.SetViewportAsync(new ViewPortOptions
{
Width = 1000,
Height = 800
});
// 定义要截取的区域
var clip = new Clip
{
X = 150, // 截图区域的左上角 X 坐标
Y = 150, // 截图区域的左上角 Y 坐标
Width = 500, // 截图区域的宽度
Height = 350 // 截图区域的高度
};
await page.ScreenshotAsync(imagePath, new ScreenshotOptions
{
Clip = clip
});
await using var stream = File.OpenRead(imagePath);
DownloadOption downloadOption = new DownloadOption();
downloadOption.FileName = Path.GetFileName(imagePath);
downloadOption.FileStream = stream;
await _downloadService.DownloadFromStreamAsync(downloadOption);
_MsgBox.Show("截图成功!", AlertTypes.Success);
}
catch (Exception ex)
{
_MsgBox.Show(ex.Message, AlertTypes.Error);
}
}
}