// ==UserScript==
// @name 万能验证码自动输入(升级版)
// @namespace https://www.like996.icu:1205/
// @version 2.8
// @description 在将来的时间里将会在后台默默的为你自动识别页面是否存在验证码并填入。对于一些书写不规整的验证码页面请手动配置规则。感谢老六提供基础代码
// @author crab
// @match http://*/*
// @match https://*/*
// @connect like996.icu
// @require https://cdn.bootcss.com/jquery/3.4.1/jquery.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_openInTab
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_xmlhttpRequest
// @nocompat Chrome
// @downloadURL none
// ==/UserScript==
class CaptchaWrite {
IdCard() {
return Set["idCard"];
}
getCaptchaServerUrl(){
return "https://www.like996.icu:1205/";
}
constructor() {
this.Tip = this.AddTip();
if (GM_listValues().indexOf("set") == -1) {
GM_setValue("set", {
"idCard": ""
});
var WhetherHelp = confirm("万能验证码填入\n初始化完毕!\n在将来的时间里将会在后台默默的为你\n自动识别页面是否存在验证码并填入。\n对于一些书写不规整的验证码页面请手动添加规则。\n查看添加方法请点击确定。");
if (WhetherHelp == true) {
GM_openInTab(this.getCaptchaServerUrl() + "help.html", 'active')
}
}
Set = GM_getValue("set");
// 设置自动识别初始值
if(Set["autoIdentification"] == undefined ){
Set["autoIdentification"]="true";
GM_setValue("set", Set);
}
// 设置开启提示初始值
if(Set["showHintCheck"] == undefined ){
Set["showHintCheck"]="true";
GM_setValue("set", Set);
}
}
//手动添加规则
PickUp() {
var that = this;
var AddRule = {};
var IdentifyResult = '';
that.Hint('请对验证码图片点击右键!')
$("img").each(function() {
$(this).on("contextmenu", function() {
var img = that.Aimed($(this));
console.log('PickUp_Img:' + img);
if($(img).length!=1){
that.Hint('验证码选择错误,该图片实际对应多个元素。')
return;
}
that.Hint('等待识别')
IdentifyResult = that.Identify(img,function ManualRule(img,IdentifyResult){
if (img && IdentifyResult) {
console.log('记录信息' + img + IdentifyResult);
AddRule['img'] = img;
$("img").each(function() {
$(this).off("click");
$(this).off("on");
$(this).off("load");
});
that.Hint('接下来请点击验证码输入框')
$("input").each(function() {
$(this).click(function() {
var input = that.Aimed($(this));
// console.log('PickUp_input' + input);
AddRule['input'] = input;
AddRule['path'] = window.location.href;
AddRule['title'] = document.title;
AddRule['host'] = window.location.host;
AddRule['idcard'] = that.IdCard();
that.Write(IdentifyResult,input);
that.Hint('完成')
//移除事件
$("input").each(function() {
$(this).off("click");
});
//添加信息
that.Query({
"method": "captchaHostAdd",
"data": AddRule
},function(data){writeResultIntervals[writeResultIntervals.length]={"img":img,"input":input}});
that.delCapFoowwLocalStorage(window.location.host);
});
});
}
});
});
});
}
//创建提示元素
AddTip() {
var TipHtml = $("
").text("Text.");
TipHtml.css({
"background-color": "rgba(211,211,211,0.86)",
"align-items": "center",
"justify-content": "center",
"position": "fixed",
"color": "black",
"top": "-5em",
"height": "2em",
"margin": "0em",
"padding": "0em",
"font-size": "1.2em",
"width": "100%",
"left": "0",
"right": "0",
"text-align": "center",
"z-index": "9999999999999",
"padding-top": "3px",
display: 'none'
});
$("body").prepend(TipHtml);
return TipHtml;
}
//展示提醒
Hint(Content, Duration) {
if(Set["showHintCheck"]!="true"){
return;
}
var that = this;
that.Tip.stop(true, false).animate({
top: '-5em'
}, 300, function() {
that.Tip.show();
that.Tip.html(Content+"X");
});
that.Tip.animate({
top: '0em'
}, 500).animate({
top: '0em'
}, Duration ? Duration : 3000).animate({
top: '-5em'
}, 500, function() {
that.Tip.hide();
});
return;
}
//查询规则
Query(Json,callback) {
var that = this;
var QueryRule = '';
var LocalStorageData=this.getCapFoowwLocalStorage(Json.method + "_" + Json.data.host);
if(Json.method=='captchaHostAdd'){
that.delCapFoowwLocalStorage("captchaHostQuery_"+Json.data.host);
LocalStorageData=null;
}
if(LocalStorageData!=null){
console.log("存在本地缓存的验证码识别规则直接使用。")
if(callback!=null){
callback(LocalStorageData);
return;
}else{
return LocalStorageData;
}
}
$.ajax({
url: that.getCaptchaServerUrl() + Json.method,
type: "POST",
dateType: 'json',
cache: false,
async: callback!=null,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(Json.data),
success: function(data) {
if (data.info) {
that.Hint(data.info);
}
QueryRule = data;
that.setCapFoowwLocalStorage(Json.method + "_" + Json.data.host,data,new Date().getTime()+1000*60)
if(callback!=null){
callback(QueryRule);
}
},
error: function(data) {
console.log("error");
}
});
return QueryRule;
}
//开始识别
Start() {
//检查配置中是否有此网站
var that = this;
var Pathname = window.location.href;
var Card = that.IdCard()
writeResultInterval= setInterval(function(){that.WriteResultsInterval();},500);
that.Query({
"method": "captchaHostQuery",
"data": {
"host": window.location.host,
"path": Pathname,
"idcard": Card
}
},function(Rule){
if (Rule.code ==531 || Rule.code ==532) {
console.log('有规则执行规则' + Pathname);
var data=Rule.data;
for(var i=0;i {
var data=obj.response;
if (!data.valid) {
if(data.description!=undefined){
that.Hint('识别请求发生错误: ' + data.description, 5000);
}
that.setCapFoowwLocalStorage(Base.substring(Base.length-32),data.description,new Date().getTime()+(9999999 * 9999999))
} else {
Results = data.data;
if (Results.length < 4) {
that.Hint('验证码识别结果可能错误,请刷新验证码尝试', 5000)
}else if(data.description != ''&& data.description != null){
that.Hint(data.description, data.showTime)
}else{
that.Hint('验证码识别完成', 500)
}
that.setCapFoowwLocalStorage(Base.substring(Base.length-32),Results,new Date().getTime()+(9999999 * 9999999))
if(callback!=null){
if(callback.name=='WriteRule'){
callback(Results);
}else if(callback.name=='ManualRule'){
callback(img,Results);
}
}
}
},onerror: err => {
console.log(err)
}
});
return Results;
}
//识别操作
Identify(img,callback) {
var that = this;
var Base = that.ConversionBase(img);
try{
if(Base.toDataURL("image/png").replace(/.*,/, "").length<255){
throw new Error("图片大小异常");
}
}catch(e){
if(callback.name=='ManualRule'){
that.Hint('跨域策略,请重新右键点击图片');
}
return;
}
if (Base.width) {
if(!$(img).is(":visible")){
console.log("验证码不可见,本次不识别");
return;
}
that.Identify_Baidu(img,Base,callback);
} else {
console.log('验证码没有加载加载后自动识别');
that.Hint('点击图片非验证码图片,或存在跨域问题')
}
}
//根据配置识别写入
WriteResults(img, input) {
var that = this;
//创建一个触发操作
if(document.querySelector(img)==null){
return;
}
document.querySelector(img).onload = function() {
that.WriteResults(img, input)
}
this.Identify(img,function WriteRule(vcode){
that.Write(vcode, input)
})
}
//写入操作
Write(ResultsImg, WriteInput) {
var that = this;
WriteInput = document.querySelector(WriteInput);
WriteInput.value = ResultsImg;
if(typeof(InputEvent)!=='undefined') {
//使用 InputEvent 方法,主流浏览器兼容
WriteInput.value=ResultsImg;
WriteInput.dispatchEvent(new InputEvent("input")); //模拟事件
that.fire(WriteInput,"change");
that.fire(WriteInput,"blur");
that.fire(WriteInput,"focus");
that.fire(WriteInput,"keypress");
WriteInput.value = ResultsImg;
} else if(KeyboardEvent) {
//使用 KeyboardEvent 方法,ES6以下的浏览器方法
WriteInput.dispatchEvent(new KeyboardEvent("input"));
}
}
// 各类事件
fire(element,eventName){
var event = document.createEvent("HTMLEvents");
event.initEvent(eventName, true, true);
element.dispatchEvent(event);
}
//转换图片
ConversionBase(img) {
img = document.querySelector(img);
img.setAttribute("crossOrigin",'Anonymous');// 设置允许跨域
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
return canvas;
}
//自动规则
AutoRules() {
var that = this;
var MatchList = [];
$("img").each(function() {
var Randomcolor = "red";
if ($(this).siblings("input").length == 1) {
MatchList.push({
"img": that.Aimed($(this)),
"input": that.Aimed($(this).siblings("input"))
})
$(this).css("borderStyle", "solid").css("borderColor", Randomcolor).css("border-width", "4px");
$(this).siblings("input").css("borderStyle", "solid").css("borderColor", Randomcolor);
} else {
if ($(this).prev().children("input").length == 1) {
MatchList.push({
"img": that.Aimed($(this)),
"input": that.Aimed($(this).prev().children("input"))
})
$(this).css("borderStyle", "solid").css("borderColor", Randomcolor).css("border-width", "4px");
$(this).prev().children("input").css("borderStyle", "solid").css("borderColor", Randomcolor);
}
if ($(this).next().children("input").length == 1) {
MatchList.push({
"img": that.Aimed($(this)),
"input": that.Aimed($(this).next().children("input"))
})
$(this).css("borderStyle", "solid").css("borderColor", Randomcolor).css("border-width", "4px");
$(this).next().children("input").css("borderStyle", "solid").css("borderColor", Randomcolor);
}
}
});
return MatchList;
}
//生成标识
Aimed(Element) {
// console.log('---根据元素创建配置信息---');
Element = Element[0]
var that = this;
var ElementLocalName = Element.localName;
var result;
// 如果有vue的id,则直接返回
var vueId=that.getDataV(Element);
if(vueId != null){
result = ElementLocalName+"["+vueId+"]";
if( $(result).length == 1){
return result;
}
}
// 如果有placeholder,则直接返回
var placeholder=that.getPlaceholder(Element);
if(placeholder != null){
result = ElementLocalName+"["+placeholder+"]";
if( $(result).length == 1){
return result;
}
}
// 如果有alt,则直接返回
var alt=that.getAlt(Element);
if(alt != null){
result = ElementLocalName+"["+alt+"]";
if( $(result).length == 1){
return result;
}
}
// 如果有name且只有一个,则直接返回
var selectElement=that.getElementName(Element);
if(selectElement != null){
return selectElement;
}
// 如果有src,且src后面无参数则直接返回
var src=that.getSrc(Element);
if(src != null && src.length<200){
result = ElementLocalName+"["+src+"]";
if( $(result).length == 1){
return result;
}
}
var Symbol = ( this.getElementId(Element) ? "#" :Element.className ? "." : false);
var locationAddr;
if (!Symbol) {
locationAddr= that.Climb(Element.parentNode, ElementLocalName);
} else {
locationAddr= that.Climb(Element, ElementLocalName);
}
if($(locationAddr).length==1){
return locationAddr.trim();
}
that.Hint('该网站非标准web结构,暂时无法添加规则,请联系客服添加。')
return null;
}
//判断元素id是否可信
getElementId(element){
var id=element.id;
if(id){
if(id.indexOf("exifviewer-img-")==-1){// 对抗类似vue这种无意义id
if(id.length<40){// 对抗某些会自动变换id的验证码
return true;
}
}
}
return false;
}
//爬层级
Climb(Element, ElementLocalName, Joint = '') {
var ElementType = (this.getElementId(Element) ? Element.id : Element.className ? Element.className.replace(/\s/g, ".") : false);
var Symbol = (this.getElementId(Element) ? "#" : Element.className ? "." : false);
var Address ;
if (ElementType && ElementLocalName == Element.localName) {
Address = ElementLocalName + Symbol + ElementType;
} else {
Address ="";
if(Symbol!=false){
Address=Address+Symbol;
}
if(ElementType!=false){
Address=Address+ElementType;
}
Address= ' ' + ElementLocalName
}
if ($(Address).length == 1) {
return Address + ' ' + Joint;
} else {
Joint = this.Climb($(Element).parent()[0], $(Element).parent()[0].localName, Address + ' ' + Joint)
return Joint;
}
}
// 获取vue的data-v-xxxx
getDataV(element){
var elementKeys=element.attributes;
if(elementKeys==null){
return null;
}
for(var i=0;i