04 【UiBot 开发者指南】- 无目标命令
无目标命令
在[上一章][界面元素]中,我们讲述了界面元素,以及如何选取一个界面元素作为目标,以便使用有目标的命令。当然,并非在所有的情况下,都能准确找到恰当的界面元素作为目标。因此,我们需要学会使用“无目标命令”,以备不时之需。
为什么没有目标?
在[上一章][界面元素]中提到,我们在查找、操作界面元素的时候,实际上都是在调用界面元素所在的软件给我们提供的接口。UiBot 所做的,实际上是把这些种类各异的接口统一起来了,让编写流程的人无需关注这些细节。但是,仍然会有一些软件,没有给我们提供查找、操作界面元素的接口,或者虽然提供了接口,但在最终发布时关闭了。这些软件包括:
- 虚拟机和远程桌面
包含Citrix、VMWare、Hyper-V、VirtualBox、远程桌面(RDP)、各种安卓模拟器(如靠谱助手)等。这些程序都有单独的操作系统在运行,和UiBot所在的操作系统是完全隔离的,UiBot自然无法操作另一个操作系统里面的界面元素。
当然,如果条件允许的话,可以把UiBot和流程涉及到的软件,都安装在虚拟机里,或者远程计算机里。这样一来,这些软件提供的接口就可以被UiBot直接使用了,因为它们还是运行在同一个操作系统里面的,本地计算机只是起到了一个显示器的作用而已。
- 基于DirectUI的软件
以前,Windows软件界面的开发框架都是微软提供的,包括MFC、WTL、WinForm、WPF等。微软很贴心的为这些框架制作出来的界面都提供了自动化操作的接口。近年来,
为了让软件界面更好看,也更容易制作,很多厂商或开发团队推出了自己的Windows软件界面开发框架。这类框架统称为DirectUI。用这些框架制作的界面,其界面元素都是“画”出来的,虽然人眼可以看到,但操作系统和其他程序都不知道界面元素到底在哪里。有的DirectUI框架提供了对外的接口,可以找到界面元素,有的则根本没有提供这样的接口,其他程序,包括UiBot,自然也无法找到界面元素。
实际上,UiBot Creator、UiBot Worker本身的界面就是用一种DirectUI框架开发的,这种框架称为electron。electron其实提供了界面元素的查找接口,但对外发布的版本默认都关闭了。所以,细心的读者可能会发现,UiBot里面的界面元素,反而是市面上任何RPA平台,包括UiBot自己,都无法找到的。
还有一个我们常用的基于DirectUI的软件,就是微信的Windows客户端。由于腾讯并未对外透漏,我们无法得知微信的Windows客户端使用了哪种DirectUI框架。但事实表明,这种框架并未提供界面元素的接口,所以也是市面上任何RPA平台都无法找到的。不过,微信还提供了基于浏览器的网页版,可以获得界面元素,推荐大家在RPA流程中使用。
- 游戏
由于游戏的界面强调美观和个性化,所以,一般游戏的界面元素都是“画”出来的,原理上和DirectUI类似。这种界面通常也没有提供接口,告知我们界面元素的位置。和基于DirectUI的软件不同的是,游戏界面变化速度快,对时效性的要求更高,一般来说,RPA平台并未针对游戏进行优化,所以在游戏上使用的效果不会太好。
如果要在游戏上使用自动操作,推荐使用按键精灵。按键精灵是专门为游戏设计的,内置了很多针对游戏的界面查找手段,比如单点颜色比对、多点颜色比对、图像查找,等等。且运行效率更高。
无目标命令
我们在[上一章][界面元素]中介绍了“有目标”的命令,相对的,UiBot也有“无目标”的命令。如下图所示,红框中表示有目标的命令,蓝框中表示无目标的命令。
有目标和无目标的命令如果遇到了没有目标的Windows软件,“有目标命令”自然就不能再用了,但仍然可以用“无目标命令”。
在图中这些无目标的命令里面,最重要的是“模拟移动”,因为“模拟移动”需要我们在命令中指定一个坐标点,在执行这条命令的时候,鼠标指针也会移动到这个坐标点;移动之后,我们再使用“模拟点击”命令,模拟按下左键,才能正确的按下某个按钮;或者正确的在某个输入框上设置焦点,之后,再使用“输入文本”命令,才能在焦点所在的输入框里面输入一段文本。
比如,有一个输入框,其中间的坐标是x:200, y:300。那么我们就需要先用“模拟移动”,并设定移动的坐标为x:200, y:300;再用“模拟点击”按下左键,设置焦点;再用“输入文本”,才能正常输入。否则,直接用“输入文本”的话,很大概率就输入到其他输入框里面了。
这里,我们有必要先解释一下Windows操作系统的屏幕坐标系。如果您之前了解Windows的屏幕坐标系,这一段可以跳过不看。
在Windows操作系统中,屏幕上的每一点都有一个唯一的坐标,坐标由两个整数组成,一个称为x,另一个称为y。例如坐标x:200, y:300的含义就是这个点的坐标的x值是200,y值是300。x是以屏幕左边为0开始计算,从左到右分别是0,1,2,3...,以此类推。y是以屏幕上边为0开始计算,从上到下分别是0,1,2,3...,以此类推。所以,坐标x:200, y:300所对应的点,其位置大致如下图中红圈所示:
Windows的屏幕坐标系只要有x和y两个整数值,就可以确定屏幕上一个点的位置。在UiBot中,有一些命令可以获得屏幕上某点的位置,并输出到一个变量里。如何用一个变量来保存x和y两个值呢?我们在[后文][语言参考]中学习UiBot所使用的Botscript语言的时候会了解到,BotScript中有“字典”数据类型,可以保存多个值。所以,UiBot在输出一个点的位置的时候,会输出到一个字典类型的变量中。假设这个变量名为pnt
,则使用pnt["x"]
和pnt["y"]
即可得到坐标的x和y两个值。
假如我们要找的界面元素在屏幕上的固定位置,那么用固定的坐标,配合无目标命令,即可正常模拟操作。但这种情况往往比较少见,因为Windows是多窗口系统,每个窗口的位置都可以被拖动,导致窗口里面的界面元素的位置也会发生变化。而且,在微信这样的软件中,联系人的位置也不是固定的,而是根据最近联系的时间排序的,位置随时可能发生变化。
所以,在UiBot中,一般不推荐直接写固定的坐标,因为变化的情况太多了,很难一一考虑周全。通常,如果使用无目标的命令,需要搭配其他命令使用,让其他命令能根据某种特征,找到界面元素的坐标,然后把找到的坐标当作变量,传给这些无目标命令。
在UiBot中,无目标命令的最佳拍档,是图像命令。
图像命令
除了常用的“鼠标”、“键盘”类之外,UiBot的“图像”类命令也是很强大的。在UiBot Creator的命令区,找到“图像”,单击展开,可以看到其中包含了如下图所示的几个命令:
UiBot Creator里面列出的“图像”类命令我们首先来看“查找图像”这条命令,其作用是:首先指定一个图像文件,格式可以是bmp、png、jpg等(推荐使用png格式,因为它是无损压缩的),然后在屏幕上的指定区域,按照从左到右,从上到下的顺序依次扫描,看这个图像是否出现在指定区域当中。如果出现,则把其坐标值保存在一个变量中,否则发生异常。
看起来好像很复杂,又要指定图像文件,又要指定扫描的区域。实际上,使用UiBot Creator的话,操作非常简单。
比如,我们要模拟点击微信(Windows版)窗口上的“登录”按钮。[前文][为什么没有目标?]提到,微信Windows版是基于DirectUI的,无法获取到界面元素作为目标。所以,需要用到图像命令。
假设我们已经启动了微信,并打开了登录界面。下面,在UiBot Creator中编辑一个流程块,并以双击或拖动的方式,插入一条“查找图像”命令。点击命令上的“查找目标”按钮(如下图左),和有目标命令类似,UiBot Creator也会暂时隐藏,图标会变成一个箭头和一张图片的样子(如下图右)。此时,按下左键,并向右下方拖动,直到画出一个蓝框,且蓝框中已经包含了要找的图像,松开鼠标左键,大功告成!
使用“查找图像”命令并指定图像和查找范围看起来,上面的操作只是画了一个蓝框,但是,UiBot Creator已经帮我们做了两件事情:
-
判断蓝框落在哪个窗口上,并记录这个窗口的特征,将来找图的时候,也需要先找到这个窗口,并在这个窗口的范围内找图。
-
对蓝框所框住的部分截图,自动保存为一个png格式的文件,并自动把这个文件保存在当前所编写的流程所在目录的res子目录中。这就是将来要查找的图片。
用鼠标单击这条“查找图像”命令,将其置为高亮状态,右边的属性栏会显示出这条命令的属性,如下图所示:
“查找图像”命令的属性其中,画红框的两条属性,也是最重要的两条属性,就是前面所说的,UiBot Creator帮我们做的两件事情。其他各个属性里面,“相似度”是一个0-1之间的数字,可以包含小数位,这个数字越接近1,UiBot在查找图像时,越严格要求每个点都必须匹配上,通常取0.9,表示允许出现一小部分不匹配的情况,只要大体匹配即可。“光标位置”属性的含义是,当找到图像时,由于图像是一个矩形,而命令输出只是一个点的坐标,究竟要返回矩形中的哪个点的坐标,通常取“中心”即可。“激活窗口”属性表示在找图之前,是否需要先把所查找的窗口放到前台显示。如果窗口被遮住了,即使窗口上有我们要找的图像,也无法正确找到,所以这个属性通常也设为“是”。
其他的属性通常不用改,保持默认值就好。在“输出到”属性中,已经指定了一个变量名objPoint,如果成功的找到了图像,会把结果保存在这个变量中。我们来看看这个变量中保存了什么内容:在命令区的“基本命令”类中找到“输出调试信息”,将其插入到查找图像命令的后面,并且在属性中指定输出内容为objPoint(注意objPoint不加双引号,否则会把"objPoint"当作字符串输出)。如图所示:
用“输出调试信息”查看结果假设要查找的图像确实能在屏幕上看到,运行这个流程块后,得到结果:
{ "x" : 116, "y" : 235 }
具体的数值在不同的计算机上可能有所不同,但原理不变。这个值是一个“字典”数据类型,当这个值保存在变量objPoint中的时候,只需要写 objPoint["x"]
和 objPoint["y"]
即可得到其中的x和y值。
下面,得到了图像的中心位置,只需要用鼠标去点击这个位置,即可模拟微信的登录操作了。选用“鼠标”类中包含的“模拟移动”和“模拟点击”命令,即可很好的完成任务。
如下图,“模拟移动”命令最关键的属性,就是要操作的屏幕位置,分别输入查找图像的结果 objPoint["x"]
和 objPoint["y"]
即可。移动完成后,再来一个“模拟点击”,让左键在登录按钮的中心点下去。至此,我们已经模拟出点击“登录”按钮的全套操作。
上面三条命令很容易看懂,即使是从来没有学过UiBot的用户,也能大致了解其含义。但是,仅仅为了点一个登录按钮,还需要三条命令才能完成,显然过于复杂了。这时候,请再回头看一下UiBot提供的“图像”类下的所有命令,其中第一条命令叫“点击图像”,它其实就是“查找图像”、“模拟移动”、“模拟点击”三条命令的组合,只要插入一条“点击图像”命令,并按下命令上面的“查找目标”按钮,拖动鼠标选择要查找的窗口和要查找的图像,即可快速完成模拟点击微信“登录”按钮的功能。虽然是无目标的命令,但其操作便捷程度并不逊于有目标的命令。
有了上述基础,对于其他几条图像类的命令,包括“鼠标移动到图像上”、“判断图像是否存在”等等,您应该可以举一反三了,本文不再赘述。
OCR命令
使用“图像”类命令,可以在无法获取界面元素的情况下,找到准确的操作位置。但还不能像有目标的命令那样,把界面元素中的内容读出来。仍以微信Windows版为例,我们可以依靠图像命令来登录微信并切换不同的联系人,但对于联系人发来的聊天内容,仍然无法获取到(虽然这些内容用肉眼很容易看到),如图所示。此时,就需要祭出UiBot的“OCR”类命令了。
![很难直接获取微信中的聊天文字]!(https://img.haomeiwen.com/i3353491/c28872835a6cb4a6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
OCR的全称是“光学字符识别”,这是一项历史悠久的技术,早在上个世纪,OCR就可以从纸质的书本中扫描并获得其中的文字内容。如今,OCR的技术也在不断演进,已经融入了流行的深度学习等技术,识别率不断提高。我们现在用OCR去识别屏幕上的文字,由于这些文字不像纸质书本一样存在印刷模糊、光线不好等问题,所以识别率是非常高的。
当然,术业有专攻,OCR是RPA的好伙伴,但OCR的专业性较强,需要深厚的积累才能做好。通常RPA厂商不会自己去做OCR,而是直接接入第三方的OCR服务。在UiBot中,默认接入的就是百度云的OCR服务,因为百度云的OCR技术在国内厂商中还是比较强大的,不仅能识别界面上的文字、数字等,还对发票、身份证、火车票等票证的图像进行了特别优化,能较为准确的识别其中的关键内容(如发票号码、发票金额等)。
为了能够正常接入百度云的OCR,首先需要满足以下三个要求:
-
要能够接入互联网。百度云是基于互联网的云服务,而不是本地运行的软件,个人使用的话,必须接入互联网。如果是企业用途,不能接入互联网,可能需要和百度云进行商务磋商,购买其离线服务。
-
可能需要向百度付费。百度云OCR服务是收费的,但提供了每天若干次(通用文字识别每天5000次,证照等识别每天500次)的免费额度。个人使用的话,免费额度也基本够用了。当然,百度可能会随时修改免费额度和收费价格等政策,我们无法预估您需要向百度付多少费用。
-
由于百度云是收费的,不可能UiBot的用户都共用一个账号。所以每个用户要申请自己的百度云账号,以及百度云OCR服务的账号(一般称为Access Key和Secret Key),申请方法很简单,请点击这里查看我们的在线教程。
UiBot中包含了以下的OCR命令:
UiBot的OCR命令其中,红框里的命令类似于“图像”类中的“点击图像”、“鼠标移动到图像上”,“查找图像”命令,只不过不需要传入图像了,只需要在属性中标明要找的文字即可。
蓝框里的命令和绿框里的命令类似,只不过前者需要提供一个图像文件,后者需要提供一个窗口、以及窗口中的一个区域,UiBot会在流程运行到这一行的时候,自动在窗口的指定区域截图并保存为一个文件,然后采用和前者一样的方式去执行。
我们先试一下“屏幕OCR”命令。双击或拖动插入一条“屏幕OCR”命令,点击命令上的“查找目标”按钮(此时UiBot Creator的窗口会暂时隐藏);把鼠标移动到微信窗口上,微信窗口会被红框蓝底的遮罩遮住;此时拖动鼠标,划出一个要进行文字识别的区域,这个区域会用紫色框表示。如下图所示。
选择OCR目标这样的一条命令,会在运行的时候,自动找到微信的窗口,并在紫色框指定的位置(相对于微信窗口的位置)截图,然后识别截图里面的文字,最后把识别到的文字保存在变量sText中。
先不要急着运行,我们还需要选中这条命令,在“属性”中填写我们在百度云上申请的Access Key和Secret Key。注意Access Key和Secret Key都是字符串,所以需要保留左右两边的双引号。OCR命令完成之后,为了看到效果,最好加入一条“输出到调试窗口”命令,并指定输出变量sText。注意sText是变量名,而不是字符串,所以两边不加双引号。
完成一条OCR命令运行这个流程块,即可看到效果。只要微信窗口存在,且窗口大小没有发生变化,就能识别出当前聊天人(或微信群)的名字。
下面,再测试一下“图像特殊OCR识别”命令。所谓“特殊”,是指我们要测试的是某种特定的图像,如身份证、火车票等。假设我们在D:\\1.png
文件中保存了如下的图像:
插入一条“图像特殊OCR识别”命令,按图示修改其属性。除了前文提到的Access Key和Secret Key之外,还需要指定要识别的图片的文件名,以及选择OCR引擎为“火车票识别”。其他属性均保持默认值,运行后,可以在输出栏看到识别的结果。这个结果实际上是一个JSON文档,如果需要进一步处理,需要采用UiBot提供的JSON类命令,但与本章关系不大,略过不表。
特殊OCR的属性设置注意事项
在上一章中,我们学习了有目标的命令,而在这一章中学习了无目标的命令。其实,在大多数情况下,无目标命令也不是对着一个固定的屏幕位置进行操作,而是结合图像、OCR等命令,动态的在屏幕上找到要操作的位置。
那么,我们该选择有目标的命令,还是无目标的命令呢?只要能获得恰当的界面元素作为目标,就应该优先考虑有目标的命令。因为无目标的命令,特别是它们所依赖的图像、OCR等命令,有以下的缺点:
- 速度远远慢于有目标的命令;
- 可能受到遮挡的影响,当图像被遮挡时,即使只遮挡了一部分,也可能受到很大影响;
- 往往需要依赖图像文件,一旦丢失图像文件就不能正常运行;
- OCR命令还必须连接互联网才能运行。
当然,这些缺点也是可以缓解的,以下技巧能帮您更好的使用图像、OCR命令:
首先,请牢记一个“小”字。在截图时,尽量截取较小的图像,只要能表达出所操作的界面元素的基本特征即可。在指定查找的区域时,尽量缩小区域。这样不仅速度会有所改善,而且也不容易受到遮挡的影响。比如下图中的“登录”按钮,没必要像左图一样,把整个按钮作为一幅图像来查找,只要像右图一样选择最关键的部分就可以了。
选择较小的截图其次,大部分图像命令都支持“相似度”的属性,这个属性的初始值是0.9,如果设置过低,可能造成“错选”,如果设置过高,可能造成“漏选”(“错选”和“漏选”的概念请参考[上一章][目标编辑])。可以根据实际情况进行调整,并测试其效果,选择最佳的相似度。
然后,屏幕的分辨率和屏幕的缩放比例对图像命令可能有非常关键的影响。因为在不同的分辨率下,软件的界面显示可能完全不一样,导致图像命令失效。所以,请尽量保持运行流程的计算机和开发流程的计算机的分辨率、缩放比例都是一致的。在Windows 10操作系统上设置分辨率和缩放比例的界面如下图所示:
设置分辨率和缩放比例最后,无论是图像命令还是OCR命令,当需要使用图像文件时,可以用一个绝对路径来测试,如前面例子中的D:\\1.png
。但是,这就要求在运行此流程的计算机上,也必须在同一路径下有同样的文件,否则就会出错。有一个改进的方法,就是在您的流程所在的文件夹中,可以看到一个名为res的文件夹,把图像或其他文件放在这个文件夹中,并在流程中使用@res"1.png"
来代表这个文件即可。这样的话,当前流程发布给UiBot Worker使用的时候,也会自动带上这个文件。并且无论UiBot Worker把这个流程放在哪个路径下,都会自动修改@res
前缀所代表的路径,使其始终有效。
返回目录
注: 上述内容经 UiBot 官方 授权发布,版权归 UiBot 官方所有,如需转载请先联系。
更多 RPA 相关的资讯,请关注公众号:流程自动化机器人教程
由于简书禁止直接在文章中插入公众号二维码,请点击 这里 了解添加该公众号的细节。