changed to individual files instead one big ass script and added auto captcha solver functionality
This commit is contained in:
+128
@@ -0,0 +1,128 @@
|
||||
const Tesseract = require('tesseract.js');
|
||||
|
||||
const CAPTCHA_PATTERNS = {
|
||||
recaptcha: {
|
||||
selectors: ['.g-recaptcha', '[data-sitekey]', 'iframe[src*="recaptcha"]', '#recaptcha'],
|
||||
name: 'reCAPTCHA'
|
||||
},
|
||||
hcaptcha: {
|
||||
selectors: ['.h-captcha', '[data-hcaptcha-sitekey]', 'iframe[src*="hcaptcha"]', '#hcaptcha'],
|
||||
name: 'hCaptcha'
|
||||
},
|
||||
textCaptcha: {
|
||||
selectors: ['input[name*="captcha"]', 'input[id*="captcha"]', '.captcha-input', '#captcha'],
|
||||
name: 'Text CAPTCHA'
|
||||
},
|
||||
imageCaptcha: {
|
||||
selectors: ['img[src*="captcha"]', '.captcha-image', '#captcha-image', 'img[alt*="captcha" i]'],
|
||||
name: 'Image CAPTCHA'
|
||||
},
|
||||
mathCaptcha: {
|
||||
selectors: ['.math-captcha', '[name*="math"]', 'input[placeholder*="math" i]'],
|
||||
name: 'Math CAPTCHA'
|
||||
}
|
||||
};
|
||||
|
||||
async function detectCaptcha(page) {
|
||||
const captchaInfo = await page.evaluate((patterns) => {
|
||||
const results = [];
|
||||
|
||||
for (const [type, config] of Object.entries(patterns)) {
|
||||
for (const selector of config.selectors) {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
if (elements.length > 0) {
|
||||
results.push({
|
||||
type: type,
|
||||
name: config.name,
|
||||
selector: selector,
|
||||
count: elements.length
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}, CAPTCHA_PATTERNS);
|
||||
|
||||
return captchaInfo;
|
||||
}
|
||||
|
||||
async function solveSimpleCaptcha(page) {
|
||||
const mathSolution = await page.evaluate(() => {
|
||||
const mathText = document.querySelector('.math-captcha, .captcha-question, [class*="math"]');
|
||||
if (mathText) {
|
||||
const text = mathText.textContent || '';
|
||||
const match = text.match(/(\d+)\s*([+\-*/])\s*(\d+)/);
|
||||
if (match) {
|
||||
const [_, a, op, b] = match;
|
||||
let result;
|
||||
switch(op) {
|
||||
case '+': result = parseInt(a) + parseInt(b); break;
|
||||
case '-': result = parseInt(a) - parseInt(b); break;
|
||||
case '*': result = parseInt(a) * parseInt(b); break;
|
||||
case '/': result = Math.floor(parseInt(a) / parseInt(b)); break;
|
||||
}
|
||||
return { type: 'math', answer: result, text: text };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (mathSolution) {
|
||||
return mathSolution;
|
||||
}
|
||||
|
||||
const imageCaptchaInfo = await page.evaluate(() => {
|
||||
const selectors = [
|
||||
'img[src*="captcha"]',
|
||||
'.captcha-image img',
|
||||
'#captcha-image',
|
||||
'img[alt*="captcha" i]',
|
||||
'img[class*="captcha" i]'
|
||||
];
|
||||
|
||||
for (const selector of selectors) {
|
||||
const img = document.querySelector(selector);
|
||||
if (img && img.src) {
|
||||
return { src: img.src, selector: selector };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (imageCaptchaInfo) {
|
||||
console.log(' Attempting OCR-based CAPTCHA solving...');
|
||||
try {
|
||||
const { data: { text } } = await Tesseract.recognize(
|
||||
imageCaptchaInfo.src,
|
||||
'eng',
|
||||
{ logger: m => {} }
|
||||
);
|
||||
|
||||
const cleanedText = text.replace(/[^a-zA-Z0-9]/g, '').trim();
|
||||
|
||||
if (cleanedText && cleanedText.length >= 3) {
|
||||
console.log(` OCR read: "${cleanedText}"`);
|
||||
return {
|
||||
type: 'image',
|
||||
answer: cleanedText,
|
||||
originalText: text,
|
||||
imageSrc: imageCaptchaInfo.src
|
||||
};
|
||||
}
|
||||
} catch (ocrError) {
|
||||
console.log(` OCR failed: ${ocrError.message}`);
|
||||
}
|
||||
|
||||
return { type: 'image', message: 'Image CAPTCHA detected - OCR failed, manual solving required' };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CAPTCHA_PATTERNS,
|
||||
detectCaptcha,
|
||||
solveSimpleCaptcha
|
||||
};
|
||||
Reference in New Issue
Block a user