Comment utiliser le plugin Anti-Captcha avec Puppeteer ou Selenium
Puppeteer et Selenium sont deux moteurs principaux pour l'automatisation du navigateur et notre plugin s'y intègre de manière transparente. Dans cet article, nous montrerons comment l'utiliser dans Puppeteer et Selenium pour les langages de programmation NodeJS et Python respectivement. Si vous choisissez entre deux, nous recommandons fortement NodeJS+Puppeteer pour son environnement natif.
1. Installez les dépendances. Pour NodeJS, il suffit d'installer les packages npm ci-dessous, pour Python installez les packages et téléchargez l'éxécutable "chromedriver" à partir de cette page. La version du pilote doit correspondre à la version de Chrome installée sur votre système.
npm install adm-zip puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
pip install selenium
2. Téléchargerz le plugin version ZIP pour Chrome, décompressez-le dans votre dossier de projet. Les versions réelles se trouvent ici. Vous pouvez également le faire par programmation:
//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 () => {
// téléchargez le plugin
await new Promise((resolve) => {
https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
})
// décompressez-le
const zip = new AdmZip("./plugin.zip");
await zip.extractAllTo("./plugin/", true);
})();
import urllib.request
import zipfile
url = 'https://antcpt.com/anticaptcha-plugin.zip'
# téléchargez le plugin
filehandle, _ = urllib.request.urlretrieve(url)
# décompressez-le
with zipfile.ZipFile(filehandle, "r") as f:
f.extractall("plugin")
3. Ensuite, configurez votre clé API dans le fichier ./plugin/js/config_ac_api_key.js. Vous pouvez trouver votre clé API dans la zone clients. Vous aurez besoin d'un solde positif pour que cela fonctionne.
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
# définissez la clé API dans le fichier de configuration
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)))
# compressez le répertoire du plugin dans 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. Initialisez le navigateur avec le plugin. Pour Puppeteer nous recommandons le plugin 'puppeteer-extra-plugin-stealth' pour le package 'puppeteer-extra', qui cache tous les signes du navigateur Web automatisé 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. Naviguez vers une page cible et remplissez un formulaire si nécessaire. Le plugin récupérera Recaptcha automatiquement et va commencer à le résoudre.
(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);
}
// désactivez les erreurs de délai de navigation
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. Ensuite, c'est une partie un peu délicate. Quelques formulaires Web exigent que l'utilisateur appuie sur un bouton d'envoi après avoir résolu Recaptcha, les autres utilisent les callbacks et les soumettent automatiquement. Dans le premier cas, nous voulons appuyer sur le bouton Soumettre juste après la résolution de Recaptcha. Pour le faire au bon moment, il suffit d'attendre le sélecteur .antigate_solver.solved, puis appuyez sur le bouton Soumettre.
// attendez le sélecteur "résolu"
await page.waitForSelector('.antigate_solver.solved').catch(error => console.log('failed to wait for the selector'));
console.log('recaptcha résolu');
// cliquez sur le bouton soumettre
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('tâche terminée, formulaire avec recaptcha contourné');
# attendez le sélecteur "résolu"
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))
# cliquez sur le bouton soumettre
browser.find_element_by_css_selector('#submitButton').click()
Ça y est, le formulaire est rempli, Recaptcha est résolu et contourné. Exemples de code complet:
// 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 () => {
// téléchargez le plugin
await new Promise((resolve) => {
https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
})
// décompressez-le
const zip = new AdmZip("./plugin.zip");
await zip.extractAllTo("./plugin/", true);
// définissez la clé API dans le fichier de configuration
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();
}
});
// définissez les options de lancement du navigateur
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 {
// démarrez le navigateir avec le plugin
const browser = await puppeteer.launch();
page = await browser.newPage();
} catch (e) {
console.log('could not launch browser: '+e.toString())
return;
}
// allez sur la page cible
try {
await page.goto(url, {
waitUntil: "networkidle0"
});
} catch (e) {
console.error('err while loading the page: '+e);
}
// désactivez les erreurs de délai de navigation
await page.setDefaultNavigationTimeout(0);
// remplissez le formulaire
await page.$eval('#login', (element, login) => {
element.value = login;
}, login);
await page.$eval('#password', (element, password) => {
element.value = password;
}, password);
// attendez le sélecteur "résolu"
await page.waitForSelector('.antigate_solver.solved').catch(error => console.log('failed to wait for the selector'));
console.log('recaptcha résolu');
// cliquez sur le bouton soumettre
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('recaptcha résolu');
})();
import urllib.request
import zipfile
import os
from pathlib import Path
from selenium import webdriver
# téléchargez le plugin
url = 'https://antcpt.com/anticaptcha-plugin.zip'
filehandle, _ = urllib.request.urlretrieve(url)
# décompressez-le
with zipfile.ZipFile(filehandle, "r") as f:
f.extractall("plugin")
# définissez la clé API dans le fichier de configuration
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)))
# compressez le répertoire du plugin dans 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()
# définissez les options de lancement du navigateur
options = webdriver.ChromeOptions()
options.add_extension('./plugin.zip')
# définissez les options de lancement du navigateur
browser = webdriver.Chrome('./chromedriver', options=options)
# allez sur la page cible
browser.get('https://anti-captcha.com/demo/?page=recaptcha_v2_textarea')
# remplissez le formulaire
browser.find_element_by_css_selector('#login').send_keys('Test login')
browser.find_element_by_css_selector('#password').send_keys('Test password')
# attendez le sélecteur "résolu"
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))
# cliquez sur le bouton soumettre
browser.find_element_by_css_selector('#submitButton').click()
Bonus : il y a une astuce pour faire tourner le plugin en mode headless, puisque Chrome ne supporte l'automatisation du navigateur avec des plugins. Utilisez l'outil appelé Xvfb qui fournit un bureau virtuel pour votre application.
# installez le package
apt-get install -y xvfb
# définissez la variable d'affichage
export DISPLAY=:0
# démarrez le daemon Xvfb en arrière-plan (une seule fois)
/usr/bin/Xvfb :0 -screen 0 1024x768x24 &
# attendez un peu pour le laisser monter (une seule fois)
sleep 5
# ajoutez le préfixe "xvfb-run" au script "node" ou "python"
xvfb-run node myscript.js
# ou
xvfb-run python myscript.py