mhyX
// ==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")
`
});
})();