قائمة الوثائق

كيفية استخدام إضافة Anti-Captcha بواسطة محرك Puppeteer أو Selenium

Puppeteer و Selenium هما المحركين الأساسيين لأتمتة المتصفح. وتعمل الإضافة الخاصة بنا معهم بشكل جيد. وفي هذا المقال سنستعرض كيفية استخدام Puppeteer و Selenium مع لغات NodeJS و بايثون على الترتيب. كما أننا ننصح بشدة باستخدام NodeJS + Puppeteer لأن البيئة الخاصة بها أكثر ملائمة.

1. تثبيت الحزم البرمجية المطلوبة لتشغيل الإضافة. لتشغيل NodeJs ينبغي تثبيت حزم npm المذكورة أدناه، ولتشغيل بايثون، يجب تثبيت وتحميل حزم "chromedriver" الموجودة في هذه الصفحة. يجب أن يوافق إصدار المُشغل إصدار متصفح الكروم المُثبت على نظامك.

NodeJS
          npm install adm-zip puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
        
Python
          pip install selenium
        

2. تحميل الإضافة بصيغة مضغوطة من أجل متصفح كروم، ثم استخراج الملف المضغوط في مجلد المشروع. توجد الإصدارات الفعلية هنا. يمكنك القيام بذلك عن طريق السطور البرمجية التالية:

NodeJS
          //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);
})();
        
Python
          import urllib.request
import zipfile

url = 'https://antcpt.com/anticaptcha-plugin.zip'
# download the plugin
filehandle, _ = urllib.request.urlretrieve(url)
# unzip it
with zipfile.ZipFile(filehandle, "r") as f:
    f.extractall("plugin")
        

3. الخطوة التالية، إعداد مفتاح API الخاص بك في ملف ./plugin/js/config_ac_api_key.js . يمكنك إيجاد مفتاح API الخاص بك في منطقة العملاء. وستحتاج إلى وجود رصيد في حسابك من أجل تشغيله.

NodeJS
          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!')
}
        
Python
          from pathlib import Path
import zipfile

# set API key in configuration file
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)))

# zip plugin directory back to 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. بدأ تشغيل المتصفح واستخدام الإضافة. في حالة استخدام محرك Puppeteer فإننا نوصي باستخدام إضافة 'puppeteer-extra-plugin-stealth' الخاصة بحزمة 'puppeteer-extra' والتي تعمل على إخفاء كل علامات أتمتة الويب في متصفح كروم.

NodeJS
          //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();
})();
        
Python
          from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_extension('./plugin.zip')

browser = webdriver.Chrome('./chromedriver', options=options)
        

5. عليك التوجه إلى صفحة الويب المستهدفة لتحرير نموذج إذا كان مطلوبًا. وستلتقط الإضافة الـ recaptcha تلقائيًا وتبدأ بحلها.

NodeJS
          (async () => {
    const url = 'https://anti-captcha.com/tutorials/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);

})();
        
Python
          browser.get('https://anti-captcha.com/tutorials/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. تحتاج الخطوة القادمة المزيد من الاهتمام. حيث تتطلب بعض نماذج الويب أن يقوم المستخدم بالضغط على زر الإرسال بعد حل الـ recaptcha، ويستخدم البعض الآخَر استدعاء ويعمل على إرساله بشكل تلقائي. ففي الحالة الأولى نحتاج للضغط على زر إرسال بعد حل الـ reCAPTCHA مباشرة. ولعمل ذلك في التوقيت الصحيح، ينبغي انتظار ظهور مُحدد .antigate_solver.solved ثم الضغط على زر الإرسال بعد ذلك.

NodeJS
          // 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('recaptcha solved');

// press submit button
await Promise.all([
    page.click('#submitButton'),
    page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('task completed, form with recaptcha bypassed');
        
Python
          # wait for "solved" selector to come up
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))
# press submit button
browser.find_element_by_css_selector('#submitButton').click()
        

:لقد تم الأمر، تم تحرير النموذج، وتم حل الـ recaptcha وتخطيها. أمثلة على كود برمجي كامل

NodeJS
          // 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/tutorials/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('recaptcha solved');

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

})();
        
Python
          import urllib.request
import zipfile
import os
from pathlib import Path
from selenium import webdriver

# download the plugin
url = 'https://antcpt.com/anticaptcha-plugin.zip'
filehandle, _ = urllib.request.urlretrieve(url)
# unzip it
with zipfile.ZipFile(filehandle, "r") as f:
    f.extractall("plugin")

# set API key in configuration file
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)))

# zip plugin directory back to 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()

# set browser launch options
options = webdriver.ChromeOptions()
options.add_extension('./plugin.zip')

# set browser launch options
browser = webdriver.Chrome('./chromedriver', options=options)

# navigate to the target page
browser.get('https://anti-captcha.com/tutorials/v2-textarea')

# fill the form
browser.find_element_by_css_selector('#login').send_keys('Test login')
browser.find_element_by_css_selector('#password').send_keys('Test password')

# wait for "solved" selector to come up
webdriver.support.wait.WebDriverWait(browser, 120).until(lambda x: x.find_element_by_css_selector('.antigate_solver.solved'))

# press submit button
browser.find_element_by_css_selector('#submitButton').click()
        

مكافأة: يوجد خدعة سحرية لتشغيل الإضافة في وضع البرمجة الخلفية (وضع لا يشمل واجهة مستخدم) لأن متصفح كروم لا يدعم الأتمتة بواسطة الإضافة. ولفعل ذلك، ينبغي عليك استخدام خاصية تسمىXvfb تعمل على توفير بيئة سطح مكتب افتراضية من أجل تشغيل تطبيقك

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