在RPA
开发一些网银页面自动化流程时,会出现一些情况,企业网银使用U盾的登陆页面有时会包含一些特殊的密码控件,使得他们的页面中的密码框元素不会显示在网页中,我们使用F12
调试工具选中的时候发现无法选中,页面中的其他元素都可以直接选中,但是密码框那边是不存在的,查找网页中的元素也找不到密码框的元素,这使得传统的网页自动化工具类似于Selenium
无法正常点击和输入。
上面的示例图可以看到,唯独密码框部分是没有选中的,查看网页源代码发现也是没有密码框的input
或者其他元素。
于是激活密码框和输入也成了一个难题。
序
在技术攻坚时了解到了Uiautomation
这一个UI
自动化工具。它支持自动化Win32
、MFC
、WPF
、Modern UI (Metro UI)
、Qt
、IE
、Firefox
、Chrome
以及基于Electron
开发的应用程序。这个是它官方说的支持情况,其实不需要知道这么多,只需要知道它可以做UI
自动化控制I/O
程序就行了,常用的也就是Win32
桌面和一些网页端的UI
控制。
微软做了一个应用程序inspect
用来方便读取整个桌面/应用程序的UI框架
,它可以直观的展示现在你所在屏幕内容的树形结构,而且显示了它们的各个属性,方便UIA
进行定位。
提供一个下载地址: Inspect.exe
再放一个程序的展示图,可以下载到本地琢磨琢磨。
应用左边显示的是整个屏幕显示内容的树形结构,右边显示的是特定桌面元素的各项属性。
正片开始
好了准备工作就绪的话,现在就可以开始操作了,先捋起袖子不要影响我们敲代码。鼠标再换成无线的否则拖拖拉拉不舒服。
回到上面的问题场景,我没法通过比如Xpath
定位使用Selenium
类似的工具进行元素的定位和点击,因为网页中根本不存在这个元素,但是它既然显示在你的桌面屏幕上,那么它就是一个桌面元素,所以我们就可以对他进行定位。再通过对他的点击操作实现目标。
可以看到,这个密码框是一个Pane
桌面元素,所以就可以很自然的定位到它在对他进行一些操作。
然后,我们也可以看到这个元素是没有Name
属性的,最多的定位是可以通过Name
属性进行定位的,所以需要找到一个可以轻松定位的元素,再通过相对位置一步一步找到这个密码输入框。
因为涉及企业网银的一些信息,这里不具体一步步展示,打个比方,在这个网页上的登录
按钮它的元素元素类别是Button
,Name
属性值为登录
(事实上确实是这样),于是我们可以通过一下代码对他进行一个简单的定位。
import uiautomation as uia
# 你可以这么写
login_btn = uia.ButtonControl(Name="登录", [maxSearchDepth])
# 如果你还想点击
login_btn = uia.ButtonControl(Name="登录", [maxSearchDepth]).click()
稍作解释:
ButtonControl
表示是按钮元素类型,还有很多比如ExitControl
、TextControl
Name
是定位的根据,还有很多比如ClassName
、AutomationId
searchDepth
表示搜索深度,表示在树形目录下的搜索深度
可以去看函数的源码做更多的了解,现在我要继续解决一下问题。
现在我打个比方,上面我的密码框的位置,是在登录按钮的父元素的下一个同级元素的第三个子元素的第一个子元素,好像说的有点花里胡哨,不是的,我是要介绍一下层级定位的各个方法。
现在我们可以开始寻找这个令人恼火的密码框了。
import uiautomation as uia
# 登录按钮
login_btn = uia.ButtonControl(Name="登录", [maxSearchDepth])
fuck_pwd_input = login_btn.GetParentControl()
.GetNextSiblingControl()
.GetChildren()[2]
.GetFirstChildControl()
if fuck_pwd_input.Exists(maxSearchSeconds=10):
# 激活它
fuck_pwd_input.click()
# 输入密码
fuck_pwd_input.SendKeys("{my_password}", [waitTime])
做一些解释:
Exists
表示搜索时间,参数为maxSearchSeconds
SendKeys
表示输入,waitTime
表示输入前等待时间,同样click
函数也又这个参数
这样问题就解决了;只是上面一级一级搜索的过程,我相信对照中文说明或者英文的字面意思都是看的明白的。
不要依赖
结合Uiautomation
工具能够弥补网页端自动化元素定位的一些缺陷,但是其实也是有问题的,这个工具不能够非常及时的刷新桌面应用程序,在一些场景下,桌面元素可能发生变动但是它并没有很及时的更新树结构,所以很多时候会发现使用UIA
去定位的时候返回为空,并没有成功的找到元素。