// ==UserScript==
// @name 自动识别填充网页验证码
// @namespace http://tampermonkey.net/
// @version 0.3.6
// @description 自动填充网页中出现的图形验证码,如有问题请加群764904163反馈🫡
// @author lcymzzZ
// @license GPL Licence
// @connect *
// @match http://*/*
// @match https://*/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
var element, input, imgIndex, inputIndex;
var localRules = [];
var queryUrl = "http://captcha.zwhyzzz.top:8091/"
var exist = false;
var iscors = false;
//添加菜单
GM_registerMenuCommand('设置识别速率', setSpeed);
GM_registerMenuCommand('添加当前页面规则', addRule);
GM_registerMenuCommand('清除当前页面规则', delRule);
GM_registerMenuCommand('交流/反馈群:764904163', ()=>{window.open("https://jq.qq.com/?_wv=1027&k=9OATqk9I")});
GM_setValue("preCode", "");
function setSpeed(){
//弹出窗体
while (true){
var speed = prompt("请输入识别速率(1-10),默认为3\n注意:\n①数字越大识别越慢,更兼容网络不佳或验证码刷新较慢的情况\n②数字设置过小易导致识别出错", "");
//点击取消
if (speed == null) {
return;
}
//输入非法字符
if (isNaN(speed) || speed < 1 || speed > 10) {
alert("请输入1—10之间的数字");
continue;
}
GM_setValue("speed", parseInt(speed) * 100);
alert("识别速率设置成功");
return;
}
}
//判断是否为验证码(预设规则)
function isCode(){
if (element.height >= 100 || element.height == element.width)
return false;
var attrList = ["id", "title", "alt", "name", "className", "src", "parentNode.id", "parentNode.className"];
var strList = ["code", "Code", "CODE", "captcha", "Captcha", "CAPTCHA", "yzm", "Yzm", "YZM", "check", "Check", "CHECK", "random", "Random", "RANDOM", "veri", "Veri", "VERI", "验证码", "看不清", "换一张"];
for (var i = 0; i < attrList.length; i++) {
for (var j = 0; j < strList.length; j++) {
var str = "element." + attrList[i];
var attr = eval(str);
if (attr.indexOf(strList[j]) != -1) {
return true;
}
}
}
return false;
}
//判断是否为验证码输入框(预设规则)
function isInput(){
var attrList = ["placeholder", "alt", "title", "id", "className"];
var strList = ["code", "Code", "CODE", "captcha", "Captcha", "CAPTCHA", "yzm", "Yzm", "YZM", "check", "Check", "CHECK", "random", "Random", "RANDOM", "veri", "Veri", "VERI", "验证码", "看不清", "换一张"];
for (var i = 0; i < attrList.length; i++) {
for (var j = 0; j < strList.length; j++) {
var str = "input." + attrList[i];
var attr = eval(str);
if (attr.indexOf(strList[j]) != -1) {
return true;
}
}
}
return false;
}
//手动添加规则(操作)
function addRule(){
var ruleData = {"url": window.location.href, "img": "", "input": ""};
//检测鼠标右键点击事件
alert("请在验证码图片上点击鼠标“右”键");
document.oncontextmenu = function(e){
e = e || window.event;
var imgList = document.getElementsByTagName('img');
// console.log(imgList);
for (var i = 0; i < imgList.length; i++) {
if (imgList[i] == e.target && imgList[i].tagName == "IMG") {
var k = i;
}
}
if (k == null) {
alert("选择有误,请重新点击验证码图片");
return;
}
ruleData.img = k;
alert("请在验证码输入框上点击鼠标“左”键");
document.onclick = function(e){
e = e || window.event;
var inputList = document.getElementsByTagName('input');
// console.log(inputList);
for (var i = 0; i < inputList.length; i++) {
if (inputList[i] == e.target && inputList[i].tagName == "INPUT") {
if (inputList[0].id == "_w_simile") {
var k = i - 1;
}
else {
var k = i;
}
}
}
if (k == null) {
alert("选择有误,请重新点击验证码输入框");
return;
}
ruleData.input = k;
// console.log(ruleData);
addR(ruleData).then((res)=>{
if (res.status == 200){
alert("添加规则成功");
start();
//结束事件监听
document.oncontextmenu = null;
document.onclick = null;
}
else {
alert("Error,添加规则失败");
document.oncontextmenu = null;
document.onclick = null;
}
});
}
}
}
//手动添加规则(请求)
function addR(ruleData){
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: queryUrl+"updateRule",
data: JSON.stringify(ruleData),
headers: {
"Content-Type": "application/json"
},
onload: function(response) {
return resolve(response);
}
});
});
}
//删除当前页面规则
function delRule(){
var ruleData = {"url": window.location.href}
delR(ruleData).then((res)=>{
if (res.status == 200)
alert("删除规则成功");
else
alert("Error,删除规则失败");
});
}
//删除规则(请求)
function delR(ruleData){
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: queryUrl+"deleteRule",
data: JSON.stringify(ruleData),
headers: {
"Content-Type": "application/json"
},
onload: function(response) {
return resolve(response);
}
});
});
}
//按已存规则填充
function codeByRule(){
var code = "";
var src = element.src;
if (src.indexOf('data:image') != -1) {
// console.log(src);
code = src.split("base64,")[1];
GM_setValue("tempCode", code);
if (GM_getValue("tempCode") != GM_getValue("preCode")) {
// console.log("preCode:" + GM_getValue("preCode"))
// console.log("tempCode:" + GM_getValue("tempCode"))
GM_setValue("preCode", GM_getValue("tempCode"));
p1(code).then((ans) => {
writeIn1(ans);
});
}
}
else {
setTimeout(function(){
try {
var img = element;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
code = canvas.toDataURL("image/png").split("base64,")[1];
GM_setValue("tempCode", code);
if (GM_getValue("tempCode") != GM_getValue("preCode")) {
// console.log("preCode:" + GM_getValue("preCode"))
// console.log("tempCode:" + GM_getValue("tempCode"))
GM_setValue("preCode", GM_getValue("tempCode"));
p1(code).then((ans) => {
writeIn1(ans);
});
}
}
catch(err){
return;
}
}, GM_getValue("speed"));
}
}
//寻找网页中的验证码
function findCode(k){
var code = '';
var codeList = document.getElementsByTagName('img');
// console.log(codeList);
for (var i = k; i < codeList.length; i++) {
var src = codeList[i].src;
element = codeList[i];
if (src.indexOf('data:image') != -1) {
if (isCode()) {
code = src.split("base64,")[1];
// console.log('code: ' + code);
GM_setValue("tempCode", code);
if (GM_getValue("tempCode") != GM_getValue("preCode")) {
// console.log("preCode:" + GM_getValue("preCode"))
// console.log("tempCode:" + GM_getValue("tempCode"))
GM_setValue("preCode", GM_getValue("tempCode"));
p(code, i).then((ans) => {
writeIn(ans);
});
}
break;
}
}
if (src.indexOf('http') != -1 || src.indexOf('https') != -1) {
if (isCode()) {
setTimeout(function(){
try {
var img = element;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
try{
code = canvas.toDataURL("image/png").split("base64,")[1];
}
catch(err){
//console.log(err);
findCode(i + 1);
return;
}
// console.log(code);
GM_setValue("tempCode", code);
if (GM_getValue("tempCode") != GM_getValue("preCode")) {
iscors = isCORS();
// console.log("preCode:" + GM_getValue("preCode"))
// console.log("tempCode:" + GM_getValue("tempCode"))
GM_setValue("preCode", GM_getValue("tempCode"));
p(code, i).then((ans) => {
writeIn(ans);
});
}
}
catch(err){
return;
}
}, GM_getValue("speed"));
break;
}
}
}
}
//寻找网页中的验证码输入框
function findInput(){
var inputList = document.getElementsByTagName('input');
// console.log(inputList);
for (var i = 0; i < inputList.length; i++) {
input = inputList[i];
if (isInput()) {
return true;
}
}
}
//将识别结果写入验证码输入框(预设规则)
function writeIn(ans){
if (findInput()) {
ans = ans.replace(/\s+/g,"");
input.value = ans;
if (typeof(InputEvent)!=="undefined"){
input.value = ans;
input.dispatchEvent(new InputEvent('input'));
var eventList = ['input', 'change', 'blur', 'focus', 'keypress', 'keyup', 'keydown', 'select'];
for (var i = 0; i < eventList.length; i++) {
fire(input, eventList[i]);
}
input.value = ans;
}
else if(KeyboardEvent) {
input.dispatchEvent(new KeyboardEvent("input"));
}
}
}
//识别验证码(预设规则)
function p(code, i){
return new Promise((resolve, reject) =>{
const datas = {
"ImageBase64": String(code),
}
GM_xmlhttpRequest({
method: "POST",
url: "http://captcha.zwhyzzz.top:6688/identify_GeneralCAPTCHA",
data: JSON.stringify(datas),
headers: {
"Content-Type": "application/json",
},
responseType: "json",
onload: function(response) {
// console.log(response);
if (response.status == 200) {
var result = response.response["result"];
console.log("识别结果:" + result);
return resolve(result);
}
else {
try {
if (response.response["result"] == null)
findCode(i + 1);
else
console.log("识别失败");
}
catch(err){
console.log("识别失败");
}
}
}
});
});
}
//识别验证码(自定义规则)
function p1(code){
return new Promise((resolve, reject) =>{
const datas = {
"ImageBase64": String(code),
}
GM_xmlhttpRequest({
method: "POST",
url: "http://captcha.zwhyzzz.top:6688/identify_GeneralCAPTCHA",
data: JSON.stringify(datas),
headers: {
"Content-Type": "application/json",
},
responseType: "json",
onload: function(response) {
// console.log(response);
if (response.status == 200) {
var result = response.response["result"];
console.log("识别结果:" + result);
return resolve(result);
}
else {
console.log("识别失败");
}
}
});
});
}
//判断是否跨域
function isCORS(){
try {
if (element.src.indexOf('http') != -1 || element.src.indexOf('https') != -1) {
if (element.src.indexOf(window.location.host) == -1) {
console.log("检测到当前页面存在跨域问题");
return true;
}
//console.log("当前页面不存在跨域问题");
return false;
}
}
catch(err){
return;
}
}
//将url转换为base64(解决跨域问题)
function p2(){
return new Promise((resolve, reject) =>{
GM_xmlhttpRequest({
url: element.src,
method: "GET",
headers: {'Content-Type': 'application/json; charset=utf-8','path' : window.location.href},
responseType: "blob",
onload: function(response) {
// console.log(response);
let blob = response.response;
let reader = new FileReader();
reader.onloadend = (e) => {
let data = e.target.result;
element.src = data;
return resolve(data);
}
reader.readAsDataURL(blob);
}
});
});
}
//此段逻辑借鉴Crab大佬的代码,十分感谢
function fire(element,eventName){
var event = document.createEvent("HTMLEvents");
event.initEvent(eventName, true, true);
element.dispatchEvent(event);
}
//将识别结果写入验证码输入框(自定义规则)
function writeIn1(ans){
ans = ans.replace(/\s+/g,"");
input.value = ans;
if (typeof(InputEvent)!=="undefined"){
input.value = ans;
input.dispatchEvent(new InputEvent('input'));
var eventList = ['input', 'change', 'blur', 'focus', 'keypress', 'keyup', 'keydown', 'select'];
for (var i = 0; i < eventList.length; i++) {
fire(input, eventList[i]);
}
input.value = ans;
}
else if(KeyboardEvent) {
input.dispatchEvent(new KeyboardEvent("input"));
}
}
//判断当前页面是否存在规则,返回布尔值
function compareUrl(){
return new Promise((resolve, reject) => {
var datas = {"url": window.location.href};
GM_xmlhttpRequest({
method: "POST",
url: queryUrl+"queryRule",
headers: {
"Content-Type": "application/json"
},
data: JSON.stringify(datas),
onload: function(response) {
// console.log(response);
try {
localRules = JSON.parse(response.responseText);
}
catch(err){
localRules = [];
}
if (localRules.length == 0)
return resolve(false);
return resolve(true);
}
});
});
}
//开始识别
function start(){
if (GM_getValue("speed") == undefined) {
GM_setValue("speed", 300);
}
// console.log("识别速度:" + GM_getValue("speed"));
compareUrl().then((isExist) => {
if (isExist) {
exist = true;
console.log("【自动识别填充验证码】已存在该网站规则");
imgIndex = localRules["img"];
inputIndex = localRules["input"];
element = document.getElementsByTagName('img')[imgIndex];
// console.log(element.src);
input = document.getElementsByTagName('input')[inputIndex];
// console.log(input);
var inputList = document.getElementsByTagName('input');
// console.log(inputList);
if (inputList[0].id == "_w_simile") {
inputIndex = parseInt(inputIndex) + 1;
input = inputList[inputIndex];
}
iscors = isCORS();
// console.log(input);
// console.log(element);
if (iscors) {
p2().then(() => {
// console.log(data);
codeByRule();
});
}
else {
codeByRule();
}
}
else {
console.log("【自动识别填充验证码】不存在该网站规则,正在根据预设规则自动识别...");
findCode(0);
}
});
}
//页面变化执行函数
function pageChange(){
if (exist) {
element = document.getElementsByTagName('img')[imgIndex];
input = document.getElementsByTagName('input')[inputIndex];
// console.log(element);
// console.log(input);
iscors = isCORS();
if (iscors) {
p2().then(() => {
// console.log(data);
codeByRule();
});
}
else {
codeByRule();
}
}
else {
findCode(0);
}
}
console.log("【自动识别填充验证码】正在运行...");
start();
var imgSrc = "";
//监听页面变化
setTimeout(function(){
const targetNode = document.body;
const config = { attributes:true, childList: true, subtree: true};
const callback = function() {
try {
if (iscors){
if (element == undefined) {
pageChange();
}
if (element.src != imgSrc) {
console.log("【自动识别填充验证码】页面/验证码已更新,正在识别...");
imgSrc = element.src;
pageChange();
}
}
else {
console.log("【自动识别填充验证码】页面/验证码已更新,正在识别...");
pageChange();
}
}
catch(err) {
return;
// pageChange();
}
}
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
}, 1000);
})();