VB.net 2010 視頻教程 VB.net 2010 視頻教程 VB.net 2010 視頻教程
SQL Server 2008 視頻教程 c#入門經典教程 Visual Basic從門到精通視頻教程
  • JavaScript教程之一個基于chrome擴展的自動答題器

  • 2019-04-17 20:46 來源:未知

魔兽世界wow www.geyjm.icu 1、寫在前面

首先感謝小茗同學的文章-【干貨】Chrome插件(擴展)開發全攻略,

基于這篇入門教程和demo,我才能寫出這款

基于chrome擴展的自動答題器。

git地址: https://gitee.com/cifang/lighthouse_answering_machine.git

2、開發背景

去年12月,某省委組織部舉辦了一系列學習競賽活動,第一期時,參加人數寥寥,在第二期時,便通過黨組織渠道要求所有黨員保質保量的參加。

該活動每期10天,每天有一次答題機會,每一期通過分享可獲得額外兩次。每次答題則是在題庫中隨機抽?。ê罄捶⑾植⒉荒敲此婊┑パ『投嘌」?0道題。

該活動可在專門的app上參加,也可通過官方網站參加。

既然是基于網頁的并且支持chrome內核的考試系統,那自然能從前端入手進行操作。

3、主要功能迭代

1月11日,開發出腳本版本答題器。通過控制臺(F12)運行腳本并自動作答。2月初,開始學習chrome擴展相關內容

2月21日,發布第一版答題器,主要功能有

  • 1、打開活動主頁、用戶登錄頁;
  • 2、清除登錄信息;
  • 3、記錄并切換帳號;
  • 4、自動標記正確答案;
  • 5、自動答題并交卷。 

3月4日,增加了了添加自定義試題及答案的功能。

3月12日,增加了用戶信息導入導出功能,自動分享獲取答題次數功能。

3月20日,增加了全自動答題功能。

4月20日,增加了偽造回傳鼠標點擊坐標的功能。

5月14日,增加了在線更新的功能

至此,答題器的功能已基本成熟,最終答題器的界面如下:

4、結構拆解與代碼分析

chrome擴展的文檔結構在小茗同學的文章中描述的很清楚了。為了便于開發,我最終決定使用popup,content 和 inject 相互配合通訊來實現本程序的功能。

整個程序的存儲由 content 部分來處理,存放于 chrome.storage.local 中,popup和inject在需要時從 content 更新數據,同時如果用戶修改了設置也及時反映給 content 進行保存。

popup的js代碼如下:(我覺得我備注的還可以)

復制代碼
  1 var config;//設置
  2 var auto_all_ans=0;//全自動答題標志
  3 
  4 $(function() {
  5 
  6     // 加載設置
  7     //config = {'set':{'save_login': 1, 'sign_ans': 1, 'auto_ans': 0}, 'login_info':{}, 'active':''}; // 默認配置
  8 
  9     //打開活動頁面
 10     $('#open_page').click(function()
 11     {
 12         chrome.tabs.create({url: '//xxjs.dtdjzx.gov.cn/index.html'});
 13     })
 14     //打開登陸頁面
 15     $('#open_login_page').click(function()
 16     {
 17         getCurrentTabId(tabId => {
 18             chrome.tabs.update(tabId, {url: 'https://sso.dtdjzx.gov.cn/sso/login'});
 19         });
 20     })        
 21     //清除登錄信息
 22     $('#open_logout_page').click(function()
 23     {
 24             sendMessageToContentScript(    
 25             {'cmd':'logout','data':{}},
 26             //回調函數
 27             function(response){if(response) {}}
 28             );
 29             //刪除active類
 30             $('.active').removeClass('active');
 31     })
 32 
 33     //顯示、隱藏設置區域
 34     $('#hide_config').click(function(){
 35         $('#hide_config').hide();
 36         $('#show_config').show();
 37         $('#config').hide(500);    
 38     })
 39     $('#show_config').click(function(){
 40         $('#show_config').hide();
 41         $('#hide_config').show();
 42         $('#config').show(500);    
 43     })    
 44 
 45         
 46     //手動更新
 47     $('#update').click(function(){
 48         $(this).html('更新中...');
 49         $(this).css('pointer-events','none');
 50 
 51         var xhr = new XMLHttpRequest();
 52         xhr.open("GET", "//mydomain/dengta/update.php?v="+config['set']['date_version'], true);
 53         xhr.onreadystatechange = function() {
 54             if (xhr.readyState == 4) {
 55             // JSON解析器不會執行攻擊者設計的腳本.
 56                 //var resp = JSON.parse(xhr.responseText);
 57                 //console.log(resp);
 58                 if(resp=xhr.responseText)
 59                 {
 60                     //console.log(resp);
 61                     
 62                     //清空原有擴展題庫
 63                     sendMessageToContentScript({'cmd':'del_new_ques'}),
 64 
 65                     //第一行是最新的版本號,并保存設置
 66                     setTimeout(()=>{
 67                         config['set']['date_version']=resp.match(/(\/\/)(\S*)/)[2];
 68                         console.log(config);
 69                         save_set();
 70                     },1000);
 71                         
 72 
 73                     //通過update函數向content更新補充題庫
 74                     setTimeout(()=>{update(xhr.responseText);},2000);
 75 
 76                     //彈出提醒
 77                     //alert('已更新數據至'+config['set']['date_version'])
 78                 }
 79                 else
 80                 {
 81                     alert('已是最新版本')
 82                 }
 83             }
 84         }
 85         xhr.send();
 86 
 87         setTimeout(()=>{$(this).html('已更新'+config['set']['date_version']);},2000);
 88     })    
 89 
 90     //切換上一人、下一人功能
 91     $('#prev_one').click(function(){
 92         $('#login_info_conf .active').prev().find('.login_info_change').click();                
 93     });
 94     $('#next_one').click(()=>{
 95         $('#login_info_conf .active').next().find('.login_info_change').click();                
 96     })
 97 
 98     //導入導出功能
 99     $('#input_login_info').click(()=>{
100     
101         var new_login_info=$('#input_login_info_box').val();
102         //測試是否有效
103         try
104         {
105             new_login_info=JSON.parse(new_login_info);
106         }
107         catch (err)
108         {
109               txt="您輸入的字符串有誤,請重新查證。";
110               alert(txt);        
111         }
112         //成功轉化的字符串
113         //console.log(new_login_info);
114         if(typeof new_login_info === 'object')
115         {
116             console.log(new_login_info);
117             $.extend(config['login_info'],new_login_info);
118             //向content_script報告新加入的用戶
119             sendMessageToContentScript(    
120                 {'cmd':'add','data':new_login_info},
121                 //回調函數
122                 function(response){if(response) {
123                 }}
124             );
125             alert('導入完成');
126         }
127     });
128     //登錄信息導出
129     $('#output_login_info').click(()=>{
130         $('#input_login_info_box').val(JSON.stringify(config['login_info']));        
131     });
132     //全自動答題功能
133     $('#auto_all_ans').click(()=>{
134         auto_all_ans=1;
135         $('.login_info_change').each((i,v)=>{
136             
137             setTimeout(()=>{
138                 $(v).click();
139             },(config['set']['dtime']*1000+500)*53*i+1000);
140                 
141         });
142     })
143 
144     //函數:向content保存設置
145     function save_set(){                
146         var res={
147                 'cmd':'set_conf',
148                 'data':{
149                     'save_login': $('#save_login').get(0).checked?1:0,
150                     'sign_ans': $('#sign_ans').get(0).checked?1:0,
151                     'sign_ans_mouseover': $('#sign_ans_mouseover').get(0).checked?1:0,
152                     'auto_ans': $('#auto_ans').get(0).checked?1:0,
153                     'dtime':parseFloat($('#dtime').val()?$('#dtime').val():3),
154                     'date_version':config['set']['date_version']
155                 }
156         };
157         console.log(res);
158         sendMessageToContentScript(    
159             res,
160             //回調函數
161             function(response)
162             {
163                 if(response) 
164                 {
165                     
166                 
167                 }
168             }
169         );
170         //chrome.storage.local.set(res['data']);
171         config['set']=res['data'];
172         console.log(res);
173     }
174 
175     //函數:向content遞交補充題庫
176     function update(data){
177         var new_data=data.split(/[\n]+/g);
178         console.log(new_data);
179         var len=new_data.length;
180         var j=0;//題目答案計數器
181         var new_question='';
182         var new_answer='';
183         var new_ques_arr=[];
184 
185         //第一個不為空的數組為試題
186         for(var i=0;i<len;i++){
187             //如果是備注的話,就跳過改行
188             if(new_data[i].match(/^\/\//))
189                 continue;
190             //第0、2、4、6..行是題目
191             //第1、3、5、7..行是答案
192             if(j%2==0)
193             {
194                 new_question=new_data[i].replace(/[ABCD. \r\n]/g,'');
195             }
196             else
197             {
198                 new_answer=new_data[i].replace(/[ABCD. \r\n]/g,'');
199                 new_ques_arr.push([new_question,new_answer]);
200 
201                 new_question='';
202                 new_answer='';                        
203             }
204             j++;
205         };
206         //向前端發送命令
207         if(new_ques_arr.length>0)
208         {
209             //對無關信息過濾
210             var res={
211                 'cmd':'set_new_ques',
212                 'data':new_ques_arr
213             };
214             
215 
216             sendMessageToContentScript(    
217                 res,
218