一起來擺脫教務(wù)系統(tǒng)強制教評的痛苦

文章的最后給出了使用方法,如果你沒有編程經(jīng)驗的話,按照底下的教程直接拿來用就可以啦。

故事是這么開始的

每學(xué)習(xí)期末都會被教務(wù)系統(tǒng)的教學(xué)質(zhì)量評價系統(tǒng)折騰的很慘,因為我必須完成所有科目的評價才能干別的事情。但是做這個評價又是一個非常痛苦的過程,每一個科目都要選一堆的項目,曾經(jīng)因為選了十幾門課,被教評狠狠地折騰到雙手殘廢。

image.png

我曾在空間里看到有同學(xué)發(fā)過自動填充表單的腳本,大致是這樣的

var divJs=frame.getElementById('divJs');
var items=divJs.querySelectorAll('select');
for(i=0;i<items.length;i++)
    items[i].value="1(完全同意)"

其實原理很簡單,就是查詢到所有評價項目的DOM,把它們的值逐一改成第一項就行了。運行這段腳本,頁面上所有的評價就會自動填好,這時只要點擊保存就可以了。
不過因為教務(wù)系統(tǒng)的網(wǎng)頁是一個框架結(jié)構(gòu),教評的頁面實際上是嵌在一個iframe里面的,所以我們要先讓這個頁面獨立地在一個新標(biāo)簽中打開,才能去運行這段腳本。

image.png

不過聰明的你一定能發(fā)現(xiàn)其中的缺陷,我們在保存完之后,瀏覽器就會跳轉(zhuǎn)到下一個科目的評價頁面,這時候我們剛才運行的腳本已經(jīng)被刪除掉了。于是我們就得在每個頁面把這個腳本粘貼到控制臺再運行。在課程非常多的情況下,評價的效率仍有很大的提升空間。

第一次優(yōu)化

這個時候我們正好可以利用教務(wù)系統(tǒng)這個框架結(jié)構(gòu)的特點,我們在父頁面運行腳本,讓子頁面在iframe跳轉(zhuǎn),腳本則可以一直保留在父頁面中。我們對最初的腳本做一些改動,讓父頁面獲取框架內(nèi)的DOM(因為它們是同域的),再把代碼封裝到函數(shù)內(nèi),每跳到一個新頁面執(zhí)行一次函數(shù)就行了。

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

這時,你一定能想到,既然都做到這一步了,干脆讓點擊保存按鈕這個步驟也自動化咯,這樣還省去了自己按按鈕的麻煩。這時候,我們再加入一個間隔計時器,設(shè)定每2秒鐘進行一次自動填充,并且保存。這樣只要執(zhí)行一次腳本,就可以嘩嘩嘩地運行到底啦。

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);

設(shè)定跳轉(zhuǎn)的結(jié)束邊界

很快我們就發(fā)現(xiàn)一個問題,當(dāng)保存完最后一個科目的評價時,就應(yīng)該提交了。但是由于計時器還在運行,這時候我們的框架還會不斷地刷新,雖然這時你直接點擊提交并且關(guān)閉頁面就沒事了,不過對于前端人員來說這樣子太不優(yōu)雅了。在這里加入一個判斷方式:在進入一個新頁面時,通過DOM獲取課程代碼,并保存在一個變量中。如果獲取到的代碼和上一次獲取的代碼是一樣的,說明最后一個科目已經(jīng)評價完成了,這時刪除定時器就可以了。

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);

優(yōu)化輪詢的方式

這里對計時器再進行一個改進,因為現(xiàn)在的執(zhí)行間隔是2秒,在遇到網(wǎng)速慢的情況,或者函數(shù)從任務(wù)隊列里彈出的時候正好DOM沒有加載出來,那就會產(chǎn)生錯誤。在剛才的基礎(chǔ)上,加入一個判斷,如果獲取不到課程代碼的DOM(忽略獲取課程代碼和評價選項的微小的時間差),則跳過這次輪詢,進入下一次就可以了。同時我們可以把輪詢時間調(diào)短到1秒1次,這對服務(wù)器來說還是沒有壓力的。

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插件的,不過這種一次性的東西,裝上還得卸掉也麻煩,就直接附上腳本的運行方式,不學(xué)編程的同學(xué)也可以拿來用喔。


附:大眾版使用方法

首先你要復(fù)制下面這段代碼

(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);
})();

打開教務(wù)系統(tǒng),進入教學(xué)評價頁面

image.png

打開瀏覽器的控制臺

多數(shù)瀏覽器的控制臺是按F12調(diào)出,或者在網(wǎng)頁上點擊右鍵->審查元素,在菜單里找一找有沒有開發(fā)者工具。打開面板后,選擇Console,就是控制臺了。

image.png

粘貼代碼回車,10秒搞定,這下就可以放飛自我地查成績了!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,027評論 25 709
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,679評論 18 399
  • 恰逢一縷清風(fēng), 牽走千絲躁動。 正好一片枯葉, 引來萬縷哀愁。
    妮梓閱讀 235評論 0 0
  • 我們總是這樣,越來越趨向于懶惰。 本來是很好的年紀(jì),年輕,應(yīng)該去接受很多新的東西,進行很多新的挑戰(zhàn),談一場說愛就愛...
    東八區(qū)區(qū)草閱讀 495評論 3 6
  • 也許終究是這樣的一個開始 , 可我還是沒有猜到故事的結(jié)局 我想: 我們還是孤寂的守在各自的航道 沒有...
    劉凱鋒閱讀 346評論 0 1

友情鏈接更多精彩內(nèi)容