通途

教务网验证码识别,已适配西南交通大学(swjtu),石家庄铁道大学,新乡医学院三全学院,四川城市职业学院(scuvc),阿坝师范学院(旧版教务),四川国际标榜职业技术学院,四川交通职业技术学院(svtcc),四川工商学院(abtc)

目前为 2020-10-26 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 通途
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.5.6
  5. // @description 教务网验证码识别,已适配西南交通大学(swjtu),石家庄铁道大学,新乡医学院三全学院,四川城市职业学院(scuvc),阿坝师范学院(旧版教务),四川国际标榜职业技术学院,四川交通职业技术学院(svtcc),四川工商学院(abtc)
  6. // @author kaka
  7. // @match http://jwc.swjtu.edu.cn/service/login*
  8. // @match *://jiaowu.swjtu.edu.cn/service/login*
  9. // @match http://jwc.swjtu.edu.cn/vatuu/YouthIndexAction?setAction=index
  10. // @match http://jwc.polus.edu.cn/service/login*
  11. // @match http://jwc.abtu.edu.cn/service/login*
  12. // @match http://jwb.sqmc.edu.cn/service/login*
  13. // @match http://jwc.svtcc.edu.cn/service/login*
  14. // @match http://jwc.scuvc.com/service/login*
  15. // @match http://jwxt.stbu.edu.cn/service/login*
  16. // @match https://bslc.lib.swjtu.edu.cn/uas/auth*
  17. // @match *.vatuu.com/service/login*
  18. // @match *.vvtuu.com/service/login*
  19. // @connect aip.baidubce.com
  20. // @connect localhost
  21. // @grant unsafeWindow
  22. // @grant GM_xmlhttpRequest
  23. // @grant GM_getValue
  24. // @grant GM_setValue
  25. // @run-at document-end
  26. // ==/UserScript==
  27. (function() {
  28. 'use strict';
  29.  
  30. let setting = {//改一改这个,应该能用于其他网站,慢慢适配
  31. ////////////////////////////////////////////////////////////////////////////////////////////user-setting
  32. ran_img:function(){return document.querySelector("#randomPhoto > img")}, /*验证码图片元素*/
  33. ran_img_url:window.location.origin+'/vatuu/GetRandomNumberToJPEG?test='+new Date().getTime(),/*验证码图片请求url*/
  34. ran_text:function(){return document.getElementById('ranstring')},/*验证码填写元素*/
  35. other_data:['document.querySelector("#password")',/*其它必填项#######################自动处理,下次跟新再说(逃*/
  36. 'document.querySelector("#username")'],/*必须是字符串,目前想不到更好的解决办法*/
  37. submit:document.querySelector("#submit2"),/*登陆按钮*/
  38. add_onload_listener:1,//是否需要在切换验证码后对图片元素监听
  39. autologin:false,//自动登录(不可用)开关
  40. //////////////////////////////////////////////////////////////////////////////////////////////other-setting
  41. nostop:true,/*错误后允许重试*/
  42. err_total:8, /*各环节允许最大错误*/
  43. debugger:0,//调试开关
  44. done:0,
  45. ocrurl: "https://aip.baidubce.com/rest/2.0/ocr/v1/webimage",//api地址
  46. ocrurl_1: "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic",//备用api
  47. apis:[['iKGARn6BhGgU82W9xzLUIatb','hES0Zae2iLdP1iotenC8zlGo9qA3r0Hc'],
  48. ],
  49. };
  50. ////////////////////////////////////////////////////////////////其它网址匹配
  51. if(/bslc.lib.swjtu.edu.cn/.test(window.location.href)){
  52. debug('lib')
  53. setting.ran_img= function(){return document.querySelector("#kaptcha")}
  54. setting.ran_text= function(){return document.querySelector("#code")}
  55. setting.ran_url= "https://bslc.lib.swjtu.edu.cn/uas/kaptcha.jpg"
  56. setting.other_data= ['document.querySelector("#userid")','document.querySelector("#password")']
  57. setting.submit= document.querySelector("#form1 > div:nth-child(10) > button")
  58. //setting.autologin=true,//自动登录(不可用)开关
  59. }
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66. /////////////////////////////////////////////////////////////
  67.  
  68.  
  69.  
  70. function autologin(){
  71. if(other_data_done()){/*其它信息也填了就登陆*/
  72. setting.submit.click();
  73.  
  74. };
  75.  
  76. };
  77. function add_onload(){
  78. if(setting.add_onload_listener){
  79. try{
  80. let img =setting.ran_img()//再次添加监听
  81. img.addEventListener("load",function(){
  82. get_random_img(function( bs64_str){
  83. get_str(bs64_str)
  84.  
  85. })
  86. })
  87. }catch(e){}
  88. }
  89. }
  90. function debug(){
  91. if(setting.debugger){
  92. const arg = Array.from(arguments);
  93. arg.unshift(`color: white; background-color:#2274A5`);
  94. arg.unshift('%c 通途:');
  95. console["info"].apply(console, arg);
  96. }
  97. }
  98. function enter_login(){
  99. document.onkeydown = function(ev){
  100. var e = ev || event;
  101. if(e.keyCode ==13){
  102. setting.submit.click();
  103. };
  104. }};
  105. function other_data_done(){
  106. if(eval(setting.other_data.join('.value&&')+'.value')){return true;};
  107. };
  108.  
  109. function get_random_img(callback){
  110. setting.runing=1
  111. let img= setting.ran_img()
  112. debug(img)
  113. let canvas = document.createElement("canvas");
  114. canvas.width = img.width;
  115. canvas.height = img.height;
  116. let ctx = canvas.getContext("2d");
  117. ctx.drawImage(img, 0, 0, img.width, img.height);
  118. let ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();
  119. let dataURL = canvas.toDataURL("image/"+ext);
  120. let bs64_str = dataURL.split(",")[1];
  121. callback(bs64_str);
  122.  
  123. };
  124. function get_access_url(){
  125. let randomapi = setting.apis[setting.ran_api_num];
  126. return 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+randomapi[0]+'&client_secret='+randomapi[1]
  127. };
  128.  
  129. function setCookie(cname, cvalue, exp) {
  130. var d = new Date();
  131. d.setTime(d.getTime() + (exp*1000)-5000);
  132. var expires = "expires="+d.toUTCString();
  133. document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
  134. };
  135.  
  136. function getCookie(cname) {
  137. var name = cname + "=";
  138. var ca = document.cookie.split(';');
  139. for(var i = 0; i < ca.length; i++) {
  140. var c = ca[i];
  141. while (c.charAt(0) == ' ') {
  142. c = c.substring(1);
  143. };
  144. if (c.indexOf(name) == 0) {
  145. return c.substring(name.length, c.length);
  146. };
  147. };
  148. return "";
  149. };
  150.  
  151. function get_access(){
  152. debug("api-num",setting.ran_api_num)
  153. debug("api-url",setting.ocrurl)
  154. let access_token = getCookie("access_token_"+setting.ran_api_num);
  155. if (access_token != "") {/*access未过期*/
  156. setting.access_token =access_token;
  157. } else {
  158. try{
  159. GM_xmlhttpRequest({
  160. method: "GET",
  161. url:get_access_url(),
  162. onload: function(response) {
  163. let access_token =JSON.parse(this.responseText)["access_token"];
  164. let expires =JSON.parse(this.responseText)["expires_in"];
  165. setCookie("access_token_"+setting.ran_api_num, access_token, expires);
  166. setting.access_token = access_token;
  167. }
  168. });
  169. }catch(err){
  170. debug("response1",response.responseText)
  171.  
  172. if( err_access_num<=setting.err_total){
  173. err_access_num+=1;
  174. get_access();
  175. }else{
  176. setting.ran_text().placeholder = '失败,请自行输入';
  177.  
  178. }
  179. }
  180. }
  181.  
  182. }
  183. function get_str(bs64_str){
  184. if(setting.done){debug('已填写,取消操作')
  185. return}
  186. let request_url = setting.ocrurl + "?access_token=" + setting.access_token;
  187. let data = 'image='+encodeURIComponent(bs64_str);
  188. /*alert(encodeURIComponent(bs64_str));*/
  189. GM_xmlhttpRequest({
  190. method: 'POST',
  191. url: request_url,
  192. data: data,
  193. headers: {
  194. 'charset': 'UTF-8',
  195. "Content-Type": "text/plain"
  196. },
  197. onload: function(response) {
  198. /* console.log("baidu_response");*/
  199. debug(response.responseText)
  200. let temp = JSON.parse(response.responseText);
  201. if(temp['error_code']==17){
  202. debug('服务器请求超限',setting.ran_api_num)
  203. let lastapi=setting.apis[setting.ran_api_num]
  204. setting.apis[setting.ran_api_num]=0//标记超限的
  205. debug(setting.apis)
  206.  
  207. for(let i=0;i<setting.apis.length;i++){
  208.  
  209. if(setting.apis[i]!=0){
  210. setting.ran_api_num = i
  211. get_random_img(function( bs64_str){
  212. get_access();
  213. get_str(bs64_str);
  214. throw "超限"
  215. }
  216. )
  217. }
  218. }
  219. setting.ocrurl= setting.ocrurl_1//使用备用识别url
  220. setting.apis[setting.ran_api_num]=lastapi
  221. get_random_img(function( bs64_str){
  222. get_access();
  223. get_str(bs64_str);
  224.  
  225. }
  226. )
  227. setting.ran_text().placeholder = '今日请求超限';
  228. debug('无可用')
  229. return
  230. }else if(temp['error_code']&& temp['error_code']!= 18&& temp['error_code']!= 110){
  231. setting.ran_text().placeholder = '服务器访问出错';
  232. return
  233. }
  234. try{
  235.  
  236. let rand_str = temp['words_result'][0]['words'].trim();
  237. debug("解析结果",rand_str)
  238. if(rand_str.length == 4){
  239. setting.ran_text().value = rand_str; /*填写验证码 */
  240. if(other_data_done()&&setting.autologin){/*其它信息也填了就登陆*/
  241. setting.submit.click();
  242. };
  243. debug('已填写')
  244. setting.done=1
  245. //add_onload()//添加监听
  246. }else{ /*重来*/
  247.  
  248. throw "解析失败";
  249.  
  250. };
  251. }catch(err){
  252. setTimeout(function(){
  253. if(setting.nostop){
  254. if(setting.err_num<=setting.err_total ){
  255. setting.err_num+=1;
  256. debug('重试次数:'+setting.err_num)
  257. setting.ran_text().placeholder = '失败,重试中...';
  258. //if(setting.done){debug('已填写,取消操作') return}
  259. setting.ran_img().click()//切换验证码
  260. add_onload()
  261. }else{
  262. setting.ran_text().placeholder = '失败,请自行输入';
  263. return;
  264. }
  265. };
  266.  
  267. },200)
  268.  
  269. };
  270. }
  271. });
  272. };
  273. function init(){
  274. setting.runing=0;
  275. setting.err_num = 1;
  276. let err_access_num = 1;
  277. setting.ran_api_num = Math.floor(Math.random() * setting.apis.length);
  278. enter_login();
  279. debug(setting.ran_text())
  280. //setting.ran_text().addEventListener('focus',function(){setting.nostop=false; setting.ran_text().placeholder = '检测到自行输入';})/*用户选择自己写时,阻止继续执行*/
  281. }
  282. function main(){
  283. let img =setting.ran_img()
  284. debug(img)
  285. img.addEventListener("load",function(){
  286. setting.ran_text().placeholder = '尝试获取验证码中';
  287. get_random_img(function( bs64_str){
  288. get_access();
  289. get_str(bs64_str);
  290. });
  291. /*setInterval(autologin,3000)//适合自己用*/
  292. autologin();/*针对浏览器预先填写的用户*/
  293. // setInterval(add_onload,10);目的是验证码错误后再次尝试,但好像有点问题,如何区分谁改的img标签,脚本还是源网页
  294.  
  295.  
  296. })
  297. }
  298.  
  299. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  300. init();
  301. main();
  302. var yalert = window.alert
  303. function newalert(msg){
  304. if('验证码输入不正确' == msg&&setting.nostop){
  305. debug('检测到alert,验证码输入不正确,开始执行main',msg)
  306. setting.ran_text().value = ''
  307. setting.done = false
  308. setting.ran_img().click()//切换验证码
  309. add_onload()
  310. setting.err_num+=1;
  311. }else{
  312. yalert(msg)
  313. }
  314. }
  315. unsafeWindow.alert = newalert
  316. let isrun= setInterval(function(){//发现会概率性不执行,推测是因为上面onload的锅,先加个检测
  317. console.log(setting.runing)
  318. if(setting.runing){
  319. clearInterval(isrun)
  320. }else{
  321. debug('run main')
  322. setting.ran_text().placeholder = '尝试获取验证码中';
  323. get_random_img(function( bs64_str){
  324. get_access();
  325. get_str(bs64_str);
  326. }
  327. )
  328. }
  329. },100)
  330.  
  331. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址