如何使用Sikuli自动化输入成绩?
手里明明有一份学生成绩Excel表格,却还得一一手动把它们输入到教务系统?类似这样的简单重复枯燥操作,其实你都可以一键让电脑自动替你完成。
(由于微信公众号外部链接的限制,文中的部分链接可能无法正确打开。如有需要,请点击文末的“阅读原文”按钮,访问可以正常显示外链的版本。)
痛点
期末了,学生们考完试,都愉愉快快放假回家了。
老师们呢?暂时还不能休息。
因为考试成绩,要在一定时间节点之前,录入系统。
在我们学校,这个时限是2周。否则系统一旦切换到下学期课程,本学期的成绩就无法录入了。
辛辛苦苦判完卷子,老师手里往往已经有了一份Excel,包含了全部的分数信息。
有人可能不解?为什么先要弄份Excel出来呢?
因为现在出题,都是有严格的规范要求的。
题型不能单一,题量不能太小,分值不能过于集中……
即便用论文或者报告结课,也需要给出详细的分项成绩。
所以,期末给各项小题分别打分之后,老师们需要跟小学生一样,训练连续加减法。
对于我自己的课来说,还更加麻烦。因为期末的卷面成绩不一定等于期末成绩,这里还有一个系数转换问题。
平时上机课优胜的同学,领先完成了MOOC证书的同学,承担了额外课程任务的同学……这些学生都有系数加分。最终的系数要乘以卷面成绩,放到期末成绩上。
所以,算成绩的时候要有乘法小数运算。
只是乘完了还不行。因为平时成绩占40分,期末成绩占60分。我平时成绩就是按照40分算的。可是系统录入的时候,却需要把它转换成百分制,这样才能保证平时比例加上期末比例刚好是1,否则是需要写情况说明的。
因此,我还需要把平时成绩做除法转换,从40分制转换为百分制。
另外,由于输入成绩必须是整数,因此中间出现的任何小数部分,都需要四舍五入处理……
这些算术题,你真的愿意每个都手算吗?
就算你愿意,你真的还能像十岁时那样,算得那么快,那么好吗?
你行我佩服,反正我做不到。
出于对学生负责的态度,我都是弄一个Excel表格,运用公式替我计算,最后得出总成绩。
顺便说一句,预先算出总成绩是很必要的。
在某些特殊情境下(例如预计挂科率过高),你得在保证名次顺序的情况下,合理变动成绩。在某些专业,这种操作需要运用到开方运算,就更是纸笔算力所不能及的了。
终于,老师们手里有一份最终版成绩了。
只要把这些Excel表格里面的成绩输入到系统,就算见到胜利曙光了。
每当这个时候,我都在教务系统的界面上,寻找“导入Excel”按钮。
但是,我一次次确认,面前的教务系统没有这项功能。
系统设计者,是家国内知名的软件企业。设计师们在用产品传达给教师用户一个信息:
小样儿的,别找了,老老实实手动录入成绩吧!
为了建设合谐社会,此处省略描述我心理活动的若干字词。
把Excel表格里面的成绩,手动搬家到教务系统这个事儿,不仅让人烦恼,而且还很容易出错。特别是一旦抄串行了,又没有及时发现而提交,后果不堪设想。
忍了。
好在一般我期末录入的成绩数量不超过100人。加上本人眼睛还没花,在校准数据,避免串行上还是能够勉强做到的。
但是,其他老师的工作量,就未必只有这些了。
有的老师教的是通修课,好几个班,数百人。成绩好容易都计算出来了,还得手动一一录入到系统。
每年到这个时候,许多老师想想成绩输入这回事儿,都会觉得头痛。
可是把成绩从Excel搬家到教务系统,真的就必须手动操作吗?
自动
答案是否定的。
即便系统没有提供导入功能。
因为这种数据搬家过程,根本就不需要什么酷炫的高科技,只需要让电脑傻傻地重复执行操作就可以了。
如果让你把Excel表格的内容完整录入到系统中,需要几步?
- 把光标移动到Excel的指定位置;
- 拷贝该数据;
- 切换到网络浏览器(成绩系统Web页面);
- 粘贴该数据;
- 把光标移动到下一个位置做准备;
- 切换回Excel里面;
- 光标移动到下一项;
- 返回第一步,循环执行。
看,跟把大象装冰箱一样容易。对不对?
这个成绩录入操作清单,下文中将被简称为“清单”。
请注意,其中每一个动作,都对应着操作系统的一个响应操作。
既然我们可以罗列一个清单出来,那么让电脑自动化替我们执行操作,也就有了基础。
我们需要一种特殊编程环境,可以表达与处理清单中的所有动作。
它可以模拟用户的按键输入,可以调用操作系统的窗口切换功能,还得能重复执行若干次动作。
有没有这样的编程环境呢?
环境
当然有。而且还有很多。
Windows上,有AutoHotkey;macOS上,有AppleScript。
但是它们都是单平台工具,而且都需要学习专用的操作语言(虽然并不复杂),这样你的技能就会被局限在某一种操作系统上,不能通用。
今天我推荐给你的这一种编程环境,叫做Sikuli。
它基于Java编写,因此跨平台毫无问题。而且它使用的语言,是Jython。
这个词儿,看着是不是眼熟?
对,它是一种基于Java的Python变种,所以叫做Jython。
这样一来,只要你有Python的编程基础,就可以非常轻易地使用Sikuli编程,来处理各种图形界面的操作了。
用这么强悍的工具来录入个成绩,确实是典型的大炮轰蚊子。
不过能轰蚊子,也是好事儿。
我们来看看如何安装Sikuli。
首先你需要到这个地址下载Sikuli的最新版本。本文写作的时候,最新版本是1.1.1。
点击右侧的“Get Version 1.1.1”,找到下载地址。前面说过,Sikuli是跨平台的工具,基于Java。它的下载文件是jar格式的。
下载之后,你还需要安装JDK 8,以提供Java底层运行环境。注意一定是版本8,因为版本9目前还不支持。
JDK 8的下载地址在这里。
我用的是macOS平台,下面的安装过程以苹果系统的安装方式来演示。如果你用的是Windows或者Linux,请参考对应的文档说明来安装对应Java环境。
在macOS下面,JDK 8的安装文件,是dmg格式。双击该文件,出现以下图标:
双击对话框中的pkg图标,开始安装。
安装成功后,会有以下提示:
JDK 8安装后,咱们就可以使用刚刚下载的jar文件,来安装Sikuli了。
我们到终端里,切换到下载目录,执行以下语句:
java -jar sikulixsetup-1.1.1.jar
屏幕上会显示一大堆文字提示,然后出现以下对话框。
勾选其中第一个分类,然后点击其中的第一小分项。之后继续。
遇到提示,询问下载地址。请选择“是”。
然后就会出现不同的文件下载提醒:
继续下载:
下载完毕以后,安装过程继续提示是否安装Jython 2.7.0。
选择是。
Jython下载完毕,安装过程顺利结束,会弹出以下对话框:
好了,至此我们的环境安装配置过程就完成了。
演示
下面,咱们来演示一下用Sikuli自动录入成绩的使用效果。
我建立了一个github项目,用于给你演示自动化程序录入。
请点击这个链接,下载压缩包。然后在本地解压。作为咱们的演示目录。
目录中,除了说明文件(README.md)之外,一共只有三个文件。
- scorelist.xlsx,是我们的成绩单文件;
- score-input.html,是一个模拟成绩登录系统页面;
- demo-score-input.sikuli,是我们即将调用的Sikuli脚本源文件。
先看看我们的成绩单文件。
为保护真实世界的学生隐私,这里我们没法用真名和真实学号,所以模拟了一份成绩单。
我们也不能把学校的教务系统原原本本展示出来,所以只依样画葫芦,做了个最简单的成绩录入页面。
请确保使用Google Chrome浏览器打开该html文件。
这里只有10个学生的信息。我们需要录入他们的平时成绩和期末成绩。由于没有备注信息需要录入,所以这一列应该都空着。
我们演示一下Sikuli的执行过程。
进入Sikuli,启动过程需要几秒钟。中间你会看到这样的提示:
进入主界面:
我们定位到演示目录,打开其中的demo-score-input.sikuli文件。
打开后,我们就能看到脚本内容了:
对于已经等得不耐烦的老师,咱们先来介绍一下用法:
首先我们到Excel里面,把光标定位到第一个同学的平时成绩。
然后到Chrome浏览器里,把光标同样定位在第一个同学的平时成绩录入框。
然后切换到Sikuli里,执行运行按钮:
好了,操作完毕。
点击运行按钮后,你会看到如这段视频展示的情景:
注意,这个视频中,除了开始的点击运行按钮是人在操作外,后面所有的动作,都是计算机自动执行的,直到成绩全部录入完毕。
是不是看得眼花缭乱,跃跃欲试了?
代码
别着急。
为了让你自己能够通过对脚本细微修改,满足实际分数录入的需要,我们来简单阅读一下代码。
放心,代码并不长。
第一行代码,我们指定了n的数值。
n = 10
在Excel里,每一个学生的成绩,包括平时和期末,作为一条记录。
这样的记录一共有10条,所以这里我们设定一共需要循环处理的条目数为10次。
假设你班上有50人,可以将其设定为50,以此类推。
紧接着,是一条循环语句:
for i in range(n):
这就是告诉Sikuli,我们要循环执行内部的全部语句,执行次数由前面的n指定。
我们把循环内部的代码分成了4个部分,一一来看。
首先,是从Excel里面拷贝平时成绩。
switchApp("Microsoft Excel")
sleep(0.1)
type("c", Key.CMD)
sleep(0.1)
type("c", Key.CMD)
type(Key.RIGHT)
sleep(0.2)
注意我们采用switchApp()
函数来指定切换到哪一个应用。
应用的名称怎么设置呢?
很简单,在macOS下面,把鼠标移动到屏幕下方Dock上面的对应图标上,看到的提示就是应用的正式名称。照着写就可以。
其中出现了3条sleep()
语句。它们并不是实际执行什么内容,而是让电脑歇一下,不要急于执行下面的语句。
这是因为,有些操作需要一定的响应时间。
如果上一步操作的结果还没有响应,你就急匆匆紧接着执行下面的动作,可能会把原先的计划打乱,导致操作失误。例如还没有拷贝好内容,就进行粘贴,显然是不行的。
因此,几乎每一步操作后,我们都加上一个休眠时间,单位为秒。
另外出现的一个函数为type()
。
以这一句为例:
type("c", Key.CMD)
我们让Sikuli替我们按下键盘上的c键,同时还要按下控制按键Cmd。
在macOS里面,Cmd + c用来拷贝数据。如果你在Windows下,需要将其修改为Ctrl键。
这样一解释,这一段代码的含义就很清晰了。
我们做了以下动作:
- 切换到了Excel;
- 执行了拷贝;
- 又执行了一遍拷贝;
- 光标右移一格(到了期末成绩)
每一步之间,我们都让Sikuli休眠一会儿,以保证系统成功响应。
这里解释一下,为什么进行了2步拷贝。
因为在macOS里面,Excel, Word这些应用有时候用快捷键进行拷贝操作时,会出现没有成功拷贝的情况。所以为了保险起见,我不得不经常强迫症一样按下同样的操作键两次。
这里,我们让Sikuli一样执行保守操作。
好了,有了上面的知识基础,我们再来看看下面这段Web浏览器页面操作代码:
switchApp("Google Chrome")
sleep(0.1)
type("a", Key.CMD)
type("v", Key.CMD)
type(Key.TAB)
sleep(0.2)
怎么样,很容易就理解了吧?
梳理一下,我们做了以下操作:
- 切换到了Chrome浏览器;
- 选中当前文本框内容;
- 把剪贴板里面的平时成绩粘贴;
- 按TAB键,切换到下一个输入文本框(期末成绩)。
之后,我们又回到Excel继续操作:
switchApp("Microsoft Excel")
sleep(0.1)
type("c", Key.CMD)
sleep(0.1)
type("c", Key.CMD)
type(Key.DOWN)
sleep(0.1)
type(Key.LEFT)
sleep(0.2)
这一段代码,我们做了以下动作:
- 切换到了Excel;
- 执行了拷贝;
- 又执行了一遍拷贝;
- 光标下移一格(到了新记录的期末成绩);
- 光标左移一格(到了新记录的平时成绩)。
然后,我们又回到了Chrome。
switchApp("Google Chrome")
sleep(0.1)
type("a", Key.CMD)
type("v", Key.CMD)
type(Key.TAB)
sleep(0.1)
type(Key.TAB)
sleep(0.2)
最后这段代码,我们做了以下操作:
- 切换到了Chrome浏览器;
- 选中当前文本框内容;
- 把剪贴板里面的平时成绩粘贴;
- 按TAB键,切换到下一个输入文本框(备注);
- 按TAB键,切换到下一个输入文本框(新记录的平时成绩)。
好了,这就是全部需要循环的代码了。在Excel和Chrome里,光标都指向了下一条记录的平时成绩位置。
这样再次循环的时候,就是下一条记录的输入了。依此类推。
如果你使用的系统输入界面,和我们的系统有区别,也可以根据上述命令的含义,自行调整细节,以便成功输入。
只是千万不要忘了,在语句之间用sleep()
来稍作停顿。
小结
本文我为你展示了如何利用Sikuli编程环境和自动化Jython脚本,把原本枯燥的成绩录入动作,变成一键搞定。
回顾一下,我们介绍了以下内容:
- 不同操作系统平台上的几个典型自动化脚本工具;
- 如何安装JDK运行环境;
- 如何安装Sikuli;
- 如何执行Sikuli脚本;
- 如何阅读和修改Sikuli脚本中的Jython代码。
还是那句话,用这么强悍的自动化脚本工具来输入个考试成绩,简直是委屈了它。
其实,Sikuli具有基本图标识别和像素级定位操作能力,被广泛应用于软件测试、桌面监控等领域。
如果你对它感兴趣,推荐你从官方的文档开始,深入阅读学习。
讨论
除了输入成绩以外,你还遇到过哪些需要重复执行枯燥操作指令的场景?你觉得Sikuli能否帮助你有效接管这些繁复的机械动作?除了Sikuli,你还用过哪些好用的自动化脚本工具?欢迎留言,把你的经验和思考分享给大家,我们一起交流讨论。
上一篇: 电脑端自动测试工具
下一篇: 如何设置自动点击鼠标
推荐阅读
-
位、字节、WORD、DWORD 的区别和联系 - Unicode 和 ANSI 的区别就像输入法中 "全宽 "和 "半宽 "的区别一样。 由于不同的 ANSI 编码有不同的标准(不同的字符集),对于给定的多字节字符串,我们必须知道它使用的是哪种字符集,才能知道它包含哪些 "字符"。对于 UNICODE 字符串来说,无论环境如何,它所代表的 "字符 "内容始终是相同的。Unicode 有一个统一的标准,定义了世界上大多数字符的编码,因此拉丁文、数字、简体中文、繁体中文和日文都可以存储在一个编码中。统一码是一个统一的标准,定义了世界上大多数字符的编码。 比特(Bit)和字节(Byte)的区别:例如USB2.0 标准接口的传输速率为 480Mbps,有一些人误认为是每秒 480 兆比特,同样网络带宽为 2MB,就容易误认为是每秒 2 兆比特。其实,480Mbps 应该是 480 兆比特/秒或 480 兆字节/秒,它等于 "60 兆字节/秒";同样,2MB,应该是 256 兆字节/秒。 Bit 和 Byte 译为 "比特",都是数据计量单位,比特="位 "或 "比特"。 Byte = 字节,即 1byte = 8bits,两者的换算关系为 1:8。 Mbps = mega bits per second(兆位/秒)是速率单位,因此 2M 带宽应为 2 兆位/秒,即 2MBps。MB = 兆字节(Megabytes,兆字节)是单位量,1MB/S(兆字节/秒)= 8MBPS(兆字节/秒)。 通常所说的硬盘容量是指 40GB、80GB、100GB,其中的 B 是指 Byte 也称为 "字节"。 1 KB=1024 字节 1 MB=1024 KB=1024*1024 字节 1 GB=1024 MB=1024*1024*1024 字节 例如,以前所谓的 56KB MODEM 转换过来的 56KBps 除以 8 就是 7Kbyte,所以真正从网上下载文件存在硬盘上的速度也是每秒 7Kbyte;也就是说,用 B 表示传输速度一般指 Bit;用 B 表示容量一般指 Byte。比特、字节、WORD、DWORD 的本质。
-
如何使用 Java 输入语句
-
手把手教你如何注册谷歌账号--这个手机号不能用来验证。于是人们想当然地认为,谷歌退出的原因,并不是对国内手机号验证通过。其实不然,根据谷歌的注册机制,这是注册时的第一次验证,也属于机器验证,即判断注册者是否为机器人,以防止滥用,所以这次验证只是纯粹的手机号验证,并不是绑定手机号。 那么我们就有疑问了,第一次验证要求手机号验证却显示手机号无法验证,这不是自相矛盾吗? 谷歌现在在全球至少有14亿注册用户,所以谷歌对注册的网络、机器要求非常严格,可以说是判断筛选机制,你的网络、机器或者浏览器身份验证,不符合谷歌机器认证,就不允许你验证通过,而不是因为手机号的问题。不信的朋友可以换个美国手机号输入试试,同样显示这个手机号无法验证。 所以我不建议使用代理网络注册,因为那是一个共享通道,已经被滥用了,这个时候遇到无法验证也就不奇怪了,即使有些朋友侥幸通过了验证,这个号码也活不了多久,因为很快就会被检测出是什么ip注册的,然后出现异常验证,甚至直接封号,这个时候你就后悔晚矣。所以对于QQ邮箱谷歌注册入口,笔者强烈不推荐这样做,因为QQ邮箱注册早就被滥用了,会有那么多人会遇到异常验证的情况。 异常验证在你输入任何手机号码的情况下都会显示无法验证或者手机号码验证次数过多。
-
如何使用 PHP 正则表达式验证输入字符串是否为正确的手机号码、座机号码或 400 电话号码格式
-
如何使用 Java 中的自动化测试工具实施持续集成和自动化测试?
-
纯干货分享 | 研发效能提升——敏捷需求篇-而敏捷需求是提升效能的方式中不可或缺的模块之一。 云智慧的敏捷教练——Iris Xu近期在公司做了一场分享,主题为「敏捷需求挖掘和组织方法,交付更高业务价值的产品」。Iris具有丰富的团队敏捷转型实施经验,完成了企业多个团队从传统模式到敏捷转型的落地和实施,积淀了很多的经验。 这次分享主要包含以下2个部分: 第一部分是用户影响地图 第二部分是事件驱动的业务分析Event driven business analysis(以下简称EDBA) 用户影响地图,是一种从业务目标到产品需求映射的需求挖掘和组织的方法。 在软件开发过程中可能会遇到一些问题,比如大家使用不同的业务语言、技术语言,造成角色间的沟通阻碍,还会导致一些问题,比如需求误解、需求传递错误等;这会直接导致产品的功能需求和要实现的业务目标不是映射关系。 但在交付期间,研发人员必须要将这些需求实现交付,他们实则并不清楚这些功能需求产生的原因是什么、要解决客户的哪些痛点。研发人员往往只是拿到了解决方案,需要把它实现,但没有和业务侧一起去思考解决方案是否正确,能否真正的帮助客户解决问题。而用户影响地图通常是能够连接业务目标和产品功能的一种手段。 我们在每次迭代里加入的假设,也就是功能需求。首先把它先实现,再逐步去验证我们每一个小目标是否已经实现,再看下一个目标要是什么。那影响地图就是在这个过程中帮我们不断地去梳理目标和功能之间的关系。 我们在软件开发中可能存在的一些问题 针对这些问题,我们如何避免?先简单介绍做敏捷转型的常规思路: 先做团队级的敏捷,首先把产品、开发、测试人员,还有一些更后端的人员比如交互运维的同学放在一起,组成一个特训团队做交付。这个团队要包含交付过程中所涉及的所有角色。 接着业务敏捷要打通整个业务环节和研发侧的一个交付。上图中可以看到在敏捷中需求是分层管理的,第一层是业务需求,在这个层级是以用户目标和业务目标作为输入进行规划,同时需要去考虑客户的诉求。业务人员通过获取到的业务需求,进一步的和团队一起将其分解为产品需求。所以业务需求其实是我们真正去发布和运营的单元,它可以被独立发布到我们的生产环境上。我们的产品需求其实就是产品的具体功能,它是我们集成和测试的对象,也就是我们最终去部署到系统上的一个基本单元。产品需求再到了我们的开发团队,映射到迭代计划会上要把它分解为相应的技术任务,包括我们平时所说的比如一些前端的开发、后端的开发、测试都是相应的技术任务。所以业务敏捷要达到的目标是需要去持续顺畅高质量的交付业务价值。 将这几个点串起来,形成金字塔结构。最上层我们会把业务目标放在整个金字塔的塔尖。这个业务目标是通过用户的目标以及北极星指标确立的。确认业务目标后再去梳理相应的业务流程,最后生产。另外产品需求包含了操作流程和业务规则,具需求交付时间、工程时间以及我们的一些质量标准的要求。 谈到用户影响的地图,在敏捷江湖上其实有一个传说,大家都有一个说法叫做敏捷需求的“任督二脉”。用户影响地图其实就是任脉,在黑客马拉松上用过的用户故事地图其实叫督脉。所以说用户影响地图是在用户故事地图之前,先帮我们去梳理出我们要做哪些东西。当我们真正识别出我们要实现的业务活动之后,用户故事地图才去梳理我们整个的业务工作流,以及每个工作流节点下所要包含的具体功能和用户故事。所以说用户影响地图需要解决的问题,我们包括以下这些: 首先是范围蔓延,我们在整张地图上,功能和对应的业务目标是要去有一个映射的。这就避免了一些在我们比如有很多干系人参与的会议上,那大家都有不同想法些立场,会提出很多需求(正确以及错误的需求)。这个时候我们会依据目标去看这些需求是否真的是会影响我们的目标。 这里提到的错误需求,比如是利益相关的人提出的、客户认为产品应该有的、某个产品经理需求分析师认为可以有的....但是这些功能在用户影响地图中匹配不到对应目标的话,就需要降低优先级或弃掉。另外,通常我们去制定解决方案的时候,会考虑较完美的实现,导致解决方案括很多的功能。这个时候关键目标至关重要,会帮助我们梳理筛选、确定优先级。 看一下用户影响到地图概貌 总共分为一个三层的结构: 第一层why,你的业务目标哪个是最重要的,为什么?涉及到的角色有哪些? 第二层how ,怎样产生影响?影响用户角色什么样的行为? (不需要去列出所有的影响,基于业务目标) 第三层what,最关键的是在梳理需求时不需一次把所有细节想全,这通常团队中经常遇到的问题。 我们用这个例子来看一下 这是一个客服中心的影响地图,业务目标是 3个月内不增加客服人数的前提下能支持1.5倍的用户数。此业务目标设定是符合 smart 原则的,specific非常的具体,miserable 是可以衡量的,action reoriented是面向活动的, real list 也是很实际的。 量化的目标会指引我们接下来的行动,梳理一个业务目标,尽量去量化,比如 :我们通过打造一条什么样的流水线,能够提高整个部署的效率,时间是原来的 1/2 。这样才是一个能量化的有意义的目标。 回到这幅图, how 层级识别出来的内容,客服角色:想要对它施加的影响,把客户引导到论坛上,帮助客户更容易的跟踪问题,更快速的去定位问题。初级用户:方论坛上找到问题。高级用户:在论坛上回答问题。通过我们这些用户角色,进行活动,完成在不增加客户客服人数的前提下支持更多的用户数量。 最后一个层级,才是我们日常接触比较多的真正的功能的特性和需求,比如引导到客户到论坛上,其实这个产品就需要有一个常见问题的论坛的链接。这个层次需要我们团队进一步地在交付,在每个迭代之前做进一步的梳理,细化成相应的用户故事。 这个是云智慧团队中,自己做的影响地图的范例,可以看下整个的层级结构。序号表示优先级。 那我们用户影响地图可以总结为:
-
新手如何使用 Postman 进行界面自动化测试
-
色选机智能工厂 自动化流水线生产的使用将如何改变色选机
-
如何在 ubuntu 启动时指定 qt 程序使用指定用户运行?要使用指定用户,你需要自动输入该用户的密码。
-
使用硒库的网络自动化如何移除自动化徽标、禁用浏览器关闭窗口并关闭保存密码提示框