自动评教js脚本的实现

一、引子

​ 学校每个学期都会让同学们在线对每个老师的教学进行评教。每个老师的课点击后会弹一个表单,表单里面有若干单选和输入,如果你选的课比较多的话,单选框简直要点到爆炸!所以,为了节省劳力(懒),我觉得让代码来做这种事情。因为是在线评教,所以很自然的选择javascript脚本来实现。

首先分析这个神奇的评教页面:

这里写图片描述

这个是我已经评教过的,没评教之前超链接显示的是“评价”。当我们点击“评价”后弹出表单:

这里写图片描述

那么我们只需要遍历这个表单就行了。正好复习以下js的原生写法。

好,我们先来定位到这个表单:

这里写图片描述

它竟然是一个iframe!介于学校教务的历史原因,虽然无*可说,但还是滚去看看iframe的用法。

二、iframe的用法

iframe其实就是个html页面,包含window和document对象。

<iframe id="iframe1" src="frame1.html"></iframe>  

<script type="text/javascript">  
    //获取iframe的document对象         
    //方法1  
    var iframe = document.getElementById('iframe1').contentWindow.document;  

    //方法2  
    function getIframeDom(iframeId) {  
        return document.getElementById('iframe1').contentDocument ;  
    }  
</script>  

注意:这里的contentWindow.docement就等于contentDocument对象,只是contentDocument对象ie不兼容。

ok,如果是简单一点的页面iframe只要获取到了document对象后就像正常一样操作了。

但是,我们学校的神级页面,不仅有父页面,还有子页面,还有孙页面,还有孙孙页面,子子孙孙无穷尽也

经过我踩过的坑,在这里mark一下:

iframe只能获取当前页面document的元素,要获取孙页面的元素,需要切换到父页面的contentWindow!

所以,为了找到这个表单的iframe我可是费了不少劲。

在这里要提一个找元素的小技巧:在chrome中的Element选项卡里,可以这样看到一个元素的路径:

这里写图片描述

然后一个一个contentWindow地切换,最后的路径如下:

var frame_1 = document.getElementById('frmbody').contentDocument
    .getElementById('frmDesk').contentDocument
    .getElementById('frame_1').contentDocument;

三、模拟用户点击

要弹出这个表单,首先要点击那个超链接啊!所以就要模拟用户的点击动作。

//找到所有评价超链接
var atag = frame_1.getElementById('frmReport').contentDocument.getElementsByTagName("a");
for (var i = 0; i < atag.length; i++) {
    var a = atag[i];
    if (a.innerText == "评价") {
        console.log("**************************************************");
        a.click();//点击动作
        console.log("点击了评价!");
        setTimeout("autoAssess()",1000);
    }
}

特别注意

  1. js里面的延时执行函数是setTimeout(code,time)。这里的code是js代码,必须有!!!!
  2. 这里必须要稍作延时再执行填表单操作,因为这里模拟的是真实的用户行为。之前因为没加这个延时,导致这个表单frame的document始终获取不到,查了好久才发现当你执行填表单操作时那个表单还没有load成功。

关于页面的confirm框(这是一个大坑):

​ 因为后续页面提交的时候会出现一个confirm框让用户确定,本来我也想通过代码模拟点击这个confirm框的确定,当时Google一圈后发现,这个confirm是系统级的命令,必须由用户亲自点击,如果让程序可以执行会增加风险(黑人问号)!如果有能实现模拟点击confirm框的朋友可以告诉我。

​ 如果不做处理将有一个课程弹一个confirm叠加!

​ 那么我是怎样处理这个confirm的呢?好吧,我怂,只能用户点击了。做不到全自动那就半自动吧。于是在每个confirm弹出的时候,我等几秒让用户点击咯。

if (input.id == "butSave") {
    alert("下面会有4秒钟让你点击确定提交,准备好了吗?");
    input.click();
}

这个坑我卡了很长时间,现在我就知道了,在浏览器里执行自己的js脚本时,脚本就是用户

四、js操作html元素

到这里我们终于得到了表单,开始执行我们的autoAssess()吧。

  1. 单选怎么选?

    input.checked = "true";
  2. input type=”text”怎么填?

    input.value = 95;
  3. 怎样找没有id的元素?

    firstElementChild、nextElementSibling…..动用一切手段。

  4. 为了体验更好,要让自己知道已经评教过了哪些课程。

    那就获取表单中的课程信息显示一下咯。

  5. 执行脚本的时候报不关我们事的异常?

    比如原页面在关闭的时候会调用closeWindow方法,closeWindow里面有个CollectionGarbage()方法。
    这是IE里面内存清理的函数,在chrome里面直接出error,程序终止。
    解决:用try    catch     包围,catch里面不处理

五、最终代码

function autoAssess() {
    //console.log(frame_1);
    var questionFrame = frame_1.getElementById("CKWindowContainer").firstElementChild.nextElementSibling;
    //console.log(questionFrame.contentDocument);
    //用try_catch忽略爆出的傻x异常
    try {
        doit();
    }catch (e) {
        console.log(e);
    }
    function doit() {
        //获取课程信息
        var classInfo = "";
        var form = questionFrame.contentDocument.getElementById("ActionForm");
        //console.log("form:"+form);
        var childs = form.childNodes;
        // console.log("form nodes:"+childs);
        for (var i = 0; i < childs.length; i++) {
            if (childs[i].tagName == "TABLE") {
                var td = childs[i].firstElementChild.firstElementChild.nextElementSibling.firstElementChild;
                classInfo += td.innerHTML;
                break;
            }
        }
        //遍历填表单
        var inputs = questionFrame.contentDocument.getElementsByTagName("input");
        for (var i = 0; i < inputs.length; i++) {
            var input = inputs[i];
            //console.log("type:" + inputs[i].type + "----id:" + inputs[i].id + " name:" + inputs[i].name + " value:" + inputs[i].value);
            if (input.type == "radio") {
                var radioID = input.id;
                if (radioID.substring(0, 3) == "wdt" && radioID.charAt(radioID.length - 1) == '1') {
                    input.checked = "true";
                }
                if (radioID == "radio0_0" || radioID == "radio1_1" || radioID == "radio2_0" || radioID == "radio3_0") {
                    input.checked = "true";
                }
            }
            if (input.type == "text") {
                input.value = 95;
            }
            if (input.id == "butSave") {
                alert("下面会有4秒钟让你点击确定提交,准备好了吗?");
                input.click();
            }
        }
        //等待点击提交完毕
        setTimeout(function () {
            alert(classInfo.substring(0, classInfo.indexOf("&")).trim() + "!!!!!评教完毕!!!!!");
            console.log(classInfo.substring(0, classInfo.indexOf("&")).trim() + "!!!!!评教完毕!!!!!");
        },4000);
    }
}

//一层一层找到评教页面
var frame_1 = document.getElementById('frmbody').contentDocument
    .getElementById('frmDesk').contentDocument
    .getElementById('frame_1').contentDocument;
//找到所有评价超链接
var atag = frame_1.getElementById('frmReport').contentDocument.getElementsByTagName("a");
for (var i = 0; i < atag.length; i++) {
    var a = atag[i];
    if (a.innerText == "评价") {
        console.log("**************************************************");
        a.click();
        console.log("点击了评价!");
        setTimeout("autoAssess()",1000);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_37540865/article/details/80498117