玩了一下geckodriver
and Wireshark
:
--marionette
用;启动 Firefox 我个人喜欢添加--headless --no-remote --profile $(mktemp -d)
,但这取决于你!打开在端口 2828 上侦听的 FireFox(有一种方法可以改变它,但我不是 100% 确定如何)。
木偶协议如下:
- 每条消息都是没有换行符的以长度为前缀的 json 消息(例如,当您 connect 时
telnet localhost 2828
,您会受到 的欢迎50:{"applicationType":"gecko","marionetteProtocol":3}
,这50
意味着 json 的长度为 50 个字节。
- 每条消息(除了第一条消息)都是一个 4 项的 json 数组:
[0, messageId, command, body]
对于一个请求,其中messageId
是一个 int、command
一个字符串和body
一个对象。示例(带长度前缀)31:[0,1,"WebDriver:NewSession",{}]
[1, messageId, error, reply]
回复。这messageId
是回复的 id,或者error
或result
为空(取决于是否有错误)。例如697:[1,1,null,{"sessionId":"d9dbe...", ..., "proxy":{}}}]
- 可以在Marionette 源代码中找到所有命令的完整列表,在我看来,那里的所有函数都有很好的文档记录。一方面,它们似乎将所有 webdriver 函数都暴露在
WebDriver:*
.
更新:似乎https://bugzilla.mozilla.org/show_bug.cgi?id=1421766也在努力寻找正确的木偶端口/设置端口。我现在这样做的方式:
TEMPD="$(mktemp -d)"
echo 'user_pref("marionette.port", 0);' > "${TEMPD}"/prefs.js
/Applications/Firefox.app/Contents/MacOS/firefox-bin --marionette --headless --no-remote --profile "${TEMPD}" &
PID=$!
MARIONETTE_PORT=""
while [ -z "$MARIONETTE_PORT" ]; do
sleep 1
MARIONETTE_PORT=$(lsof -a -p $PID -s TCP:LISTEN -i4 -nP | grep -oE ':\d+ \(LISTEN\)' | grep -oE '\d+')
done
echo "Marionette started on port $MARIONETTE_PORT"
fg
(给端口 0 使 Firefox 选择一个随机的空端口。该命令适用于 MacOS;可能需要在 Linux 上进行一些调整(我认为参数lsof
略有不同;Linuxgrep
也有后视/前瞻,因此您可以将双精度替换grep
为单一个)。
更新 2
由于 Firefox 将编写它使用的 Marionette 端口,因此"${TEMPD}"/prefs.js
甚至不需要用lsof
;做“花哨”的事情。而只是检查该文件:
TEMPD="$(mktemp -d)"
echo 'user_pref("marionette.port", 0);' > "${TEMPD}"/prefs.js
/Applications/Firefox.app/Contents/MacOS/firefox-bin --marionette --headless --no-remote --profile "${TEMPD}" &
MARIONETTE_PORT=""
while [ -z "$MARIONETTE_PORT" ]; do
sleep 1
MARIONETTE_PORT=$(cat "${TEMPD}"/prefs.js | grep 'user_pref("marionette.port"' | grep -oE '[1-9][0-9]*')
done
echo "Marionette started on port $MARIONETTE_PORT"
fg