使用 Chrome DevTools 协议 Input.dispatchKeyEvent 或 Input.dispatchMouseEvent 发送事件

Posted

技术标签:

【中文标题】使用 Chrome DevTools 协议 Input.dispatchKeyEvent 或 Input.dispatchMouseEvent 发送事件【英文标题】:Using Chrome DevTools Protocol Input.dispatchKeyEvent or Input.dispatchMouseEvent to send an event 【发布时间】:2017-11-20 09:09:11 【问题描述】:

我正在编写一个 DSL,它将通过 Google Chrome 的远程调试 API 与页面交互。

INPUT 域(链接在这里: https://chromedevtools.github.io/devtools-protocol/1-2/Input/) 列出了两个可用于发送事件的函数:Input.dispatchKeyEventInput.dispatchMouseEvent

我似乎无法弄清楚如何指定目标 element,因为这两个函数和 DOM.NodeId 之间没有链接,或者接受 DOM.NodeId 的中间 API 然后返回 X,Y坐标。

我知道可以使用 Selenium,但我有兴趣直接使用 WebSockets。

感谢任何帮助。

【问题讨论】:

【参考方案1】:

简介

我目前正在开发一个 NodeJS 交互库,以通过远程调试协议与 Chrome Headless 一起使用。想法是将其集成到我同事的测试框架中,以最终取代不再支持的 PhantomJS 的使用。

评估 javascript

我目前只是在试验一些东西,但我有一种评估页面上 JavaScript 的方法,例如,通过选择器引用单击元素。假设我的实现没有缺陷,它应该在理论上适用于任何事情。

let evaluateOnPage: function (fn) 
    let args = [...arguments].slice(1).map(a => 
        return JSON.stringify(a);
    );

    let evaluationStr = `
        (function() 
            let fn = $String(fn);
            return fn.apply(null, [$args]);
        )()`;

        return Runtime.evaluate(expression: evaluationStr);
    

上面的代码将接受一个函数和任意数量的参数。它将参数转换为字符串,因此它们是可序列化的。然后它评估页面上的 IIFE,它调用传入参数的函数。

示例用法

let selector = '.mySelector';

let result = evaluateOnPage(selector => 
    return document.querySelector(selector).click();
, selector);

Runtime.evaluate 的结果是一个 promise,当它被实现时,你可以检查结果对象的类型来确定成功或失败。例如,subtype 可能是nodeerror

我希望这对你有用。

【讨论】:

是否有没有 Javascript 的纯远程调试 API 决策(理论上可以禁用 Javascript)?【参考方案2】:

如果您想点击特定元素而不是点击屏幕上的点,这个协议可能不是最好的......

请务必记住,devtools 协议的这个区域旨在模拟原始输入。如果您想尝试使用协议或通过在页面中运行一些javascript来找出元素的位置,您可以这样做,但是最好使用target.dispatchEvent()和MouseEvent之类的东西并将javascript注入页面。

【讨论】:

以上是关于使用 Chrome DevTools 协议 Input.dispatchKeyEvent 或 Input.dispatchMouseEvent 发送事件的主要内容,如果未能解决你的问题,请参考以下文章

使用谷歌浏览器远程调试协议

使用Chrome Headless 快速实现java版数据的抓取

使用 Selenium Webdriver 控制 Chrome Devtools

Chrome DevTools

使用 Selenium webdriver 运行时是不是可以使用 Chrome 的 devtools?

最新 Chrome DevTools(v57) 使用详解