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.
npm install adm-zip puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
pip install selenium
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:
//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);
})();
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. 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.
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
# 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. 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.
//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. Pumunta sa puntiryang pahina at punan ang form kung kinakailangan. Ang plugin ay makukuha ang Recaptcha nang awtomatiko at sisimulang resolbahin ito.
(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);
})();
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. 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.
// 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');
# 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()
Ayun na nga, ang form ay napunan, ang Recapatcha ay nalutas at na-bypass. Mga buong code na halimbawa:
// 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('recaptcha solved');
// press submit button
await Promise.all([
page.click('#submitButton'),
page.waitForNavigation({ waitUntil: "networkidle0" })
]);
console.log('recaptcha solved');
})();
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/demo/?page=recaptcha_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()
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