文章的最后给出了使用方法,如果你没有编程经验的话,按照底下的教程直接拿来用就可以啦。
故事是这么开始的
每学习期末都会被教务系统的教学质量评价系统折腾的很惨,因为我必须完成所有科目的评价才能干别的事情。但是做这个评价又是一个非常痛苦的过程,每一个科目都要选一堆的项目,曾经因为选了十几门课,被教评狠狠地折腾到双手残废。
image.png我曾在空间里看到有同学发过自动填充表单的脚本,大致是这样的
var divJs=frame.getElementById('divJs');
var items=divJs.querySelectorAll('select');
for(i=0;i<items.length;i++)
items[i].value="1(完全同意)"
其实原理很简单,就是查询到所有评价项目的DOM,把它们的值逐一改成第一项就行了。运行这段脚本,页面上所有的评价就会自动填好,这时只要点击保存就可以了。
不过因为教务系统的网页是一个框架结构,教评的页面实际上是嵌在一个iframe里面的,所以我们要先让这个页面独立地在一个新标签中打开,才能去运行这段脚本。
不过聪明的你一定能发现其中的缺陷,我们在保存完之后,浏览器就会跳转到下一个科目的评价页面,这时候我们刚才运行的脚本已经被删除掉了。于是我们就得在每个页面把这个脚本粘贴到控制台再运行。在课程非常多的情况下,评价的效率仍有很大的提升空间。
第一次优化
这个时候我们正好可以利用教务系统这个框架结构的特点,我们在父页面运行脚本,让子页面在iframe跳转,脚本则可以一直保留在父页面中。我们对最初的脚本做一些改动,让父页面获取框架内的DOM(因为它们是同域的),再把代码封装到函数内,每跳到一个新页面执行一次函数就行了。
function autoFill() {
var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
var divJs = frame.getElementById('divJs');
var items = divJs.querySelectorAll('select');
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
}
autoFill();
image.png
这时,你一定能想到,既然都做到这一步了,干脆让点击保存按钮这个步骤也自动化咯,这样还省去了自己按按钮的麻烦。这时候,我们再加入一个间隔计时器,设定每2秒钟进行一次自动填充,并且保存。这样只要执行一次脚本,就可以哗哗哗地运行到底啦。
function autoFill() {
var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
var divJs = frame.getElementById('divJs');
var items = divJs.querySelectorAll('select');
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
frame.getElementById('Button1').click();
}
setInterval(autoFill, 2000);
设定跳转的结束边界
很快我们就发现一个问题,当保存完最后一个科目的评价时,就应该提交了。但是由于计时器还在运行,这时候我们的框架还会不断地刷新,虽然这时你直接点击提交并且关闭页面就没事了,不过对于前端人员来说这样子太不优雅了。在这里加入一个判断方式:在进入一个新页面时,通过DOM获取课程代码,并保存在一个变量中。如果获取到的代码和上一次获取的代码是一样的,说明最后一个科目已经评价完成了,这时删除定时器就可以了。
var courseCode;
var timer;
function autoFill() {
var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
var divJs = frame.getElementById('divJs');
var items = divJs.querySelectorAll('select');
var newCourseCode=frame.getElementById('pjkc').value;
if(newCourseCode==courseCode){
clearInterval(timer);
return;
}
courseCode=newCourseCode;
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
frame.getElementById('Button1').click();
}
timer=setInterval(autoFill, 2000);
优化轮询的方式
这里对计时器再进行一个改进,因为现在的执行间隔是2秒,在遇到网速慢的情况,或者函数从任务队列里弹出的时候正好DOM没有加载出来,那就会产生错误。在刚才的基础上,加入一个判断,如果获取不到课程代码的DOM(忽略获取课程代码和评价选项的微小的时间差),则跳过这次轮询,进入下一次就可以了。同时我们可以把轮询时间调短到1秒1次,这对服务器来说还是没有压力的。
var courseCode;
var timer;
function autoFill() {
var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
var divJs = frame.getElementById('divJs');
var items = divJs.querySelectorAll('select');
if(!frame.getElementById('pjkc'))
return false;
var newCourseCode=frame.getElementById('pjkc').value;
if(newCourseCode==courseCode){
clearInterval(timer);
console.log('评价完成');
return true;
}
courseCode=newCourseCode;
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
frame.getElementById('Button1').click();
}
timer=setInterval(autoFill, 1000);
收尾
最后,把我们的代码重新整理一下,封装到一个闭包里面,避免污染了全局作用域。一个用起来超爽的自动教评程序就完成了。
(function() {
var courseCode;
var timer;
var autoFill=function() {
var frame = document.getElementById('rightDiv').querySelector('iframe').contentWindow.document;
var divJs = frame.getElementById('divJs');
var items = divJs.querySelectorAll('select');
if (!frame.getElementById('pjkc'))
return false;
var newCourseCode = frame.getElementById('pjkc').value;
if (newCourseCode == courseCode) {
clearInterval(timer);
console.log('评价完成');
return true;
}
courseCode = newCourseCode;
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
frame.getElementById('Button1').click();
}
timer = setInterval(autoFill,1000);
})();
测试起来,速度堪比开车。本来想写成chrome插件的,不过这种一次性的东西,装上还得卸掉也麻烦,就直接附上脚本的运行方式,不学编程的同学也可以拿来用喔。
附:大众版使用方法
首先你要复制下面这段代码
(function() {
var courseCode;
var timer;
var autoFill=function() {
var frame = document.getElementById('rightDiv').getElementsByTagName('iframe')[0].contentWindow.document;
if (!frame || !frame.getElementById('pjkc'))
return false;
var divJs = frame.getElementById('divJs');
var items = divJs.getElementsByTagName('select');
var newCourseCode = frame.getElementById('pjkc').value;
console.log(newCourseCode,courseCode)
if (newCourseCode == courseCode) {
clearInterval(timer);
console.log('评价完成');
return true;
}
courseCode = newCourseCode;
for (i = 0; i < items.length; i++)
items[i].value = "1(完全同意)"
frame.getElementById('Button1').click();
}
timer = setInterval(autoFill, 2000);
})();
打开教务系统,进入教学评价页面
image.png打开浏览器的控制台
多数浏览器的控制台是按F12调出,或者在网页上点击右键->审查元素,在菜单里找一找有没有开发者工具。打开面板后,选择Console,就是控制台了。
image.png
网友评论