Menu

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 paquets npm ci-dessous, pour Python, il faut installer les paquets et télécharger l'exécutable "chromedriver" sur cette page. La version du pilote doit correspondre à la version de Chrome installée sur votre système.

Javascript
Python
npm install adm-zip puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

2. Téléchargez le plugin en version ZIP pour Chrome, décompressez-le dans le dossier de votre projet. Les versions actuelles sont situées ici. Vous pouvez également le faire par programme:

Javascript
Python
//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);
})();

3. Ensuite, configurez votre clé API dans le fichier ./plugin/js/config_ac_api_key.js. Vous trouverez votre clé API dans espace client. Vous aurez besoin d'un solde positif pour le faire fonctionner.

Javascript
Python
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. 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.

Javascript
Python
//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. 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.

Javascript
Python
(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);

})();

6. La suite est un peu plus délicate. Quelques formulaires web exigent que l'utilisateur appuie sur un bouton d'envoi après avoir résolu le Recaptcha, les autres utilisent des callbacks et les soumettent automatiquement. Dans le premier cas, nous voulons appuyer sur le bouton de soumission juste après que Recaptcha a été résolu. Pour le faire au bon moment, il suffit d'attendre que le sélecteur .antigate_solver.solved appuie sur le bouton Soumettre.

Javascript
Python
// attendez le sélecteur "résolu" 
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') }}');

// 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é');

Ça y est, le formulaire est rempli, Recaptcha est résolu et contourné. Exemples de code complet:

Javascript
Python
// 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('{{ $t('articles.how-to-integrate.code-comments.recaptcha-solved') }}');

    // cliquez sur le bouton soumettre
    await Promise.all([
        page.click('#submitButton'),
        page.waitForNavigation({ waitUntil: "networkidle0" })
    ]);
    console.log('recaptcha résolu');

})();

Bonus: il y a une astuce pour exécuter le plugin dans un mode sans tête, car Chrome ne prend pas en charge l'automatisation du navigateur avec les plugins. Utilisez l'utilitaire 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