public class PuppeteerSharpHelps
{
public PuppeteerSharpHelps()
{
}
private static PuppeteerSharp.Browser _browser { get; set; }
/// <summary>
/// 截图完成回调
/// </summary>
public static event EventHandler ScreenshotComplete;
/// <summary>
/// 截图出错回调
/// </summary>
public static event EventHandler ScreenshotError;
private async static Task<Browser> Browsers()
{
try
{
await slimLock.WaitAsync();
var result = await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
if (_browser == null)
{
Debug.WriteLine("标识输出");
_browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new string[] {
"--disable-infobars",//隐藏 自动化标题
"--no-sandbox", // 沙盒模式
},
});
return _browser;
}
return _browser;
}
catch (Exception ex)
{
throw ex;
}
finally
{
slimLock.Release();
}
}
//异步线程锁
private static SemaphoreSlim slimLock = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim _mutex = new SemaphoreSlim(10);
public static async Task ScreenshotAsync(string loadUrl, string savePath, int width = 0, int height = 0)
{
try
{
_browser ??= await Browsers();
await _mutex.WaitAsync();
if (width == 0 || height == 0)
{
await BrowsersPage(loadUrl, savePath);
}
else
{
await BrowsersPage(loadUrl, savePath, width, height);
}
}
catch (Exception ex)
{
await _browser?.CloseAsync();
_browser = null;
GC.Collect();
throw ex;
}
finally
{
_mutex.Release();
GC.Collect();
}
}
private static async Task BrowsersPage(string loadUrl, string savePath)
{
Page page = await _browser.NewPageAsync();
page.Load += async (sender, e) =>
{
try
{
var load = (Page)sender;
await page.ScreenshotAsync(savePath, new ScreenshotOptions() { Type = ScreenshotType.Png });
ScreenshotComplete(savePath, new ScreenshotEventArgs() { IsScreenshot = true, SavePath = savePath });
await page.CloseAsync();
}
catch (Exception ex)
{
ScreenshotError(savePath, new ScreenshotErrorEventArgs() { Error = ex, IsScreenshot = false, SavePath = savePath });
}
};
await page.SetViewportAsync(new ViewPortOptions
{
Width = 1000,
Height = 1000
});
var text = await page.GoToAsync(loadUrl);
page.Close += async (sender, e) =>
{
var pg = (Page)sender;
var size = await pg.Browser.PagesAsync();
if (size.Length <= 1)
{
//_browser?.CloseAsync();
await _browser.DisposeAsync();
_browser = null;
}
};
}
private static async Task BrowsersPage(string loadUrl, string savePath, int width, int height)
{
Page page = await _browser.NewPageAsync();
page.Load += async (sender, e) =>
{
try
{
var load = (Page)sender;
await page.ScreenshotAsync(savePath, new ScreenshotOptions() { Type = ScreenshotType.Png });
ScreenshotComplete(savePath, new ScreenshotEventArgs() { IsScreenshot = true, SavePath = savePath });
await page.CloseAsync();
}
catch (Exception ex)
{
ScreenshotError(savePath, new ScreenshotErrorEventArgs() { Error = ex, IsScreenshot = false, SavePath = savePath });
}
};
await page.SetViewportAsync(new ViewPortOptions
{
Width = width,
Height = height
});
await page.GoToAsync(loadUrl);
page.Close += async (sender, e) =>
{
var pg = (Page)sender;
var size = await pg.Browser.PagesAsync();
if (size.Length <= 1)
{
await _browser.DisposeAsync();
_browser = null;
}
};
}
}
public class ScreenshotEventArgs : EventArgs
{
/// <summary>
/// 截图成功为true
/// </summary>
public bool IsScreenshot { get; set; }
/// <summary>
/// 截图保存的路径
/// </summary>
public string SavePath { get; set; }
}
public class ScreenshotErrorEventArgs : EventArgs
{
/// <summary>
/// 截图成功为true
/// </summary>
public bool IsScreenshot { get; set; }
/// <summary>
/// 截图保存的路径
/// </summary>
public string SavePath { get; set; }
/// <summary>
/// 出错内容
/// </summary>
public object Error { get; set; }
}
测试代码:
for (int i = 1; i <= 50; i++) { if ((i % 2) == 0) { PuppeteerSharpHelps.ScreenshotAsync("https://www.baidu.com", $"F://test{i}.png", i); } else { PuppeteerSharpHelps.ScreenshotAsync("https://www.csdn.net/", $"F://test{i}.png", i); } }