意図
- PlaywrightとF#の組み合わせは便利なのにあまり見かけないのでサンプルとして
- 静的型、VerUp時に楽(JS/TSが大変と言うべきかも)、VSCode+Ionideが強力
- JS/TS、Pythonのコードを忘れたころに直そうとすると大変だが、F#だと少しマシな気がする
- query式、ClosedXML(Excel)、PdfSharpCore(PDF)と組み合わせるとある種の事務作業を楽できる
コード
- 実行方法
dotnet fsi sample.fsx
- 実行するとEdgeが(表で)起動してGoogleで"playwright dotnet"を検索してPDFに保存する
sample.fsx
#r "nuget: Microsoft.Playwright"
open Microsoft.Playwright
open System.Threading.Tasks
let createBrowser () =
let option = BrowserTypeLaunchOptions(Headless = false, Channel = "msedge")
task {
let! web = Playwright.CreateAsync()
let! browser = web.Chromium.LaunchAsync option
let! context = browser.NewContextAsync()
context.SetDefaultTimeout(1f * 1000f)
let! page = context.NewPageAsync()
return
{| web = web
browser = browser
context = context
page = page |}
}
let waitAnySelector (page: IPage) (selectors: string seq) =
let locators =
seq {
for sel in selectors do
page.Locator(sel)
}
|> Seq.toArray
let waitingTasks =
seq {
for loc in locators do
loc.WaitForAsync()
}
|> Seq.toArray
task {
try
let! _ = Task.WhenAny(waitingTasks)
let pred (task: Task) = task.IsCompletedSuccessfully
let index = Seq.findIndex (pred) waitingTasks
return Ok <| locators[index]
with _ as ex ->
return Error ex
}
let main () =
let tsk =
task {
let! br = createBrowser ()
let _web = br.web
let page = br.page
let url = "https://google.com"
let! _ = page.GotoAsync url
try
printfn "□タイムアウト例外捕捉"
let! _loc = page.WaitForSelectorAsync("マッチせずタイムアウトするようなパターン")
printfn "unreachable"
with
| :? System.TimeoutException -> printfn "try-with: Timeout"
| _ as ex -> printfn "try-with: %A" ex.Message
printfn "□フォームの入力"
let selectors = [ "textarea[aria-label=\"検索\"]"; "textarea[aria-label=\"search\"]" ]
let! loc = waitAnySelector page selectors
match loc with
| Ok(locator) ->
do! locator.FillAsync("playwright dotnet")
do! page.ClickAsync("input[type=\"submit\"][aria-label=\"Google 検索\"]")
| Error(err) -> failwith $"検索欄が見つかりません: {err}"
// 検索結果を待つ
let! _loc = page.WaitForSelectorAsync("h3")
let! _pdfBytes =
printfn "□スクリーンショット"
page.PdfAsync(PagePdfOptions(Path = "screenshot.pdf"))
return ()
}
tsk.Result
main ()