一起来摆脱教务系统强制教评的痛苦

文章的最后给出了使用方法,如果你没有编程经验的话,按照底下的教程直接拿来用就可以啦。

故事是这么开始的

每学习期末都会被教务系统的教学质量评价系统折腾的很惨,因为我必须完成所有科目的评价才能干别的事情。但是做这个评价又是一个非常痛苦的过程,每一个科目都要选一堆的项目,曾经因为选了十几门课,被教评狠狠地折腾到双手残废。

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里面的,所以我们要先让这个页面独立地在一个新标签中打开,才能去运行这段脚本。

image.png

不过聪明的你一定能发现其中的缺陷,我们在保存完之后,浏览器就会跳转到下一个科目的评价页面,这时候我们刚才运行的脚本已经被删除掉了。于是我们就得在每个页面把这个脚本粘贴到控制台再运行。在课程非常多的情况下,评价的效率仍有很大的提升空间。

第一次优化

这个时候我们正好可以利用教务系统这个框架结构的特点,我们在父页面运行脚本,让子页面在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

粘贴代码回车,10秒搞定,这下就可以放飞自我地查成绩了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,567评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,293评论 18 399
  • 恰逢一缕清风, 牵走千丝躁动。 正好一片枯叶, 引来万缕哀愁。
    妮梓阅读 197评论 0 0
  • 我们总是这样,越来越趋向于懒惰。 本来是很好的年纪,年轻,应该去接受很多新的东西,进行很多新的挑战,谈一场说爱就爱...
    东八区区草阅读 375评论 3 6
  • 也许终究是这样的一个开始 , 可我还是没有猜到故事的结局 我想: 我们还是孤寂的守在各自的航道 没有...
    刘凯锋阅读 311评论 0 1