GET:可以返回一串JSON字符串,
uibot还提供了设置HTTP请求头和cookies功能,分别为“设置cookies”和‘设置headers’两个命令,cookies一般存储网页的状态信息。
设置Headers”命令的则可以帮助我们模拟浏览器访问目标页面,因为它可以携带请求方的一些信息,例如我们用的什么浏览器、请求的来源等信息。
FTP(File Transfer Protocol)即文件传输协议,是一种基于TCP的协议,采用客户/服务器模式。通过FTP协议,用户可以在FTP服务器中进行文件的上传或下载等操作。虽然现在通过HTTP协议下载的站点有很多,但是由于FTP协议可以很好地控制用户数量和宽带的分配,快速方便地上传、下载文件,因此FTP已成为网络中文件上传和下载的首选服务器。下面我们来学习UiBot如何与FTP服务器交互。
第一、使用UiBot的时候,应该优先使用有目标的命令,因为有目标的命令更加准确;
第二、使用UiBot的时候,如何准确选取一个目标是很关键的,只要准确地选到了目标,模拟操作相对来说就比较简单了;
第三、UiBot提供了全自动的选取目标的方法,在全自动选取目标完成后,还可以手动修改目标的特征,以便尽量减少错选和漏选。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uf3RqlzU-1628654000107)(RPA官网视频学习笔记.assets/image-20210714111213559.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NdiSVGNo-1628654000110)(RPA官网视频学习笔记.assets/image-20210714111235598.png)]
顾名思义,既然有“主流程”,自然就会有“副流程”。在UiBot中,我们将其命名为“辅助流程”,而不是“副流程”。之所以这样命名,是因为它的用途通常是帮助主流程完成一些额外的任务,起到“辅助”的作用。
当我们在开发一个稍微复杂一些的流程时,为了能够提高效率,确保流程尽快完成,常见的方法是把流程划分为多个步骤,由不同的人去编写不同的步骤,最后再把这些步骤组装在一起。
a
,一个流程块将其值设为1
,另一个流程块将其值设为2
,第一个流程块并不知道这个值已经被修改了,仍然按照1
去处理,就会出现问题)。举例来说,假设我们有一个流程,其中包含一个前置步骤、两个业务步骤、一个后置步骤。我们希望把这两个业务步骤交给其他人来编写,其中每个业务步骤都是一个“子流程”,每个子流程里面又可以包含多个流程块,以及条件判断等。从我们的视角来看,这个流程图大致是如下的状态(不妨把这个顶级的流程称之为“总流程”,下文将延续这种称呼):
其中,“前置步骤”和“后置步骤”这两个流程块由我们来编写,“子流程1”和“子流程2”这两个步骤由其他同事来编写。细心的读者可能注意到了,“子流程1”和“子流程2”这两个步骤并不是普通的流程块,因为图标两侧各有一条竖线,和流程块的图标不一样。实际上,“子流程1”和“子流程2”分别都是一张完整的流程图,里面还可以包含其他流程块。但在我们的视角中,只是把这两位同事编写的“子流程1”和“子流程2”当作两个单独的组件,并不关心其中的细节。
例如,对于“子流程1”来说,其中可能包含了两个流程块,如下图:
而对于“子流程2”来说,其中可能包含了一个流程块和一个条件判断,如下图:
值得注意的是,对于总流程、子流程1、子流程2,它们的变量都是彼此隔离的。也就是说,如果在总流程和子流程里面都定义一个变量a
,无论a
是流程图变量,还是流程块变量,它们在总流程或者子流程里面各有各的取值,不会互相影响。这样的话,我们在编写流程或子流程的时候,即使是由不同的人完成,也不用担心大家凑巧给变量起了相同的名字而导致冲突。(变量互不干扰)
UiBot规定,您需要先创建子流程(其中的流程块,以及流程块中的内容可以先空着不写,后续再完善),然后才能在流程中引用子流程。子流程中还可以再引用其他子流程,但仍然需要遵循“先子后父”的创建顺序。如下图中,总流程包含了3个子流程,其中有的子流程又包含了其他子流程(不妨称之为“孙流程”)。那么需要先逐一创建孙流程,再创建子流程,最后创建总流程。
我们先考虑最简单的情况:在一个总流程里引用一个子流程。掌握了这种操作以后,再考虑多级子流程,也就可以举一反三了。
2.3 子流程的输入输出
当我们在总流程中引入了一个子流程的时候,根据前文所述,它们的变量是相互隔离的。即使定义了相同命名的变量,也各有各的取值,不会冲突。这样虽然避免了冲突的问题,但是,如果总流程和子流程需要协作,不可避免的还是要把数据在总流程和子流程之间进行传递。比如,子流程是某个同事负责编写的,其作用是根据我的手机号码,查询手机号码的归属地。那么,在和这位同事协作的过程中,至少有三个需求要满足:
使用方向包括“输入”、“输出”和“无”三种。为了让开发者能够尽快掌握这一功能,UiBot Creator还会自动定义两个变量,名字分别是input
和output
,使用方向分别是“输入”和“输出”。如下图所示。
流程图变量“使用方向”的含义是:
当我们兴致勃勃地用UiBot写完一个流程并运行后,总是期待得到成功的结果。但是有时候往往达不到预期的效果,尤其是对于新手而言,要么运行的时候UiBot报错,要么UiBot不报错,但是流程运行没有得到预想的结果。这个时候就需要对流程进行调试了。
所谓调试,是将编制的程序投入实际运行前,用手工或自动等方式进行测试,修正语法错误和逻辑错误的过程,是保证计算机软件程序正确性的必不可少的步骤。
其实,我们在前面已经大量使用了一种最原始、最朴素、但也是最常用、最实用的一种程序调试方法:“输出调试信息”命令。在关键代码的上一行或下一行添加输出调试信息,查看参数、返回值是否正确。严格意义上来说,这并不能算是一种程序调试的方法,但是确实可以用以测试和排除程序错误,同时也是某些不支持调试的情况下一个重要的补充方法。
程序,是人脑中流程落实到编程工具的一种手段;程序调试,本质上是帮助厘清人脑思路的一种方式。
首先,要对系统的业务流程非常清楚。业务产生数据,数据体现业务,流程的运行逻辑也代表着业务和数据的运转过程。当错误发生时,首先应该想到并且知道这个问题的产生所依赖的业务流程和数据。
添加和删除断点
调试运行
单步调试
打断点的技巧
有效范围只在做当个流程的时候,才起作用。
一般来说,一个流程图由一个或多个流程块组成,如果该流程比较复杂,那么流程中包含的流程块数量一般比较多,或者单个流程块的命令条数比较多。我们对流程图中靠后执行的流程块进行调试时,如果靠后流程块依赖靠前流程块的数据输入,那么靠后流程块的调试将会非常费时费力。我们举一个具体实例:假设某个流程由两个流程块组成,分别叫做“靠前流程块”和“靠后流程块”,流程中定义了两个全局变量x
和y
,“靠前流程块”中分别为x
和y
赋值为4
和5
,“靠后流程块”分别打印出x
、y
和x+y
的值。
我们在流程图视图下点击运行,可以看到,UiBot可以输出正确的结果:
假如我们要单独测试一下“靠后流程块”的功能(其实就是一个加法模块)是否正确,此时“靠后流程块”是无法单独执行的,我们在“靠后流程块”的可视化视图或源代码视图下点击运行,会报错:
为了测试这个“靠后流程块”,必须要执行“靠前流程块”,因为x
和y
赋值操作来源于“靠前流程块”。这里“靠前流程块”比较简单,只做了几个赋值操作,如果“靠前流程块”比较复杂,例如x
和y
的值分别来源于抓取天猫和京东两个网站某类商品后的统计数量。那么测试这个“靠后流程块”的代价将非常大。
那怎么办呢?强大的UiBot从5.0版本开始,提供了一种单元测试块,可对单个流程块进行测试。回到刚才的例子,我们来看看单元测试块的具体用法。
打开“靠后流程块”的源代码视图,在命令中心“基本命令”的“基本命令”目录下,插入一条“单元测试块”命令。我们可以看到,在源代码视图下,UnitTest
和End UnitTest
中间就是单元测试块,我们在中间填入测试命令分别为x
和y
赋值3
和2
。
我们在“靠后流程块”的可视化视图或源代码视图下再次点击运行,此时执行正确:
单元测试块具有如下特性:
第一、单元测试块不管放置在流程块中的什么位置,都会被优先执行。
第二、只有在运行单个流程块时,这个流程块中的单元测试块才会被执行;如果运行的是整个流程,流程块中的单元测试块将不会被执行。
第一条特性保证了调试单个流程块时,单元测试块肯定会被执行到;第二条特性保证了单元测试块的代码不会影响整个流程的运行,不管是运行单个流程块,还是运行整个流程,都可以得到正确的结果。
源代码的版本控制是软件开发中一个十分重要的工程手段,它可以保存代码的历史版本,可以回溯到任意时间节点的代码进度。版本控制是保证项目正常进展的必要手段。对初学者学习而言,建议在开始进行实践小项目的阶段即进行源代码版本控制,这在以后的工作中会大有裨益。
UiBot通过集成著名的代码版本控制软件Git,提供了强大的版本控制手段: “时间线”。所谓时间线,指的是不同时间点的代码版本。
用户鼠标移到工具栏“时间线”按钮上,“时间线”按钮上出现“保存时间线”按钮,点击“保存时间线”,即可保存将该时间点的流程。保存时间线时,需要填写备注信息,用以描述该时间点修改了代码的哪些内容。
如果用户不记得保存时间线,没关系,UiBot每隔五分钟,会自动保存时间线;如果这段时间内用户未修改流程内容,则不保存时间线。
点击工具栏“时间线”按钮,“时间线”页面按照“今天”、“七天之内”、“更早之前”列出已保存的时间点,单击任意一个时间点,可查看当前文件和选中时间点文件的内容差异,内容差异会用红色背景标识出。
如果要恢复该时间线的部分代码,可以直接点击代码对比框的蓝色箭头,直接将该段代码恢复到现有代码中。
模块化的思想在许多行业中早已有之,并非计算机科学所独创。
例如,建筑行业很早就提出了模块化建筑概念,即在工厂里预制各种房屋模块构件,然后运到项目现场组装成各种房屋。模块构件在工厂中预制,便于组织生产、提高效率、节省材料、受环境影响小。模块组装时施工简便快速、灵活多样、清洁环保,盖房子就像儿童搭建积木玩具一样。
总之,模块化的思想就是在对产品进行功能分析的基础上,将产品分解成若干个功能模块,预制好的模块再进行组装,形成最终产品。
一个命令库里面包含了若干条命令,使用起来就像UiBot中的预制件一样,可以在可视化视图中拖拽,也可以用接近自然语言的形式来展示,便于理解。
从UiBot Creator 5.1版本开始,当我们点击首页上的“新建”按钮时,会弹出一个对话框,可以选择要新建的是一个流程,还是一个命令库(如下图)。
选择命令库之后,可以看到命令库的编写界面和编写流程块类似。实际上,命令库确实可以视为一个特殊的流程块,但它不会像普通的流程块那样,从第一行开始执行,而是需要设置若干个“子程序”。如果您熟悉其他编程语言,“子程序”的称呼实际上就相当于其他语言中的“函数”(function)或者“过程”(procedure)。在UiBot中,之所以称为“子程序”,是为了让IT基础较少,不了解其他编程语言的开发者不至于感到困惑(比如和数学中的“函数”概念产生混淆)。
命令库中的每个子程序,对于命令库的使用者看来,就是一条“命令”。所以,就像UiBot预制的命令一样,我们可以为其设置一个名称,和一组属性,这些名称和属性也会被使用者看到。
新建一个命令库之后,作为例子,UiBot Creator已经帮我们生成了一个子程序的框架,在可视化视图和源代码视图下,其内容如下图所示。在源代码视图下,还会生成一段注释,以助理解。
我们已经学习了使用源代码来编写流程内容,直接切换到源代码视图,把下面的源代码粘贴进去。
Function 加法(被加数, 加数)
Return 被加数 + 加数
End Function
Function 减法(被减数, 减数)
Return 被减数 - 减数
End Function
Function 乘法(被乘数, 乘数)
Return 被乘数 * 乘数
End Function
Function 除法(被除数, 除数)
Return 被除数 / 除数
End Function
切换到可视化视图,即可看到我们已经完成了一个加减乘除的四则运算命令库,其中包含四条命令。如下图。当然,您也可以直接在可视化视图编写命令库及命令,具体过程比较简单,不再赘述。
命令库至此已建立完毕,但为了方便他人使用,推荐使用“发布”功能,把这个命令库发布成一个独立的文件,以便发给他人。
在编写命令库的时候,我们可以看到,工具栏上有一个“发布库”的按钮,如下图所示。
点击这个按钮,UiBot Creator会校验命令库中是否存在错误,如果没有错误,则会弹出如图所示的对话框。这个对话框中的默认值已经填写好了,可以不填。而且即使不填,也不会对使用命令库有任何影响。但在这个例子中, 我们仍然对红框所在的内容进行了修改,这样修改是为了让用户使用起命令库来更加容易。
这些修改的意义在于:
%1%
和%2%
,会在可视化视图中,分别用命令的第一个属性和第二个属性替代。例如,第一个属性为1
,第二个属性为2
,则可视化视图中显示的内容是“将1和2相加
”,而不是默认的“四则运算.加法(1,2)
”。显然,前者的可读性要好得多;填写完成后,只要点击“发布”按钮,即可把命令库发布为一个独立的、以.zip
为扩展名的文件。把这个文件用各种方式(如邮件、U盘等)发给其他同事,他们只要导入命令库,就可以像使用UiBot Creator中的其他预制件一样,使用其中的命令。
.zip
)。导入完成后,在界面上会出现已导入的命令库,如下图中绿框所示。这些命令的用法和UiBot Creator中的其他预制件一样,具体不再赘述。
值得注意的是:
添加链接描述
添加链接描述
添加链接描述
添加链接描述
无论是用哪种语言编写插件,都可以放在extend
目录的相应路径中,例如Python插件放在extend/python
目录中,即可直接使用。
编写python/c#/java代码————>压缩(*.zip)—————>uibot(命令中心)——————>自定义(自定义插件)—————>新增(根据流程弄就OK)
数据表是非常重要的数据处理工具,可以使用它对数据进行合并,排序,筛选等操作
以下是某学校的学员成绩表和通讯录表,均存储在Excel文件中。两表之间以学号作为关联。某些学员没有提供电话,所有缺失部分学员的联系方式,同时也有部分同学没有参加考试,所以缺少他们的成绩记录,表格如下:
现在学校需要找出参加考试且留有联系电话的同学,形成一张同时有成绩和联系方式的表格,再通过电话告知他们考试成绩,完成该需求并不难,可以通过UiBot中Excel模块的”读取区域“命令读取“成绩表”和“通讯录”中的内容,然后构建成两个数据表。
接下来使用“合并数据表”命令将两个数据表进行合并,并设置该命令的属性,其中“左表”设置为“成绩表”,“右表”设置为“通讯录”,“左表列”和“右表列”均为“学号”,这两个属性的作用是设置在两个表中,以哪两列作为关联进行数据合并,在本例中即是将左表和右表中学号相同的记录进行合并,形成一个新的表格。“连接方式”属性设置为“内连接”,如图:
合并数据表
将合并后的数据表转为数组,并保存到Excel中即可获得所需表格,如图:
除了“内连接”,数据表还提供“外连接”、“左连接”、“右连接”,这几个连接的具体释义如下:
数据表中还有很多实用的功能,例如:”数据表去重“、”数据筛选“等,大致使用方法基本类似,这里就不再逐一介绍。如果大家对某条命令的功能不清楚,可以将鼠标悬停在命令上,此时UiBot会有相应的功能提示,对于命令的属性也可以使用相同方法获得提示,如图:
要使用好数据表,首先需要熟悉数据表的各个功能,其次要灵活运用这些命令,很多场景需要把多个功能组合起来使用,所以大家在处理数据时一定要多多转换思路,不要一味蛮干。
内连接、左连接、右连接、外连接
数据合并、数据表去重、数据筛选
字符串的处理在流程开发过程中经常会遇到,例如用户输入了一个邮箱号,我们想要简单验证一下格式是否正确,最常用的方法就是检测用户输入的内容中是否有“@”符号,假如用户输入的邮箱号是:“[email protected]”,这时我们可以使用“查找字符串”命令,并根据该命令的输出值来进行验证“@”是否存在。需查找内容如果存在,则返回该内容在字符串中的位置,否则返回0,如图:
在数据抓取时,经常会遇到数据中夹杂一些用于排版的符号,例如:“\n”(回车换行符)等,但我们并不需要这些符号,此时就可以使用“字符串替换”命令将“\n”替换成""(空字符串),如图:
再看一个案例,某公司有一个员工管理系统,需要录入每个员工的信息,其中有一项需要录入员工的爱好,如果某员工有多个爱好,需要逐个进行录入。但员工提交的爱好都是字符串形式,例如“张三”提交的爱好是字符串“游泳,羽毛球,爬山”,这时我们需要把”张三“的爱好拆分成“游泳”、“羽毛球”、“爬山”三个字符串,然后再逐个录到系统中。可以使用“分割字符串”命令完成字符串分拆工作,如图:
从上图可以看到,最终拆分后的结果是数组,我们只需要遍历数组就可以将爱好逐个进行录入了。
UiBot经常会对企业的各种系统进行自动化操作,例如自动查询最近七天的销售数据等,此时需要在系统中输入七天前和今天的日期,获取今天的日期相对来说比较简单,可以使用“获取时间”命令来实现,在初级教程中提过该命令是获取从1900年1月1日起到现在经过的天数,所以我们可以通过“格式化时间”命令来把天数格式化成我们需要的字符串,如图:
那如何获取七天前的日期呢?您可能会想直接在日期的基础上减7即可,但如果今天是1号,减7则是一个负数,而且要考虑到每月的天数甚至跨年等问题,其实UiBot提供了一个“改变时间”命令,该命令可以很容易对时间进行加减,而不需要我们考虑每月天数之类的问题。
接下来即可通过键盘等命令将日期输入到目标系统中进行数据查询。时间模块还提供“时间戳”,“计算时间差”等非常实用的功能,在使用上类似,大家可以根据业务需求灵活运用。
一个信息系统中,最重要的就是数据,现在,几乎所有的信息系统都将数据存储在数据库中。除了使用客户端访问数据库之外,有时候,也需要直接对数据库进行访问和操作,因此,针对数据库的自动化操作也成为了RPA中不可或缺的一环。所谓数据库自动化操作,指的是在保证数据安全的前提下,直接使用用户名和密码登录数据库,并使用SQL语句对数据库进行操作。关于SQL的基础知识,请参见网络上的SQL教程
我们来看一下具体如何操作数据库。首先,需要连接数据库。在“软件自动化”的“数据库”目录下,选择并插入一条“创建数据库对象”命令,该命令将创建一个连接指定数据库的数据库对象。
“创建数据库对象”命令有三个属性:“数据库类型”属性指定了创建的数据库对象的类型,UiBot目前支持MySQL、SQL Server、Oracle、Sqlite3、PostgreSQL共五种数据库类型。“数据库配置”属性是一个字符串,这个字符串描述了创建数据库对象时的一些关键信息。这个字符串比较长,也不太容易看懂,不过没关系,点开这个属性可以看到,“数据库配置”属性由一些子属性组成。
第一个“charset”,指的是数据库的字符集,我们保持默认“utf8”不变即可;第二个“database”,指的是我们连接的数据库的名称;“host”和“port”指的是数据库的地址和端口号,这里我填的是“192.168.0.1”和“3306”,表明数据库可以通过“http://192.168.0.1:3306”进行访问;“user”和“password”指的是访问数据库的用户名和密码;通过配置上述几个参数,就可以成功创建数据库对象。
当然,每种类型的数据库,其参数可能不完全相同,比如Oracle数据库,没有“database”参数,只有“sid”参数,但是其含义是类似的。Sqlite3数据库跟另外三个数据库差别比较大:MySQL、SQL Server、Oracle是典型的关系型数据库,而Sqlite3是文件型数据库,因此Sqlite3的“数据库配置”属性,只有“filepath”一个子属性,指明了所操作的Sqlite3数据库文件的路径。新支持的PostgreSQL数据库,“数据库配置”属性与MySQL比较略有不同,但当前仅支持关系型特性的自动化操作,PostgreSQL其他的现代特性暂不支持。
“输出到”属性,这个属性填写一个变量名,这个变量会保存创建的数据库对象,在这里我们填写objDatabase
,后续的所有数据库操作都针对objDatabase
数据库对象进行。
成功创建数据库对象后,接下来可以对数据库进行操作了。UiBot提供两种数据库操作:一种是查询数据,对应“执行单SQL查询”和“执行全SQL查询”两条命令;一种是对数据库、表和表中数据进行修改,对应“执行SQL语句”和“批量执行SQL语句”两条命令。
我们先来看看“执行单SQL查询”命令,这条命令可以执行一条SQL查询语句,并且返回查询到的第一条结果。插入一条“执行单SQL查询”命令,可以看到这条命令有三个属性:一个是“数据库对象”属性,这个属性填入刚刚得到的数据库对象objDatabase
;一个是“SQL语句”属性,这个属性填入将要执行的查询语句,这里填入的是"select * from table1"
,意思是查询“table1
”表的所有数据,并返回第一条结果;第三个属性是“输出到”属性,这里填入一个变量iRet,表示SQL语句的执行结果,我们通过判断iRet的值来判断SQL语句是否成功执行。“sql语句参数”主要是用于动态的的构建SQL语句,本例中提到的“select * from table1”语句中“table1”是表名,但如果表名需要从某个网页或系统中获取时,那么该语句中就不能直接写“table1”,则是需要写成占位符,再通过“sql语句参数”将表名传递给占位符。不同的数据库占位符不同,具体可以将鼠标悬停在命令上查看。例如使用MySQL数据库时语句应该为“select * from %s”
“执行全SQL查询”命令则会返回查询到的全部结果,
最后切记,一定要记得使用“关闭连接”命令,关闭数据库连接。这条命令的唯一属性——“数据库对象”属性,填入数据库对象objDatabase
,即可关闭数据库连接。
在具体完成一个流程任务的时候,该优先选择有目标的命令,还是优先无目标的命令呢?我们给出的答案是:优选有目标命令!只要能获得恰当的界面元素作为目标,就应该优先考虑有目标的命令。因为无目标的命令,特别是使用无目标命令的过程中,依赖图像类命令,这些命令有以下的缺点:
首先,请牢记一个“小”字。在截图时,尽量截取较小的图像,只要能表达出所操作的界面元素的基本特征即可。在指定查找的区域时,尽量缩小区域。这样不仅速度会有所改善,而且也不容易受到遮挡的影响。比如下图中的“登录”按钮,没必要像左图一样,把整个按钮作为一幅图像来查找,只要像右图一样选择最关键的部分就可以了。
其次,大部分图像命令都支持“相似度”的属性,这个属性的初始值是0.9,如果设置过低,可能造成“错选”,如果设置过高,可能造成“漏选”(“错选”和“漏选”的概念请参考初级版教程的《目标编辑》章节)。可以根据实际情况进行调整,并测试其效果,选择最佳的相似度。
再次,屏幕的分辨率和屏幕的缩放比例对图像命令可能有非常关键的影响。因为在不同的分辨率下,软件的界面显示可能完全不一样,导致图像命令失效。所以,请尽量保持运行流程的计算机和开发流程的计算机的分辨率、缩放比例都是一致的。在Windows 10操作系统上设置分辨率和缩放比例的界面如下图所示:
最后,对于图像命令来说,经常需要和图像文件打交道。当需要使用图像文件时,我们固然可以用一个绝对路径来测试,如D:\\1.png
。但是,这就要求在运行此流程的计算机上,也必须在同一路径下有同样的文件,否则就会出错。有一个改进的方法,就是在您的流程所在的文件夹中,可以看到一个名为res的文件夹,把图像或其他文件放在这个文件夹中,并在流程中使用@res"1.png"
来代表这个文件即可。这样的话,当前流程发布到UiBot Worker使用的时候,也会自动带上这个文件。并且无论UiBot Worker把这个流程放在哪个路径下,都会自动修改@res
前缀所代表的路径,使其始终有效。
另外需要说明的是,本章所描述的图像类命令使用技巧,绝大部分也适用于OCR命令,大家在使用OCR相关功能的时候可以结合本节所讲的技巧,
UiBot拥有丰富的命令(预制件)库,总数量已达到四百多个,每个命令都有自己的属性,这一节主要介绍常用命令和属性的应用。
在B/S系统流程开发过程中,由于网速等原因,经常需要等待网页加载完成才能继续操作,部分同学喜欢使用“延时”命令进行等待,但实际上该命令在某些情况下是造成流程不稳定的因素之一,我们试想一下,大部分情况下一个页面3秒能加载完成,我们应该延时(等待)多久再对页面操作合适?有同学说当然是3秒,但是请注意,延时3秒的前提是大部分情况,如果网速卡顿时可能要等5秒甚至更久,但我们并不知道什么时候网络会卡顿,所以延时3秒还是5秒变成了难题,时间太短容易导致操作出错,时间太长牺牲流程的运行时效,所以最好的办法是进入页面后,使用“判断元素是否存在”或者“等待网页加载”之类实时检测的命令。另外如果想最大程度提高流程的运行时效,可以尝试将鼠标操作方式由“模拟操作”改为“后台操作”。
来看一个流程中常用的属性:“错误继续执行”。当使用“点击目标”命令时,被点击的目标消失了,UiBot则会提示流程异常,并停止继续运行,如图:
这是因为UiBot找不到目标元素导致的,假如需要点击的目标不重要,例如该目标不被点击也不会影响流程的运行结果,那么我们可以将属性“错误继续执行”设置为“是”,此时即使需要点击的目标消失,流程也会继续正常运行后续的步骤。
鼠标键盘命令中有一个比较重要的属性:“操作类型”,该属性有三个值分别是“模拟操作”、“后台操作”、“系统消息”,如图:
我们先来看一下他们的区别:
1、模拟操作:指通过调用系统API,例如:“mouseevent”等实现鼠标键盘操作,会实际移动光标 。
2、系统消息:指发送鼠标消息到目标元素,不移动光标。
3、后台操作:可以理解为调用了一次元素的鼠标响应回调函数。
那他们分别是在哪种场景下使用呢?
从使用层面来看,开发者不需要太过于关注底层的实现技术,即哪个合适用哪个。例如需要要看到鼠标的滑动轨迹来达到模拟人工操作的视觉效果,可以选择“模拟操作”;如果需要点击的目标经常被其他的界面元素遮挡,那么我们选择“系统消息”和“后台操作”会更为稳定。
当我们在使用键盘相关命令进行输入时,如果我们选择的操作类型为“模拟操作”,这时需要注意系统输入法是否为中文,因为模拟操作是调用系统的键盘鼠标功能,而系统键盘功能被调用时,输入法也会介入,例如:我们想在记事本中输入“how are you?”,由于当时系统输入法是中文,在记事本中将会出现“后卫啊热有?”,如图:
解决该问题有两种方法,第一种直接用“后台操作”或者“系统消息”,第二种将输入法设置为英文即可。
坐标偏移属性是鼠标命令特有的属性,它分为“横坐标偏移”和“纵坐标偏移”,我们来通过一个场景来理解它的作用。
下图中“跳转到官网”链接是一个标准的windows元素,它可以被UiBot有目标命令识别并选取,但图中”导出Excel文件“按钮是软件使用绘图方式画在界面上的,所以UiBot的有目标命令无法选取,但是已知的是”跳转到官网“和”导出Excel文件“中心点之间的距离是固定的,为150个像素点,根据本章《无目标命令操作技巧》的内容,使用UiBot点击”导出Excel文件“按钮最佳办法是,先选取”跳转到官网“链接作为“点击目标”命令的目标,再将“点击目标”命令的”横坐标偏移“设置为-150。
以上场景使用有目标命令来解决无目标元素的点击,相当于“声东击西”,真正要点击的目标不是我们选取的,而是与被选取元素有固定距离的图像,这也是换位思考解决问题的一种体现
“”
实参和形参
所谓函数,是指把一组常用的功能包装成一个语句块(称之为“定义”),并且可以在其他语句中运行这个语句块(称之为“调用”)。使用函数可以有效的梳理逻辑,以及避免重复代码的编写。
函数的定义和调用没有先后关系,可以先出现调用,再出现定义。但函数必须定义在全局空间中,也就是说,函数定义不能出现在其他函数定义、分支语句、循环语句下面的语句块中。
函数定义中可以包含参数,参数相当于是一个变量,但在调用时,可以由调用者指定这些变量的值。
定义函数的格式如下:
Function 函数名( )
语句块
End Function
Function 函数名(参数定义1, 参数定义2)
语句块
End Function
其中,参数定义的格式可以只是一个变量名
,也可以是变量名 = 表达式
的形式。对于后者来说,表示这个参数带有一个“默认值”,其默认值由“表达式”来确定。
如果函数有参数,则参数中的每个变量名都被认为是此函数内已经定义好的局部变量,无需使用Dim
语句定义。
在函数定义中,要退出函数并返回,采用以下写法:
Return 返回值
当执行到这一语句时,将跳出函数并返回到调用语句的下一行。返回的时候可以带一个返回值(具体作用下文叙述)。返回值可以忽略,默认为Null
。当执行到函数末尾的时候,无论有没有写Return
语句,都会返回。
例如:
Function Add(x, y=1) // 定义了两个参数的函数,第二个参数有默认值
Return x + y // 返回值为x+y的值
End Function
调用函数的格式如下:
返回 = 函数名(表达式1, 表达式2)
或者
函数名(表达式1,表达式2)
按照第一种格式调用,可以指定一个变量作为返回,当函数调用完成后,函数的返回值会自动赋值给这里的返回变量,调用者可以通过返回值,了解到函数调用的情况。此时,必须在被调用的函数名后面加圆括号。而当按照第二种格式调用时,调用者不需要返回值,则可以省略圆括号,使语句更符合自然语言习惯。
当调用时,相当于对函数中的参数进行了一次赋值运算,用表达式的值对其赋值。与赋值运算的规则相同,当表达式为一个独立的(没有使用任何运算符计算)数组、字典时,赋值操作只赋值其引用,也就是说,只是为变量增加一个“别名”。
调用函数时,传入的表达式的数量可以少于参数的数量。如果某个参数没有传入值,或者传入值为Null
,则采用其默认值。没有默认值的参数,调用函数时必须传入值或者表达式。
例如,对于上面定义的函数,可以按照如下的方式调用:
a = Add(100) // 调用Add函数,第二个参数取默认值1,所以a的值是101
b = Add(100, 200) // 调用Add函数,指定了两个参数,所以b的值是300
Add 100, 200 // 调用Add函数,不关心返回值,所以可以不写括号
当函数定义完成后,其名称可以作为一个函数类型的常量使用,也可以把函数名称赋值给某个变量,用这个变量也可以调用这个函数。
例如,对于上面定义的函数Add
,可以按照如下的方式使用:
Dim Plus = Add
TracePrint Plus(100, 200)
// 相当于先调用了Add函数,再用其返回值调用了TracePrint函数,结果是300