c# - Puppeteer Sharp:同时使用多个浏览器
问题描述
现在我正在使用 puppeteer(NodeJS 库)将 HTML 转换为 PDF 文档。虽然这是“工作”,但我正在移植到 Puppeteer-Sharp(C# 库)。
我一切正常,但我有点担心同时运行多个浏览器。
例如,我在同一台机器上的两个不同进程中运行相同的代码:
// Magic function. Downloads Chrome to a specific directory for the process.
var browser = GetBrowser();
var page = await browser.NewPageAsync();
await page.GoToAsync("http://www.google.com");
var pdf = await page.PdfAsync();
我的问题:
这里有潜在的并发问题吗?
我的(有限)理解是该库使用 websockets 向 Chrome 发出指令,我不确定浏览器是否有可能相互“碰撞”。
本质上,我在问是否有可能接收到的 PDF 字节(通过await page.PdfAsync();
)将来自“其他”浏览器。
如果有什么安慰的话,浏览器是从每个进程的特定目录下载和启动的,所以从技术上讲,它不是 Chrome 的“相同”实例被启动两次(但它确实是)。
解决方案
您不需要多个浏览器,您可以使用带有多个选项卡(或 Puppeteer 所称的页面)的一个浏览器。这是我的示例代码,它解决了您所做的相同事情(将 HTML 转换为 PDF)。它创建一个浏览器实例,该实例被传递给四个进程(可能更多),每个进程都创建和删除自己的页面。
public class PuppeteerSharpSample {
public async Task CreatePdfBatch(IEnumerable<string> urlList)
{
await using var browser = await Puppeteer.LaunchAsync( new LaunchOptions { Headless = true, ExecutablePath ="PathToChromeOrChromium.exe"};).ConfigureAwait(false);
await urlList.ForEachAsync(4, async url =>
{
await PrintPdf(url, browser).ConfigureAwait(false);
})
.ContinueWith(t =>
{
if (t.Exception != null)
{
throw t.Exception;
}
})
.ConfigureAwait(false);
}
private async Task PrintPdf(Browser browser, string Url)
{
await using var page = await browser.NewPageAsync().ConfigureAwait(false);
await page.GoToAsync(url).ConfigureAwait(false);
await page.PdfAsync("pdfFileNameMustBeMadeUniqueOfCourse.pdf").ConfigureAwait(false);
}
}
public static class HelperClass
{
//taken from https://scatteredcode.net/parallel-foreach-async-in-c/
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
async Task AwaitPartition(IEnumerator<T> partition)
{
using (partition)
{
while (partition.MoveNext())
{
await body(partition.Current).ContinueWith(t =>
{
if (t.IsFaulted && t.Exception != null)
{
throw t.Exception;
}
})
.ConfigureAwait(false);
}
}
}
return Task.WhenAll(
Partitioner
.Create(source)
.GetPartitions(dop)
.AsParallel()
.Select(AwaitPartition));
}
}
GetBrowser()
附带说明:如果您的机器上安装了 Chromium(可以是 Chrome、Chromium 或新的 Edge),您也不需要使用。然后你可以只指向 .exe,如上面的代码所示。
推荐阅读
- centos7 - 如何从 CLI 检查 MOBO 是否支持 WOL?
- react-native - 将本机帖子反应到快递服务器时可能出现未处理的承诺拒绝
- batch-file - 如何使用批处理读取从串口接收到的数据?
- c++ - 从文件 C++ 中删除一行
- django - 找不到 Django 项目页面
- jquery - 使用多选下拉菜单进行多选过滤 - jQuery
- sql - 在 VBA 中运行时 SQL 查询未显示所有结果
- javascript - 用户关闭网页时如何删除链接颜色的本地存储
- sql - 尝试使用 LAG 计算行之间的百分比变化
- laravel - 如何使用foreach循环在laravel控制器返回值中按姓氏排序