// ==UserScript== // @name 自动识别填充网页数英验证码 // @namespace http://tampermonkey.net/ // @version 1.0.5 // @description 有问题联系作者(微信:QAQTOP),可以远程协助调试脚本。自动识别填写大部分网站的数英验证码,无限次使用。本地识别服务下载路径:https://pan.quark.cn/s/23fc8f6b8250 // @author QAQTOP 感谢lcymzzZZ大佬提供的思路以及开源的代码。 // @license GPL Licence // @connect * // @match http://*/* // @match https://*/* // @icon data:image/gif;base64 // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @tag 验证码识别 // ==/UserScript== (function () { 'use strict'; var element, input, imgIndex, canvasIndex, inputIndex; var localRules = []; var exist = false; var iscors = false; var inBlack = false; var firstin = true; var fisrtUse = GM_getValue("fisrtUse", true); if (fisrtUse) { var mzsm = prompt("自动识别填充网页验证码\n首次使用,请阅读并同意以下免责条款。\n \ 1. 此脚本仅用于学习研究,您必须在下载后24小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。\n \ 2. 请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。\n \ 3. 本人对此脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。\n \ 4. 任何以任何方式查看此脚本的人或直接或间接使用此脚本的使用者都应仔细阅读此条款。\n \ 5. 本人保留随时更改或补充此条款的权利,一旦您使用或复制了此脚本,即视为您已接受此免责条款。\n \ 若您同意以上内容,请输入“我已阅读并同意以上内容” 然后开始使用。", ""); if (mzsm == "我已阅读并同意以上内容") { GM_setValue("fisrtUse", false); } else { alert("免责条款未同意,脚本停止运行。\n若不想使用,请自行禁用脚本,以免每个页面都弹出该提示。"); return; } } GM_registerMenuCommand('联系开发者', getDevWeChat); GM_setValue("preCode", ""); // 联系开发者 function getDevWeChat() { alert("开发者微信:QAQTOP\n请备注来意,谢谢合作!"); } function isCode() { if (element.height >= 100 || element.height == element.width) return false; var attrList = ["id", "title", "alt", "name", "className", "src"]; 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 attr = element[attrList[i]]; if (attr.indexOf(strList[j]) != -1) { return true; } } } return false; } function isInput() { var attrList = ["placeholder", "alt", "title", "id", "className", "name"]; 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 attr = input[attrList[i]]; if (attr.indexOf(strList[j]) != -1) { return true; } } } return false; } function findCode(k) { var code = ''; var codeList = document.getElementsByTagName('img'); for (var i = k; i < codeList.length; i++) { var src = codeList[i].src; element = codeList[i]; if (src.indexOf('data:image') != -1) { if (isCode()) { firstin = false; code = src.split("base64,")[1]; GM_setValue("tempCode", code); if (GM_getValue("tempCode") != GM_getValue("preCode")) { GM_setValue("preCode", GM_getValue("tempCode")); p(code, i).then((ans) => { writeIn(ans); }); } break; } } else { if (isCode()) { if (firstin) { firstin = false; var img = element; if (img.src && img.width != 0 && img.height != 0) { 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]; try { code = canvas.toDataURL("image/png").split("base64,")[1]; } catch (err) { findCode(i + 1); return; } GM_setValue("tempCode", code); if (GM_getValue("tempCode") != GM_getValue("preCode")) { iscors = isCORS(); GM_setValue("preCode", GM_getValue("tempCode")); p(code, i).then((ans) => { if (ans != "") writeIn(ans); else findCode(i); }); return; } } else { findCode(i); return; } } else { var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); element.onload = function () { canvas.width = element.width; canvas.height = element.height; ctx.drawImage(element, 0, 0, element.width, element.height); try { code = canvas.toDataURL("image/png").split("base64,")[1]; } catch (err) { findCode(i + 1); return; } GM_setValue("tempCode", code); if (GM_getValue("tempCode") != GM_getValue("preCode")) { iscors = isCORS(); GM_setValue("preCode", GM_getValue("tempCode")); p(code, i).then((ans) => { writeIn(ans); }); return; } } break; } } } } } function findInput() { var inputList = document.getElementsByTagName('input'); 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', '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://127.0.0.1:60001/" + "api.Image_to_Text", data: JSON.stringify(datas), headers: { "Content-Type": "application/json", }, responseType: "json", onload: function (response) { if (response.status == 200) { try { var result = response.response["result"]; console.log("识别结果:" + result); return resolve(result); } catch (e) { console.log("识别失败"); } } else { try { if (response.response["result"] == null) findCode(i + 1); else console.log("识别失败"); } catch (err) { 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; } return false; } } catch (err) { return; } } function fire(element, eventName) { var event = document.createEvent("HTMLEvents"); event.initEvent(eventName, true, true); element.dispatchEvent(event); } function pageChange() { if (exist) { if (localRules["type"] == "img" || localRules["type"] == null) { element = document.getElementsByTagName('img')[imgIndex]; if (localRules["inputType"] == "textarea") { input = document.getElementsByTagName('textarea')[inputIndex]; } else { input = document.getElementsByTagName('input')[inputIndex]; var inputList = document.getElementsByTagName('input'); if (inputList[0] && (inputList[0].id == "_w_simile" || inputList[0].id == "black_node")) { input = inputList[inputIndex]; } } } else if (localRules["type"] == "canvas") { element = document.getElementsByTagName('canvas')[canvasIndex]; if (localRules["inputType"] == "textarea") { input = document.getElementsByTagName('textarea')[inputIndex]; } else { input = document.getElementsByTagName('input')[inputIndex]; var inputList = document.getElementsByTagName('input'); if (inputList[0] && (inputList[0].id == "_w_simile" || inputList[0].id == "black_node")) { input = inputList[inputIndex]; } } } } else { findCode(0); } } function topNotice(msg) { var div = document.createElement('div'); div.id = 'topNotice'; div.style.cssText = 'position: fixed; top: 0; left: 0; width: 100%; height: 5%; z-index: 9999999999; background: rgba(117,140,148,1); display: flex; justify-content: center; align-items: center; color: #fff; font-family: "Microsoft YaHei"; text-align: center;'; div.innerHTML = msg; div.style.fontSize = 'medium'; document.body.appendChild(div); setTimeout(function () { document.body.removeChild(document.getElementById('topNotice')); }, 3500); } console.log("【自动识别填充验证码】正在运行..."); var imgSrc = ""; setTimeout(function () { const targetNode = document.body; const config = { attributes: true, childList: true, subtree: true }; const callback = function () { if (inBlack) return; try { if (iscors) { if (element == undefined) { pageChange(); } if (element.src != imgSrc) { console.log("【自动识别填充验证码】页面/验证码已更新,正在识别..."); imgSrc = element.src; pageChange(); } } else { console.log("【自动识别填充验证码】页面/验证码已更新,正在识别..."); pageChange(); } } catch (err) { return; } } const observer = new MutationObserver(callback); observer.observe(targetNode, config); }, 1000); setTimeout(function () { if (inBlack) return; try { if (element.tagName != "CANVAS") return; } catch (err) { return; } var canvasData1 = element.toDataURL(); setInterval(function () { var canvasData2 = element.toDataURL(); if (canvasData1 != canvasData2) { console.log("【自动识别填充验证码】页面/验证码已更新,正在识别..."); canvasData1 = canvasData2; pageChange(); } }, 0); }, 1000); setTimeout(function () { if (inBlack) return; var tempUrl = window.location.href; setInterval(function () { if (tempUrl != window.location.href) { console.log("【自动识别填充验证码】页面/验证码已更新,正在识别..."); tempUrl = window.location.href; start(); } }); }, 500) })();