Come usare il plugin di Anti-Captcha con Puppeteer o Selenium
Puppeteer e Selenium sono due motori importanti per l'automazione del browser e il nostro plugin si integra perfettamente con loro. In questo articolo ti mostriamo come usarlo con Puppeteer e Selenium rispettivamente per i linguaggi di programmazione NodeJS e Python. Se devi scegliere, ti consigliamo NodeJS+Puppeteer per il suo ambiente originario.
1. Installa dipendenze. Per NodeJS basta installare il pacchetto npm ricevuto che trovi sotto, per Python installa i pacchetti e scarica "chromedriver" eseguibile da questa pagina. La versione del driver deve essere compatibile con la versione di Chromeinstallata sul tuo sistema.
npm install adm-zip puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
2. Scarica il plugin per Chrome in versione ZIP, estrailo nella cartella del tuo progetto. Le versioni effettive si trovano qui. Puoi anche farlo programmaticamente:
//npm install adm-zip
const https = require('https')
const fs = require('fs');
const AdmZip = require("adm-zip");
const pluginURL = 'https://antcpt.com/anticaptcha-plugin.zip';
(async () => {
// scarica il plugin
await new Promise((resolve) => {
https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
})
// estrai
const zip = new AdmZip("./plugin.zip");
await zip.extractAllTo("./plugin/", true);
})();
3. Successivamente, configura la chiave della tua API nel file ./plugin/js/config_ac_api_key.js. Puoi trovare la chiave della tua API nell'area clienti. Devi avere un saldo positivo affinché funzioni.
const apiKey = 'API_KEY_32_BYTES';
if (fs.existsSync('./plugin/js/config_ac_api_key.js')) {
let confData = fs.readFileSync('./plugin/js/config_ac_api_key.js', 'utf8');
confData = confData.replace(/antiCapthaPredefinedApiKey = ''/g, `antiCapthaPredefinedApiKey = '${apiKey}'`);
fs.writeFileSync('./plugin/js/config_ac_api_key.js', confData, 'utf8');
} else {
console.error('plugin configuration not found!')
}
4. Avvia il browser col plugin. Per Puppeteer, consigliamo il plugin 'puppeteer-extra-plugin-stealth' per il pacchetto 'puppeteer-extra', che nasconde qualsiasi segno del browser automatizzato Chromium.
//npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async () => {
const browser = await puppeteer.launch({
headless: false,
ignoreDefaultArgs: [
"--disable-extensions",
"--enable-automation"
],
args: [
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process',
'--allow-running-insecure-content',
'--disable-blink-features=AutomationControlled',
'--no-sandbox',
'--mute-audio',
'--no-zygote',
'--no-xshm',
'--window-size=1920,1080',
'--no-first-run',
'--no-default-browser-check',
'--disable-dev-shm-usage',
'--disable-gpu',
'--enable-webgl',
'--ignore-certificate-errors',
'--lang=en-US,en;q=0.9',
'--password-store=basic',
'--disable-gpu-sandbox',
'--disable-software-rasterizer',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--disable-infobars',
'--disable-breakpad',
'--disable-canvas-aa',
'--disable-2d-canvas-clip-aa',
'--disable-gl-drawing-for-tests',
'--enable-low-end-device-mode',
'--disable-extensions-except=./plugin',
'--load-extension=./plugin'
]
});
const page = await browser.newPage();
})();
5. Vai su una pagina bersaglio e, se richiesto, compila il modulo. Il plugin prenderà il Recaptcha automaticamente e comincerà a risolverlo.
(async () => {
const url = 'https://anti-captcha.com/demo/?page=recaptcha_v2_textarea';
const login = 'Test login';
const password = 'Test password';
try {
await page.goto(url, {
waitUntil: "networkidle0"
});
} catch (e) {
console.error('err while loading the page: '+e);
}
// disabilita errori timeout della navigazione
await page.setDefaultNavigationTimeout(0);
await page.$eval('#login', (element, login) => {
element.value = login;
}, login);
await page.$eval('#password', (element, password) => {
element.value = password;
}, password);
})();
6. Il passaggio successivo è un po' complicato. Alcuni moduli web richiedono che l'utente premi un bottone di invio dopo aver risolto il Recaptcha, altri utilizzano dei callback e lo inviano automaticamente. Nel primo caso vogliamo premere il bottone di invio subito dopo che il Recaptcha è stato risolto. Per farlo nel momento giusto, aspetta che compaia il selettore .antigate_solver.solved e poi premi il bottone di invio.
// aspetta che compaia il selettore "solved"
await page.waitForSelector('.antigate_solver.solved').catch(error => console.log('failed to wait for the selector'));
console.log('{{ $t('articles.how-to-integrate.code-comments.recaptcha-solved') }}');
// premi il pulsante invia
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('task completato, modulo con recaptcha bypassato');
Ci siamo, il modulo è compilato, il Recaptcha è risolto e bypassato. Esempi di codice completo:
// first run the following to install required npm packages:
//
// npm install adm-zip follow-redirects puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
//
//
const https = require('follow-redirects').https;
const fs = require('fs');
const AdmZip = require("adm-zip");
const apiKey = 'YOUR_API_KEY_HERE!';
const pluginURL = 'https://antcpt.com/anticaptcha-plugin.zip';
const url = 'https://anti-captcha.com/demo/?page=recaptcha_v2_textarea';
const login = 'Test login';
const password = 'Test password';
let page = null;
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async () => {
// scarica il plugin
await new Promise((resolve) => {
https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
})
// estrai
const zip = new AdmZip("./plugin.zip");
await zip.extractAllTo("./plugin/", true);
// imposta la chiave dell'API nel file di configurazione
await new Promise((resolve, reject) => {
if (fs.existsSync('./plugin/js/config_ac_api_key.js')) {
let confData = fs.readFileSync('./plugin/js/config_ac_api_key.js', 'utf8');
confData = confData.replace(/antiCapthaPredefinedApiKey = ''/g, `antiCapthaPredefinedApiKey = '${apiKey}'`);
fs.writeFileSync('./plugin/js/config_ac_api_key.js', confData, 'utf8');
resolve();
} else {
console.error('plugin configuration not found!')
reject();
}
});
// imposta le opzioni di avvio del browser
const options = {
headless: false,
ignoreDefaultArgs: [
"--disable-extensions",
"--enable-automation"
],
args: [
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process',
'--allow-running-insecure-content',
'--disable-blink-features=AutomationControlled',
'--no-sandbox',
'--mute-audio',
'--no-zygote',
'--no-xshm',
'--window-size=1920,1080',
'--no-first-run',
'--no-default-browser-check',
'--disable-dev-shm-usage',
'--disable-gpu',
'--enable-webgl',
'--ignore-certificate-errors',
'--lang=en-US,en;q=0.9',
'--password-store=basic',
'--disable-gpu-sandbox',
'--disable-software-rasterizer',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--disable-infobars',
'--disable-breakpad',
'--disable-canvas-aa',
'--disable-2d-canvas-clip-aa',
'--disable-gl-drawing-for-tests',
'--enable-low-end-device-mode',
'--disable-extensions-except=./plugin',
'--load-extension=./plugin'
]
}
try {
// avvia il browser col plugin
const browser = await puppeteer.launch();
page = await browser.newPage();
} catch (e) {
console.log('could not launch browser: '+e.toString())
return;
}
// vai alla pagina bersaglio
try {
await page.goto(url, {
waitUntil: "networkidle0"
});
} catch (e) {
console.error('err while loading the page: '+e);
}
// disabilita errori timeout della navigazione
await page.setDefaultNavigationTimeout(0);
// compila il modulo
await page.$eval('#login', (element, login) => {
element.value = login;
}, login);
await page.$eval('#password', (element, password) => {
element.value = password;
}, password);
// aspetta che compaia il selettore "solved"
await page.waitForSelector('.antigate_solver.solved').catch(error => console.log('failed to wait for the selector'));
console.log('{{ $t('articles.how-to-integrate.code-comments.recaptcha-solved') }}');
// premi il pulsante invia
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('recaptcha risolto');
})();
Bonus: c'è un trucco per eseguire il plugin in modalità headless, dato che Chrome non supporta l'automazione del browser automation coi plugin. Usa lo strumento chiamato Xvfb che fornisce un desktop virtuale per la tua applicazione.
# installa il pacchetto
apt-get install -y xvfb
# imposta la variabile display
export DISPLAY=:0
# esegui il demone Xvfb in background (una sola volta)
/usr/bin/Xvfb :0 -screen 0 1024x768x24 &
# aspetta un po' affinché possa comparire (una volta sola)
sleep 5
# aggiungi il prefisso "xvfb-run" allo script "node" o "python"
xvfb-run node myscript.js
# oppure
xvfb-run python myscript.py