更新于 08-01 11:04

This commit is contained in:
root
2021-08-01 11:04:55 -04:00
parent 344142a960
commit cfb981e2f2
47 changed files with 14007 additions and 7072 deletions

View File

@@ -1,12 +1,17 @@
/*
由于 canvas 依赖系统底层需要编译且预编译包在 github releases 上,改用另一个纯 js 解码图片。若想继续使用 canvas 可调用 runWithCanvas 。
添加 injectToRequest 用以快速修复需验证的请求。eg: $.get=injectToRequest($.get.bind($))
*/
const https = require('https');
const http = require('http');
const stream = require('stream');
const zlib = require('zlib');
const vm = require('vm');
const PNG = require('png-js');
let UA = require('./USER_AGENTS.js').USER_AGENT;
const validatorCount = process.env.JDJR_validator_Count ? process.env.JDJR_validator_Count : 100
const UA = require('./USER_AGENTS.js').USER_AGENT;
const { promisify } = require('util');
const pipelineAsync = promisify(stream.pipeline);
Math.avg = function average() {
var sum = 0;
@@ -29,10 +34,14 @@ class PNGDecoder extends PNG {
decodeToPixels() {
return new Promise((resolve) => {
this.decode((pixels) => {
this.pixels = pixels;
resolve();
});
try {
this.decode((pixels) => {
this.pixels = pixels;
resolve();
});
} catch (e) {
console.info(e)
}
});
}
@@ -66,10 +75,14 @@ class PuzzleRecognizer {
}
async run() {
await this.bg.decodeToPixels();
await this.patch.decodeToPixels();
try {
await this.bg.decodeToPixels();
await this.patch.decodeToPixels();
return this.recognize();
return this.recognize();
} catch (e) {
console.info(e)
}
}
recognize() {
@@ -203,74 +216,74 @@ const DATA = {
"product": "embed",
"lang": "zh_CN",
};
const SERVER = 'iv.jd.com';
const SERVER = '61.49.99.122';
class JDJRValidator {
constructor() {
this.data = {};
this.x = 0;
this.t = Date.now();
this.count = 0;
}
async run(scene = 'cww', eid='') {
const tryRecognize = async () => {
const x = await this.recognize(scene, eid);
async run(scene) {
try {
const tryRecognize = async () => {
const x = await this.recognize(scene);
if (x > 0) {
return x;
}
// retry
return await tryRecognize();
};
const puzzleX = await tryRecognize();
// console.log(puzzleX);
const pos = new MousePosFaker(puzzleX).run();
const d = getCoordinate(pos);
// console.log(pos[pos.length-1][2] -Date.now());
// await sleep(4500);
await sleep(pos[pos.length - 1][2] - Date.now());
this.count++;
const result = await JDJRValidator.jsonp('/slide/s.html', {d, ...this.data}, scene);
if (result.message === 'success') {
// console.log(result);
console.log('JDJR验证用时: %fs', (Date.now() - this.t) / 1000);
return result;
} else {
console.log(`验证失败: ${this.count}/${validatorCount}`);
// console.log(JSON.stringify(result));
if(this.count >= validatorCount){
console.log("JDJR验证次数已达上限退出验证");
return result;
}else{
await sleep(300);
return await this.run(scene, eid);
}
}
}
async recognize(scene, eid) {
const data = await JDJRValidator.jsonp('/slide/g.html', {e: eid}, scene);
const {bg, patch, y} = data;
// const uri = 'data:image/png;base64,';
// const re = new PuzzleRecognizer(uri+bg, uri+patch, y);
const re = new PuzzleRecognizer(bg, patch, y);
// console.log(JSON.stringify(re))
const puzzleX = await re.run();
if (puzzleX > 0) {
this.data = {
c: data.challenge,
w: re.w,
e: eid,
s: '',
o: '',
if (x > 0) {
return x;
}
// retry
return await tryRecognize();
};
this.x = puzzleX;
const puzzleX = await tryRecognize();
// console.log(puzzleX);
const pos = new MousePosFaker(puzzleX).run();
const d = getCoordinate(pos);
// console.log(pos[pos.length-1][2] -Date.now());
// await sleep(4500);
await sleep(pos[pos.length - 1][2] - Date.now());
const result = await JDJRValidator.jsonp('/slide/s.html', {d, ...this.data}, scene);
if (result.message === 'success') {
// console.log(result);
console.log('JDJR验证用时: %fs', (Date.now() - this.t) / 1000);
return result;
} else {
console.count("验证失败");
// console.count(JSON.stringify(result));
await sleep(300);
return await this.run(scene);
}
} catch (e) {
console.info(e)
}
}
async recognize(scene) {
try {
const data = await JDJRValidator.jsonp('/slide/g.html', {e: ''}, scene);
const {bg, patch, y} = data;
// const uri = 'data:image/png;base64,';
// const re = new PuzzleRecognizer(uri+bg, uri+patch, y);
const re = new PuzzleRecognizer(bg, patch, y);
const puzzleX = await re.run();
if (puzzleX > 0) {
this.data = {
c: data.challenge,
w: re.w,
e: '',
s: '',
o: '',
};
this.x = puzzleX;
}
return puzzleX;
} catch (e) {
console.info(e)
}
return puzzleX;
}
async report(n) {
@@ -287,7 +300,6 @@ class JDJRValidator {
}
console.log('验证成功: %f\%', (count / n) * 100);
console.clear()
console.timeEnd('PuzzleRecognizer');
}
@@ -295,28 +307,26 @@ class JDJRValidator {
return new Promise((resolve, reject) => {
const fnId = `jsonp_${String(Math.random()).replace('.', '')}`;
const extraData = {callback: fnId};
const query = new URLSearchParams({...DATA,...{"scene": scene}, ...extraData, ...data}).toString();
const url = `https://${SERVER}${api}?${query}`;
const query = new URLSearchParams({...DATA, ...{"scene": scene}, ...extraData, ...data}).toString();
const url = `http://${SERVER}${api}?${query}`;
const headers = {
'Accept': '*/*',
'Accept-Encoding': 'gzip,deflate,br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Language': 'zh-CN,en-US',
'Connection': 'keep-alive',
'Host': "iv.jd.com",
'Host': SERVER,
'Proxy-Connection': 'keep-alive',
'Referer': 'https://h5.m.jd.com/',
'Referer': 'https://h5.m.jd.com/babelDiy/Zeus/2wuqXrZrhygTQzYA7VufBEpj4amH/index.html',
'User-Agent': UA,
};
const req = https.get(url, {headers}, (response) => {
const req = http.get(url, {headers}, (response) => {
let res = response;
if (res.headers['content-encoding'] === 'gzip') {
const unzipStream = new stream.PassThrough();
stream.pipeline(
pipelineAsync(
response,
zlib.createGunzip(),
unzipStream,
reject,
);
res = unzipStream;
}
@@ -396,7 +406,7 @@ function getCoordinate(c) {
return b.join("")
}
const HZ = 20;
const HZ = 5;
class MousePosFaker {
constructor(puzzleX) {
@@ -501,32 +511,43 @@ class MousePosFaker {
}
}
function injectToRequest(fn,scene = 'cww', ua = '') {
if(ua) UA = ua
// new JDJRValidator().run();
// new JDJRValidator().report(1000);
// console.log(getCoordinate(new MousePosFaker(100).run()));
function injectToRequest2(fn, scene = 'cww') {
return (opts, cb) => {
fn(opts, async (err, resp, data) => {
if (err) {
console.error(JSON.stringify(err));
return;
}
if (data.search('验证') > -1) {
console.log('JDJR验证中......');
let arr = opts.url.split("&")
let eid = ''
for(let i of arr){
if(i.indexOf("eid=")>-1){
eid = i.split("=") && i.split("=")[1] || ''
}
}
const res = await new JDJRValidator().run(scene, eid);
opts.url += `&validate=${res.validate}`;
fn(opts, cb);
} else {
cb(err, resp, data);
try {
if (err) {
console.error('验证请求失败.');
return;
}
if (data.search('验证') > -1) {
console.log('JDJR验证中......');
const res = await new JDJRValidator().run(scene);
if (res) {
opts.url += `&validate=${res.validate}`;
}
fn(opts, cb);
} else {
cb(err, resp, data);
}
} catch (e) {
console.info(e)
}
});
};
}
exports.injectToRequest = injectToRequest;
async function injectToRequest(scene = 'cww') {
console.log('JDJR验证中......');
const res = await new JDJRValidator().run(scene);
return `&validate=${res.validate}`
}
module.exports = {
sleep,
injectToRequest,
injectToRequest2
}