ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

WebDriver.jlで強引にedgeを使う

Web browser automation tutorial in Juliaの動画を見て,これと同じようなことがedgeでできると,社内で作っているWebアプリケーションの 検証の手助けが出来ると思って試してみた。

Edge WebDriverからedge用のドライバをダウンロードして,

$ cd $(ENV["HOME"])/Downloads/edgedriver_linux64
$ ./msedgedriver

とやってから,

using WebDriver

capabilities = Capabilities("edge")
wd = RemoteWebDriver(capabilities; port=9515)
url = "https://ujimushisradjp.hatenablog.jp/"

session = Session(wd)

sleep(5)

navigate!(session, url)

結果からいうと全然うまくいかない。 そこでどんなやり取りをしているかdriver側でログを吐き出して確認することにした。

$ cd $(ENV["HOME"])/Downloads/edgedriver_linux64
$ ./msedgedriver --log-level=ALL --log-path=log.txt

WebDriver.jlからedgidver側に次のようなJSONを送っているらしい。

[1704504490.010][INFO]: [7b7205fbf036f1fd0111a698436d34de] COMMAND InitSession {
   "desiredCapabilities": {
      "browserName": "edge",
      "timeouts": {
         "implicit": 0,
         "pageLoad": 300000,
         "script": 30000
      },
      "unhandledPromptBehavior": "dismiss and notify"
   }
}

Microsoft Edge オプションを構成するのように,バイナリの位置を指定できるとうまくいきそうだけど…

mozillaのドキュメントから,送っているJSONに うまくオプションを追加してあげると何とかなりそう。

しかし,

using WebDriver
capabilities = Capabilities("edge")

wd = RemoteWebDriver(capabilities; port=9515)
session = Session(wd, hoge="hage")

とかしてみても,ログを確認すると送られているJSON

{
   "hoge": "hage",
   "desiredCapabilities": {
      "browserName": "edge",
      "timeouts": {
         "implicit": 0,
         "pageLoad": 300000,
         "script": 30000
      },
      "unhandledPromptBehavior": "dismiss and notify"
   }
}

としかならない。また, Julia言語のPlotsのGRバックエンドでttcフォントを使う方法で使った変更方法で,本体側をいじらず何とかならないか試行錯誤したけど,型をいじらないといけないという結論に至り対応を断念。

ということで,

julia> dev WebDriver

でソースをダウンロードして,直接ソースをいじることにした。

index bb58e1d..6009192 100644
--- a/src/01_structs/04_WebDriver.jl
+++ b/src/01_structs/04_WebDriver.jl
@@ -20,7 +20,7 @@ true
 struct RemoteWebDriver{C<:Capabilities}
     addr::String
     capabilities::C
-    kw::Dict{String,Union{Int,String}}
+    kw::Dict{String,Union{Int,String,JSON3.Object}}
     function RemoteWebDriver(
         capabilities::Capabilities;
         host::AbstractString = "localhost",
@@ -31,7 +31,7 @@ struct RemoteWebDriver{C<:Capabilities}
         addr = URI(scheme = "http", host = host, port = port, path = path)
         isvalid(addr) || throw(ArgumentError("$addr is invalid"))
         addr = string(addr)
-        kw = Dict{String,Union{Int,String}}(
+        kw = Dict{String,Union{Int,String,JSON3.Object}}(
             string(k) => isa(v, Bool) ? string(v) : v for (k, v) ∈ kwargs if !isnothing(v)
         )
         new{typeof(capabilities)}(addr, capabilities, kw)
diff --git a/src/01_structs/05_Session.jl b/src/01_structs/05_Session.jl
index 21034c8..68da469 100644
--- a/src/01_structs/05_Session.jl
+++ b/src/01_structs/05_Session.jl
@@ -23,10 +23,12 @@ struct Session{D<:Object}
     attrs::D
     function Session(wd::RemoteWebDriver)
         @unpack addr = wd
+        obj_capabilities = JSON3.read(JSON3.write(wd.capabilities))
         response = HTTP.post(
             "$(wd.addr)/session",
             [("Content-Type" => "application/json")],
-            JSON3.write(Dict("desiredCapabilities" => wd.capabilities, wd.kw...)),
+            JSON3.write(Dict("desiredCapabilities" =>
+                merge(obj_capabilities, wd.kw))),
         )
         @assert response.status == 200
         json = JSON3.read(response.body)

変更としては,文字列や数値の他,JSON3のオブジェクトデータを入力オプションにできるようにして, オプションはdesiredCapabilitiesのタグの下に置けるようにした。

で,次のようにソースを変更

using WebDriver
using JSON3

capabilities = Capabilities("edge")

wd = RemoteWebDriver(capabilities; port=9515)
url = "https://ujimushisradjp.hatenablog.jp/"

json_string = """
{
   "ms:edgeOptions": {
      "binary": "/usr/bin/microsoft-edge"
   }
}
"""
option = JSON3.read(IOBuffer(json_string))

wd = RemoteWebDriver(capabilities; port=9515, option...)
session = Session(wd)

sleep(5)

navigate!(session, url)

とすると何とか動作しているようだ。

ここまで動くなるようになるのに,

  • ms:edgeOptions が分からず別の名前でやってうまくいかないのを数十回くり返す
  • Mozzilaのドキュメントにあるように,新しいバージョンの規格通りのJSONタグにするとWebDriver.jlが対応しておらずエラーとなる
  • edgeのドライバーはms:edgeOptionsに何か設定することで有効となる動きらしい

とか色々試行錯誤した。まぁこれでも本当に使えるのかは使いこんでみないとよく分からない