// ==UserScript== // @name mhyX // @namespace http://tampermonkey.net/ // @version 0.1.1 // @description 测试pyscript识别验证码目标区域位置 // @author tfsn20 // @match https://user.mihoyo.com/* // @icon https://user.mihoyo.com/favicon.ico // @grant GM_log // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @run-at context-menu // @grant unsafeWindow // ==/UserScript== (async function () { function sleep(time) { return new Promise((resolve) => setTimeout(resolve, time)) }; await sleep(1000) GM_log('注入'); //劫持console.info判断py运行时加载情况 let oldLog = unsafeWindow.console.info; unsafeWindow.console.info = function (...a) { oldLog(...a) if (a[0].toString().match(/PyScript page fully initialized/)) { oldLog('python运行时加载完毕,可执行python代码...........') pythonRuntimeThen() } } function createObject(object, variableName) { //Bind a variable whose name is the string variableName // to the object called 'object' let execString = variableName + " = object" console.log("Running `" + execString + "`"); eval(execString) } unsafeWindow.createObject = createObject; async function pythonRuntimeThen() { await loadPyodide() let res = then_js(); listenThen(res); function listenThen(res = null) { let d = null; d = JSON.parse(res); console.log('parse', d); const imageData = ctx.createImageData(w, h); let len = imageData.data.length; let t = []; for (let i = 0, l = d.length; i < l; i += 3) { t.push(d[i + 0], d[i + 1], d[i + 2], 255) }; for (let i = 0; i < len; i += 4) { imageData.data[i + 0] = t[i + 0]; imageData.data[i + 1] = t[i + 1]; imageData.data[i + 2] = t[i + 2]; imageData.data[i + 3] = 255; }; ctx.putImageData(imageData, 0, 0); console.log('has again draw'); } } let w = null; let h = null; let canvas = document.createElement('canvas'); let ctx = canvas.getContext("2d"); let imgUrl = null; //绘制图像, 返回像素数据array async function drawAndGetData() { let imgDiv = document.querySelector('div[class="geetest_item_wrap"]'); imgUrl = imgDiv.style.backgroundImage.match(/(http.*")/)[1]; function getImageSize(url) { return new Promise(function (resolve, reject) { let image = new Image(); image.onload = function () { resolve({ width: image.width, height: image.height }); }; image.onerror = function () { reject(new Error('error')); }; image.src = url; }); } let size = await getImageSize(imgUrl); w = size.width; h = size.height let img = document.createElement('img'); img.style.cssText = ` width:${w}px; height:${h}px; `; imgDiv.append(img); img.setAttribute('src', imgUrl) img.setAttribute('crossOrigin', 'anonymous'); canvas.style.cssText = `position:fixed; top:0px; left:0px; z-index:999`; let body = document.querySelector('body'); body.append(canvas); GM_log(w, h); //将canvas的宽和高设置一下 canvas.width = w; canvas.height = h; await sleep(200) ctx.drawImage(img, 0, 0); //这是原始像素数据 let dataOrigin = ctx.getImageData(0, 0, w, h).data; return dataOrigin }; let data = await drawAndGetData(); console.log('origin pixel data', data); function addElement(type, others) { if (type == 'script') { let dom = document.createElement('script'); //dom.setAttribute('defer'); dom.src = others.src; body.appendChild(dom); return } if (type == 'css') { let dom = document.createElement('link'); dom.setAttribute('ref', 'stylesheet'); dom.href = others.href; body.appendChild(dom); return } if (type == 'py-env') { let dom = document.createElement('py-env'); dom.innerHTML = others.env; body.appendChild(dom); return } if (type == 'div') { let dom = document.createElement('div'); dom.setAttribute(others.type, others.name); // dom.href = `${website}`; body.appendChild(dom); return } if (type == 'py-script') { let dom = document.createElement('py-script'); dom.setAttribute(others.type, others.name); dom.innerHTML = others.pyScript; body.appendChild(dom); return } if (type == 'py-config') { let dom = document.createElement('py-config'); dom.setAttribute('type', 'json'); dom.innerHTML = others.config; body.appendChild(dom); return } }; let body = document.querySelector("body"), head = document.querySelector("head"); //load pyodide function need() { addElement('py-env', { env: ` - numpy - opencv_python - Pillow ` }); addElement('css', { href: 'https://pyscript.net/latest/pyscript.css' }); //latest可以换成某个版本,/v0.20.0及之前不支持非纯py库opencv_python,参考https://github.com/pyodide/pyodide/discussions/2424 addElement('script', { src: 'https://pyscript.net/latest/pyscript.js' }); console.log('----------------正在加载包和环境------------'); } need(); //add output element addElement('div', { type: 'id', name: 'plot' }); //add pyscript addElement('py-script', { type: 'output', name: 'plot', pyScript: ` import js from pyodide import create_proxy, to_js import numpy as np import cv2 from PIL import Image def maxGray(img): h, w = img.shape[0:2] # 自定义空白单通道图像,用于存放灰度图 gray = np.zeros((h, w), dtype=img.dtype) # 对原图像进行遍历,然后分别对B\G\R按比例灰度化 for i in range(h): for j in range(w): gray[i, j] = max(img[i, j, 0], img[i, j, 1], img[i, j, 2]) # 求3通道中最大的值 return gray def gammaGray(img): h, w = img.shape[0:2] print('[h,w]',[h,w]) # 自定义空白单通道图像,用于存放灰度图 gray = np.zeros((h, w), dtype=img.dtype) # 对原图像进行遍历,然后分别对B\G\R按比例灰度化 for i in range(h): for j in range(w): a = img[i, j, 2]**(2.2)+1.5*img[i, j, 1]**(2.2) + \ 0.6*img[i, j, 0]**(2.2) # 分子 b = 1+1.5**(2.2)+0.6**(2.2) # 分母 gray[i, j] = pow(a/b, 1.0/2.2) # 开2.2次方根 return gray def getMserImg(gray,draw,d=10): max=60+d min=60-d draw=draw.copy() mser = cv2.MSER_create() regions, boxes = mser.detectRegions(gray) for index, box in enumerate(boxes): x, y, w, h = box if w < max and h < max and w > min and h > min: print([x,y]) cv2.rectangle(draw, (x, y), (x+w, y+h), (0, 255, 0), 1) return draw def then(): data= ${data} data=list(data) w=${w} h=${h} t=[] for i,e in enumerate(data): if i%4 ==0: t.append(data[i:i+3]) t1=[] for i,e in enumerate(t): if i%w == 0: t1.append(t[i:i+w]) data = np.array(t1).astype(np.uint8) img=Image.fromarray(data) img=np.asarray(img) img_copy=img.copy() kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]) img = cv2.filter2D(img, -1, kernel) gray=gammaGray(img) # gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB) draw = getMserImg(gray,img_copy,10) pd=np.array(draw.flatten()).tolist() pyscript.write('plot',pd) return pd # 导出then函数到js环境中(名为then_js) js.createObject(create_proxy(then), "then_js") ` }); })();