c# - puppeteer 师夏普 : Multiple Browsers Concurrently

标签 c# puppeteer 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));
    }
}

附带说明:如果您的计算机上安装了 Chromium(可以是 Chrome、Chromium 或新的 Edge),您也不需要使用 GetBrowser()。然后你可以直接指向上面代码中显示的.exe。

关于c# - puppeteer 师夏普 : Multiple Browsers Concurrently,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63258421/

相关文章:

javascript - PUPPETEER - 无法使用 page.evaluate(() => document.querySelectorAll()) 提取某些网站上的元素

html - 用 chrome 打印时,带有 thead 和 tfoot 的表格布局不正确

c# - Web API Controller 返回任务并不总是等待任务完成(puppeteer-sharp)

c# - puppeteer 师 C# : Connecting to Running Chrome Instance

c# - ChildWindow (Silverlight) 设计问题标题上的按钮

c# - 当我不知道我使用什么类时如何反序列化 json 数组?

c# - 鉴于 doubles 不能用于 volatile 字段,这是一个安全的选择吗?

c# - 如何从 MySql 工作台获取 MySql DB 连接信息?

javascript - 如何渲染JS为cookie生成指纹?

c# - 在 PuppeteerSharp 中取消下载