0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PlaywrightとF#でブラウザ自動化

Posted at

意図

  • 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 ()

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?