基于这篇入门教程和demo,我才能写出这款
基于chrome扩展的自动答题器。
2、开发背景
去年12月,某省委组织部举办了一系列学习竞赛活动,第一期时,参加人数寥寥,在第二期时,便通过党组织渠道要求所有党员保质保量的参加。
该活动可在专门的app上参加,也可通过官方网站参加。
既然是基于网页的并且支持chrome内核的考试系统,那自然能从前端入手进行操作。
3、主要功能迭代
2月21日,发布第一版答题器,主要功能有
3月4日,增加了了添加自定义试题及答案的功能。
3月20日,增加了全自动答题功能。
4月20日,增加了伪造回传鼠标点击坐标的功能。
5月14日,增加了在线更新的功能
至此,答题器的功能已基本成熟,最终答题器的界面如下:
4、结构拆解与代码分析
整个程序的存储由content部分来处理,存放于chrome.storage.local中,popup和inject在需要时从content更新数据,同时如果用户修改了设置也及时反映给content进行保存。
popup的js代码如下:(我觉得我备注的还可以)
content.js的代码:
在content和inject通讯中,我选择了在页面新建一个div元素,然后将通讯内容作为div元素的html。
优势是逻辑简单,可以直接使用jquery处理;
缺点是,破坏了页面原有结构,inject需要不停轮询该元素内容,通讯内容暴露,单项通讯
inject.js代码:
window.anslist为提前写入到程序中的基础题库,减少在线更新时数据通讯量;
因为只能从content接收指令,所以在inject中也保存了一份用户设置;
其中的ans_plus()函数则是整个答题器的核心,也是我最开始写的脚本部分。
逻辑很简单,
1遍历所有题目标签2{3找到题干;4在题库中匹配题干;5如果未匹配到6{7就用alert弹出提示8错题标记+19}10如果匹配到11{12获取所有选项并进行遍历13{14如果是单选并且选项等于该题目的答案15{16选中该选项;17continu;18}19如果是多选并且选项在该题目的答案中20{21选中该选项;22}23}24}25}26如果没有错误标记则自动交卷;以上,就是整个答题器中最重要的popup,content和inject中的js代码。
5、几个功能迭代。
从4月份期,为增加作弊难度,考试系统在每天都会增加几道新题。根据观察,是20道题中,在基础题库中抽取18道,在当日新题中抽取2道。
当时的对策是每天更新一次答题器,为了便于答题,答题器的所有用户每天都需要重新下载更新答题器。(群成员数暴涨)
5月13日,我重写了自定义新题的功能,可以批量添加多个新题。这样每天我只需要更新新题字符串,答题器用户将新题字符串导入答题器即可。
5月14日,在重新学了了小茗同学教程之后,实现了在线更新的功能。自定义新题字符串仅仅使用了两天便被淘汰。
服务器端代码:
1
数据的第一行是当前数据版本,后面则是题目/答案。依托于重写的自定义新题功能,自动更新非常顺利的实现了。
4月20日,经确认,考试系统加入了防作弊功能,原理是当鼠标点击“上一题”“下一题”或者题号时执行函数ClickButton,保存当前鼠标坐标,在交卷时同时传给服务器。
一开始我考虑的伪造回传数据,但数据经过了一点简单的计算,实在懒得跟他算计,
然后考虑的伪造下一题按钮的点击事件,但通过脚本触发的点击事件没有鼠标坐标信息,
最后忽然发现,我只要每次题目切换时,伪造一个事件(Event)作为参数传给反作弊的模块即可
varposx=Math.floor(800+Math.random()*200);
varposy=Math.floor(400+Math.random()*140);
ClickButton({'button':0,'clientX':Math.floor(posx+Math.random()*50),'clientY':Math.floor(posy+Math.random()*15)});6、写在最后
这个答题器功能实用,逻辑清晰,难度不算大,非常适合chrome扩展的学习和练手。