// ==UserScript==
// @name 通途
// @namespace http://tampermonkey.net/
// @version 2.5.4
// @description 教务网验证码识别,已适配西南交通大学(swjtu),石家庄铁道大学,新乡医学院三全学院,四川城市职业学院(scuvc),阿坝师范学院(旧版教务),四川国际标榜职业技术学院,四川交通职业技术学院(svtcc),四川工商学院(abtc)
// @author kaka
// @match http://jwc.swjtu.edu.cn/service/login*
// @match *://jiaowu.swjtu.edu.cn/service/login*
// @match http://jwc.swjtu.edu.cn/vatuu/YouthIndexAction?setAction=index
// @match http://jwc.polus.edu.cn/service/login*
// @match http://jwc.abtu.edu.cn/service/login*
// @match http://jwb.sqmc.edu.cn/service/login*
// @match http://jwc.svtcc.edu.cn/service/login*
// @match http://jwc.scuvc.com/service/login*
// @match http://jwxt.stbu.edu.cn/service/login*
// @match *.vatuu.com/service/login*
// @match *.vvtuu.com/service/login*
// @connect aip.baidubce.com
// @connect localhost
// @grant unsafewindow
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
let setting = {//改一改这个,应该能用于其他网站,慢慢适配
ran_img : document.querySelector("#randomPhoto > img"), /*验证码图片元素*/
ran_img_url:window.location.origin+'/vatuu/GetRandomNumberToJPEG?test='+new Date().getTime(),/*验证码图片请求url*/
ran_text : document.getElementById('ranstring'),/*验证码填写元素*/
other_data:['document.querySelector("#password")',/*其它必填项#######################自动处理,下次跟新再说(逃*/
'document.querySelector("#username")'],/*必须是字符串,目前想不到更好的解决办法*/
submit:document.querySelector("#submit2"),/*登陆按钮*/
nostop:true,/*错误后允许重试*/
err_total:5, /*各环节允许最大错误*/
autologin:false,//自动登录(不可用)开关
debugger:0,//调试开关
ocrurl: "https://aip.baidubce.com/rest/2.0/ocr/v1/webimage",//api地址
ocrurl_1: "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic",//备用api
apis:[['iKGARn6BhGgU82W9xzLUIatb','hES0Zae2iLdP1iotenC8zlGo9qA3r0Hc'],
['UjcQzcjSpyYGrXKyPy3dBdoW','65GqKnF5jH3QR9ZEIr8j1ppKWuDRLgI7'],
['Vt2YOiA6CZTnnpaZCEHLTTl6','LIeZdRFmg8odzPCLR8yPPdNeZDKA7yWM'],
['xCEG3OUq0mKzIThFiGPh9AES','mpCK1RI4sFIkX79QDDy6qO2GmCCGC6TS'],
],
};
function autologin(){
if(other_data_done()){/*其它信息也填了就登陆*/
setting.submit.click();
};
};
function add_onload(){
try{
let img =document.querySelector("#randomPhoto > img")//再次添加监听
img.addEventListener("load",function(){
get_random_img(function( bs64_str){
get_str(bs64_str)
})
})
}catch(e){}
}
function debug(){
if(setting.debugger){
const arg = Array.from(arguments);
arg.unshift(`color: white; background-color:#2274A5`);
arg.unshift('%c 通途:');
console["info"].apply(console, arg);
}
}
function enter_login(){
document.onkeydown = function(ev){
var e = ev || event;
if(e.keyCode ==13){
setting.submit.click();
};
}};
function other_data_done(){
if(eval(setting.other_data.join('.value&&')+'.value')){return true;};
};
function get_random_img(callback){
setting.runing=1
let img= document.querySelector("#randomPhoto > img")
debug(img)
let canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
let ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();
let dataURL = canvas.toDataURL("image/"+ext);
let bs64_str = dataURL.split(",")[1];
callback(bs64_str);
};
function get_access_url(){
let randomapi = setting.apis[setting.ran_api_num];
return 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+randomapi[0]+'&client_secret='+randomapi[1]
};
function setCookie(cname, cvalue, exp) {
var d = new Date();
d.setTime(d.getTime() + (exp*1000)-5000);
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
};
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
};
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
};
};
return "";
};
function get_access(){
debug("api-num",setting.ran_api_num)
debug("api-url",setting.ocrurl)
let access_token = getCookie("access_token_"+setting.ran_api_num);
if (access_token != "") {/*access未过期*/
setting.access_token =access_token;
} else {
try{
GM_xmlhttpRequest({
method: "GET",
url:get_access_url(),
onload: function(response) {
let access_token =JSON.parse(this.responseText)["access_token"];
let expires =JSON.parse(this.responseText)["expires_in"];
setCookie("access_token_"+setting.ran_api_num, access_token, expires);
setting.access_token = access_token;
}
});
}catch(err){
debug("response1",response.responseText)
if( err_access_num<=setting.err_total){
err_access_num+=1;
get_access();
}else{
setting.ran_text.placeholder = '失败,请自行输入';
}
}
}
}
function get_str(bs64_str){
let request_url = setting.ocrurl + "?access_token=" + setting.access_token;
let data = 'image='+encodeURIComponent(bs64_str);
/*alert(encodeURIComponent(bs64_str));*/
GM_xmlhttpRequest({
method: 'POST',
url: request_url,
data: data,
headers: {
'charset': 'UTF-8',
"Content-Type": "text/plain"
},
onload: function(response) {
/* console.log("baidu_response");*/
debug(response.responseText)
let temp = JSON.parse(response.responseText);
if(temp['error_code']==17){
debug('服务器请求超限',setting.ran_api_num)
let lastapi=setting.apis[setting.ran_api_num]
setting.apis[setting.ran_api_num]=0//标记超限的
debug(setting.apis)
for(let i=0;i<setting.apis.length;i++){
if(setting.apis[i]!=0){
setting.ran_api_num = i
get_random_img(function( bs64_str){
get_access();
get_str(bs64_str);
throw "超限"
}
)
}
}
setting.ocrurl= setting.ocrurl_1//使用备用识别url
setting.apis[setting.ran_api_num]=lastapi
get_random_img(function( bs64_str){
get_access();
get_str(bs64_str);
}
)
setting.ran_text.placeholder = '今日请求超限';
debug('无可用')
return
}else if(temp['error_code']&& temp['error_code']!= 18&& temp['error_code']!= 110){
setting.ran_text.placeholder = '服务器访问出错';
return
}
try{
let rand_str = temp['words_result'][0]['words'].trim();
debug("解析结果",rand_str)
if(rand_str.length == 4){
setting.ran_text.value = rand_str; /*填写验证码 */
if(other_data_done()&&setting.autologin){/*其它信息也填了就登陆*/
setting.submit.click();
};
debug('已填写')
add_onload()//添加监听
}else{ /*重来*/
throw "解析失败";
};
}catch(err){
setTimeout(function(){
if(setting.nostop){
if(setting.err_num<=setting.err_total ){
setting.err_num+=1;
/*console.log(setting.err_num)*/
setting.ran_text.placeholder = '失败,重试中...';
getPhotoAgain();
add_onload()
}else{
setting.ran_text.placeholder = '失败,请自行输入';
return;
}
};
},200)
};
}
});
};
function init(){
setting.runing=0;
setting.err_num = 1;
let err_access_num = 1;
setting.ran_api_num = Math.floor(Math.random() * setting.apis.length);
enter_login();
document.querySelector("#ranstring").addEventListener('focus',function(){setting.nostop=false; setting.ran_text.placeholder = '检测到自行输入';})/*用户选择自己写时,阻止继续执行*/
}
function main(){
let img =document.querySelector("#randomPhoto > img")
debug(img)
img.addEventListener("load",function(){
setting.ran_text.placeholder = '尝试获取验证码中';
get_random_img(function( bs64_str){
get_access();
get_str(bs64_str);
});
/*setInterval(autologin,3000)//适合自己用*/
autologin();/*针对浏览器预先填写的用户*/
// setInterval(add_onload,10);目的是验证码错误后再次尝试,但好像有点问题,如何区分谁改的img标签,脚本还是源网页
})
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
init();
main();
let isrun= setInterval(function(){//发现会概率性不执行,推测是因为上面onload的锅,先加个检测
console.log(setting.runing)
if(setting.runing){
clearInterval(isrun)
}else{
debug('run main')
setting.ran_text.placeholder = '尝试获取验证码中';
get_random_img(function( bs64_str){
get_access();
get_str(bs64_str);
}
)
}
},100)
})();