问题
这个问题与之前的 select功能无法正常使用类似,表现为在 linux 下,特别是在 iframe 中交互元素的时候,经常无法正常点击到元素。
以前猜测过是系统某些软件或者服务依赖存在问题导致的,但是在长大几个月的使用 tagui 中发现,只安装了 tagui 的 centos、ubuntu 同样存在此问题。
原因
直到现在仍然没有排查到原因,对 tagui 的整个代码和执行逻辑还没有太了解。但是通过查看成功与不成功的场景,发现 tagui_chrome.log 中的日志有一些的区别,并且验证了在多个不同 centos、ubuntu 中可能存在同样的问题
排查过程
click成功的日志输出:
[tagui] INPUT -
[7] {"id":7,"method":"Runtime.evaluate","params":{"expression":"document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotLength"}}
[tagui] OUTPUT -
[7] {"id":7,"result":{"result":{"type":"number","value":1,"description":"1"}}}
[tagui] INPUT -
[8] {"id":8,"method":"Runtime.evaluate","params":{"expression":"var result_bounds = document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0).getBoundingClientRect(); var result_rect = {top: Math.round(result_bounds.top), left: Math.round(result_bounds.left), width: Math.round(result_bounds.width), height: Math.round(result_bounds.height)}; result_rect","returnByValue":true}}
[tagui] OUTPUT -
[8] {"id":8,"result":{"result":{"type":"object","value":{"top":110,"left":240,"width":1080,"height":601}}}}
[tagui] INPUT -
[9] {"id":9,"method":"Runtime.evaluate","params":{"expression":"mainframe_context = document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0).contentDocument"}}
[tagui] OUTPUT -
[9] {"id":9,"result":{"result":{"type":"object","subtype":"node","className":"HTMLDocument","description":"#document","objectId":"-211116244302657272.5.1"}}}
[tagui] INPUT -
[10] {"id":10,"method":"Runtime.evaluate","params":{"expression":"(function (dom_json) {document.querySelector('iframe').contentWindow.dlClick.call(document.querySelector('iframe').contentDocument.querySelectorAll('.tdlist > div')[0]);})({})"}}
[tagui] OUTPUT -
[10] {"id":10,"result":{"result":{"type":"undefined"}}}
click 不成功的日志输出
[tagui] INPUT -
[66] {"id":66,"method":"Runtime.evaluate","params":{"expression":"document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotLength"}}
[tagui] OUTPUT -
[66] {"id":66,"result":{"result":{"type":"number","value":1,"description":"1"}}}
[tagui] INPUT -
[67] {"id":67,"method":"Runtime.evaluate","params":{"expression":"var result_bounds = document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0).getBoundingClientRect(); var result_rect = {top: Math.round(result_bounds.top), left: Math.round(result_bounds.left), width: Math.round(result_bounds.width), height: Math.round(result_bounds.height)}; result_rect","returnByValue":true}}
[tagui] OUTPUT -
[67] {"id":67,"result":{"result":{"type":"object","value":{"top":110,"left":240,"width":1080,"height":601}}}}
[tagui] INPUT -
[68] {"id":68,"method":"Runtime.evaluate","params":{"expression":"mainframe_context = document.evaluate('(//frame|//iframe)[@name=\"MFrame\" or @id=\"MFrame\"]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null).snapshotItem(0).contentDocument"}}
[tagui] OUTPUT -
[68] {"id":68,"result":{"result":{"type":"object","subtype":"node","className":"HTMLDocument","description":"#document","objectId":"6526965194935895727.5.2"}}}
通过日志最后几行可以看到,click不成功的时候最后在定位到 元素 后根本没有输出点击这个元素的日志。这个到底是什么原因我们排查手段有限,也许在后续有时间更加熟悉 tagui 代码后能够帮助它排查出来,但是现在我们不得而知。
这个现象与其他 click 或者 select 点击不了有很大的类似,也有一些不同。目前观察到的问题,只要在linux下无法click或者select元素,那么基本上都是通过坐标来定位的。有时候是坐标点击出现了误差,有些(这次)是根本没有执行代码。
所以我们解决的办法是通过 js 来操作,目前经过了这多次测试验证,基本上只要通过了控制台执行,那么 rpa 的 js 调用也可以成功。
但是 js 执行对于我们来说比较复杂,因为有时候浏览器本身提供的功能无法满足,还需要查看网站是否提供了内部的方法,比如下面这个
r.dom(f"document.querySelector('iframe').contentWindow.dlClick.call(document.querySelector('iframe').contentDocument.querySelectorAll('.tdlist > div')[-1])")
这里主要是想双击iframe内的元素,实测进入 iframe 后通过 dclick 不稳定,经常有很多案件进入不了,所以这里一整行都是为了 双击 进入某个案件。 前面一部分是定位到此 iframe ,中间一部分是调用此 iframe 中的 dlClick.call 方法,这是站点提供的双击方法,在 top 中不存在,所以需要第一部分定位到 iframe 中,接着我们在这个方法内还需要定位到此元素,又需要从 top 开始找,所以第一部分 定位 iframe 的代码仍然需要,最后一部分就是定位元素具体的代码,这个了解即可
PS. 方案汇总
后续一些场景下 click 点击不到的解决方案汇总:
- 123xx 环境点击案件详细页面的关闭按钮无效
r.frame()
r.dom('MFrame.contentWindow.document.querySelector("#btnBack").click()')
# 其中 MFrame 是元素所在的 iframe 名,当然在点击之前需要回到此 iframe 的上层
评论