Menu

Paano gamitin ang plugin ng Anti-Captcha sa Puppeteer o Selenium

Ang Puppeteer at Selenium ang dalawang pangunahing makina para sa awtomasyon ng browser at ang aming plugin ay madaling naisasama sa mga ito. Sa artikulong ito ay ipakikita namin kung paano ito gamitin sa Puppeteer at Selenium para sa mga lenggwaheng pang-program na NodeJS at Python. Kung pipili ka sa dalawang ito, inirerekomenda namin ang NodeJS+Puppeteer sa katutubong environment nito.

1. I-install ang mga dependency. Para sa NodeJS i-install lamang ang mga npm package sa ibaba, para sa pag-install ng mga Python package at i-download ang executable na "chromedriver" sa pahinang ito. Ang bersiyon ng driver ay dapat na tugma sa bersiyon ng Chrome na na-install sa iyong sistema.

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

2. I-download ang plugin na nasa bersiyong ZIP para sa iyong Chrome, i-unzip ito sa folder ng iyong proyekto. Ang mga aktwal na bersiyon ay nakalagay rito. Puwede mo rin itong gawin nang naka-program:

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 () => {
    // download the plugin
    await new Promise((resolve) => {
        https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
    })
    // unzip it
    const zip = new AdmZip("./plugin.zip");
    await zip.extractAllTo("./plugin/", true);
})();

3. Sunod, i-configure ang iyong susi ng API sa file na ./plugin/js/config_ac_api_key.js. Maaari mong makita ang iyong susi ng API sa lugar ng mga kostumer. Kailangan mo ng positibong balanse upang mapagana ito.

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. I-initialize ang browser gamit ang plugin. Para sa Puppeteer inirerekomenda namin ang plugin na 'puppeteer-extra-plugin-stealth' para sa 'puppeteer-extra' na package, na itinatago ang lahat ng mga palatandaan ng web-automated na browser na 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. Pumunta sa puntiryang pahina at punan ang form kung kinakailangan. Ang plugin ay makukuha ang Recaptcha nang awtomatiko at sisimulang resolbahin ito.

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);
    }
    // disable navigation timeout errors
    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. Ang susunod na parte ay medyo nakakalito. Ilang mga web form ay kinakailangan na ang gumagamit ay pindutin ang submit na buton pagkatapos malutas ang Recaptcha, ang iba ay gumagamit ng mga callback at isinusumite ito nang awtomatiko. Sa unang kaso nais nating pindutin ang submit na buton pagkatapos mismong malutas ang Recaptcha. Upang magawa ito sa tamang oras, mangyaring hintayin ang selector na .antigate_solver.solved na lumabas at saka pindutin ang submit na buton.

Javascript
Python
// wait for "solved" selector to come up
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') }}');

// press submit button
await Promise.all([
    page.click('#submitButton'),
    page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('task completed, form with recaptcha bypassed');

Ayun na nga, ang form ay napunan, ang Recapatcha ay nalutas at na-bypass. Mga buong code na halimbawa:

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 () => {
    // download the plugin
    await new Promise((resolve) => {
        https.get(pluginURL, resp => resp.pipe(fs.createWriteStream('./plugin.zip').on('close', resolve)));
    })
    // unzip it
    const zip = new AdmZip("./plugin.zip");
    await zip.extractAllTo("./plugin/", true);

    // set API key in configuration file
    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();
        }
    });

    // set browser launch options
    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 {
        // launch browser with the plugin
        const browser = await puppeteer.launch();
        page = await browser.newPage();
    } catch (e) {
        console.log('could not launch browser: '+e.toString())
        return;
    }

    // navigate to the target page
    try {
        await page.goto(url, {
            waitUntil: "networkidle0"
        });
    } catch (e) {
        console.error('err while loading the page: '+e);
    }

    // disable navigation timeout errors
    await page.setDefaultNavigationTimeout(0);

    // fill the form
    await page.$eval('#login', (element, login) => {
        element.value = login;
    }, login);
    await page.$eval('#password', (element, password) => {
        element.value = password;
    }, password);

    // wait for "solved" selector to come up
    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') }}');

    // press submit button
    await Promise.all([
        page.click('#submitButton'),
        page.waitForNavigation({ waitUntil: "networkidle0" })
    ]);
    console.log('recaptcha solved');

})();

Bonus: mayroong trick upang mapagana ang plugin sa mode na headless, dahil ang Chrome ay hindi sinusuportahan ang awtomasyon ng browser gamit ang mga plugin. Gamitin ang utility na tinatawag na Xvfb na nagbibigay ng desktop na bertuwal para sa iyong aplikasyon.

# install the package
apt-get install -y xvfb

# set display variable
export DISPLAY=:0

# start Xvfb daemon in the background (only once)
/usr/bin/Xvfb :0 -screen 0 1024x768x24 &

# wait a bit to let it come up (only once)
sleep 5

# add prefix "xvfb-run" to "node" or "python" script
xvfb-run node myscript.js
# or
xvfb-run python myscript.py