Spaces:
Paused
Paused
File size: 1,707 Bytes
a920dd4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | // Text/image CAPTCHA solver — Tesseract.js running locally.
// Best fit: simple text-in-image CAPTCHAs. Trained data is pre-downloaded
// at build time to /app/tesseract-data.
let _workerPromise = null;
async function getWorker() {
if (_workerPromise) return _workerPromise;
_workerPromise = (async () => {
const { createWorker } = require('tesseract.js');
const worker = await createWorker('eng', 1, {
langPath: process.env.TESSDATA_PREFIX || '/app/tesseract-data',
cachePath: process.env.TESSDATA_PREFIX || '/app/tesseract-data',
gzip: false,
});
await worker.setParameters({
// Most CAPTCHAs are 4-8 chars; treat as a single line.
tessedit_pageseg_mode: 7,
// Restrict to alphanumerics — fewer hallucinations.
tessedit_char_whitelist: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
});
return worker;
})();
return _workerPromise;
}
async function recognizeBuffer(imageBuffer) {
const w = await getWorker();
const { data } = await w.recognize(imageBuffer);
return (data?.text || '').replace(/\s+/g, '').trim();
}
async function recognizeUrl(page, url) {
const buf = await page.evaluate(async (u) => {
const r = await fetch(u, { credentials: 'include' });
if (!r.ok) throw new Error('image fetch failed: ' + r.status);
const ab = await r.arrayBuffer();
return Array.from(new Uint8Array(ab));
}, url);
return recognizeBuffer(Buffer.from(buf));
}
async function recognizeElement(page, selector) {
const buf = await page.locator(selector).first().screenshot();
return recognizeBuffer(buf);
}
module.exports = { recognizeBuffer, recognizeUrl, recognizeElement, getWorker };
|