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
pip install selenium
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);
})();
import urllib.request
import zipfile
url = 'https://antcpt.com/anticaptcha-plugin.zip'
# scarica il plugin
filehandle, _ = urllib.request.urlretrieve(url)
# estrai
with zipfile.ZipFile(filehandle, "r") as f:
f.extractall("plugin")
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!')
}
from pathlib import Path
import zipfile
# imposta la chiave dell'API nel file di configurazione
api_key = "API_KEY_32_BYTES"
file = Path('./plugin/js/config_ac_api_key.js')
file.write_text(file.read_text().replace("antiCapthaPredefinedApiKey = ''", "antiCapthaPredefinedApiKey = '{}'".format(api_key)))
# comprimi di nuovo la directory plugin in plugin.zip
zip_file = zipfile.ZipFile('./plugin.zip', 'w', zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk("./plugin"):
for file in files:
path = os.path.join(root, file)
zip_file.write(path, arcname=path.replace("./plugin/", ""))
zip_file.close()
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();
})();
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_extension('./plugin.zip')
browser = webdriver.Chrome('./chromedriver', options=options)
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);
})();
browser.get('https://anti-captcha.com/demo/?page=recaptcha_v2_textarea')
# filling form
browser.find_element_by_css_selector('#login').send_keys('Test login')
browser.find_element_by_css_selector('#password').send_keys('Test 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('recaptcha risolto');
// premi il pulsante invia
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('task completato, modulo con recaptcha bypassato');
# aspetta che compaia il selettore "solved"
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))
# premi il pulsante invia
browser.find_element_by_css_selector('#submitButton').click()
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('recaptcha risolto');
// premi il pulsante invia
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('recaptcha risolto');
})();
import urllib.request
import zipfile
import os
from pathlib import Path
from selenium import webdriver
# scarica il plugin
url = 'https://antcpt.com/anticaptcha-plugin.zip'
filehandle, _ = urllib.request.urlretrieve(url)
# estrai
with zipfile.ZipFile(filehandle, "r") as f:
f.extractall("plugin")
# imposta la chiave dell'API nel file di configurazione
api_key = "YOUR_API_KEY_HERE!"
file = Path('./plugin/js/config_ac_api_key.js')
file.write_text(file.read_text().replace("antiCapthaPredefinedApiKey = ''", "antiCapthaPredefinedApiKey = '{}'".format(api_key)))
# comprimi di nuovo la directory plugin in plugin.zip
zip_file = zipfile.ZipFile('./plugin.zip', 'w', zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk("./plugin"):
for file in files:
path = os.path.join(root, file)
zip_file.write(path, arcname=path.replace("./plugin/", ""))
zip_file.close()
# imposta le opzioni di avvio del browser
options = webdriver.ChromeOptions()
options.add_extension('./plugin.zip')
# imposta le opzioni di avvio del browser
browser = webdriver.Chrome('./chromedriver', options=options)
# vai alla pagina bersaglio
browser.get('https://anti-captcha.com/demo/?page=recaptcha_v2_textarea')
# compila il modulo
browser.find_element_by_css_selector('#login').send_keys('Test login')
browser.find_element_by_css_selector('#password').send_keys('Test password')
# aspetta che compaia il selettore "solved"
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))
# premi il pulsante invia
browser.find_element_by_css_selector('#submitButton').click()
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