如何在 F# 中使用 Playwright Sharp 实现浏览器自动化

How to use Playwright Sharp in F# for Browser Automation

我想这是一个经典的 C# 到 F# 的转换我还没有完全理解。

我正在尝试使用快速启动自动化浏览器

https://playwright.dev/dotnet/docs/intro

C#代码是

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("http://www.bing.com");
await page.ScreenshotAsync(path: outputFile);

我已经开始了,但已经有点迷路了。

let playwright: Playwright = PlaywrightSharp.Playwright.CreateAsync() |> Async.AwaitTask

类型不正确。我在这里做错了什么?

Error   FS0001  This expression was expected to have type
    'Playwright'    
but here has type
    'Async<IPlaywright>'    

您可以使用 TaskBuilder 框架 https://github.com/rspeele/TaskBuilder.fs

dotnet 添加包 Taskbuilder.fs

并写

task {    
    use! playwright =  Playwright.CreateAsync() 
    let! browser =  playwright.Chromium.LaunchAsync()
    let! page = browser.NewPageAsync()
    
    let! response = page.GoToAsync("http://www.bing.com")
    let! title =  page.GetTitleAsync()

    printfn "%s" title

}
|> Task.WaitAll

一种方法是使用 F# 对 async computation expressions 的内置支持。翻译看起来像这样:

let (~~) = Async.AwaitTask

async {
    use! playwright = ~~Playwright.CreateAsync()
    let! browser = ~~playwright.Chromium.LaunchAsync()
    let! page = ~~browser.NewPageAsync()
    do! ~~page.GoToAsync("http://www.slashdot.com") |> Async.Ignore
    do! ~~page.ScreenshotAsync(outputFile) |> Async.Ignore
} |> Async.RunSynchronously

这里有一些您需要了解的细节:

  • F# 有自己的异步类型,称为 Async<'T>。我使用 Async.AwaitTask 从 C# 风格的任务进行转换,并定义了一个前缀运算符 ~~,使它看起来更简洁。
  • F# 不支持 async 计算表达式 yet 中的 DisposeAsync,因此浏览器无法正确处理。如果需要,您可以在块的末尾添加 do! browser.DisposeAsync().AsTask() |> Async.AwaitTask 以手动执行此操作。
  • F# 要求我们明确忽略不需要的 return 值,我通过 Async.Ignore.
  • 完成了这一点

从 F# 6 开始,任务现在通过 task computation expression 本机支持。语法几乎与 Brian Berns 的回答中的异步计算表达式相同,只是您不再需要在每个 let!use!do! 绑定上调用 Async.AwaitTask .

let screenshotTask =
  task {
    use! playwright = Playwright.CreateAsync ()
    use! browser = playwright.Chromium.LaunchAsync ()
    let! page = browser.NewPageAsync ()
    let! _ = page.GotoAsync "https://www.bing.com"
    let! _ = page.ScreenshotAsync (PageScreenshotOptions(Path = "screenshot.png"))
    return ()
  }
screenshotTask.Wait ()