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

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

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:

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 pouvez trouver votre clé API dans la zone clients. Vous aurez besoin d'un solde positif pour que cela fonctionne.

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

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 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