如何使用Puppeteer绕过验证码
CAPTCHA 是一个重要的网络抓取障碍,可以让人类通过并阻止机器人。但今天,我们将了解Puppeteer如何帮助您克服该技术,以及您可以做些什么来使其更有效。
简而言之,使用 Puppeteer 绕过验证码的方法有:
- 使用付费求解器。
- 实施免费求解器。
- 面具基地傀儡师。
- 掩盖你的要求。
Puppeteer 可以破解验证码吗?
完整的答案是有两种主要方法:避免和解决它。
由于挑战主要基于可疑活动而提示,并且无头浏览器帮助网络抓取工具模仿人类行为,Puppeteer 帮助我们避免它。但是,我们需要为基础 Puppeteer 增压以提高其成功率。
然而,最直接的场景是提示挑战时,你只想解决它。为此,您必须使用带有 Puppeteer 的第三方求解器。
本教程将涵盖这两种方法,以帮助您使用 Puppeteer 绕过 CAPTCHA。
方法 #1:使用带有 Puppeteer 的付费验证码求解器
假设您在抓取数据时遇到受验证码保护的表单,需要解决它。在这里,我们将使用 2Captcha,这是一种基于 API 的服务,它雇用人类来解决问题并返回答案。
2Captcha 的演示页面是我们将用来说明如何从头开始将求解器与 Puppeteer 集成的沙箱。
首先,在 2Captcha 上注册以获取 API 密钥。然后,安装 Puppeteer 和requests
模块。
npm install puppeteer request
现在,让我们编写一个脚本来打开您要抓取的网站,截取验证码的屏幕截图并将其发送到服务。
const puppeteer = require('puppeteer'); const request = require('request'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // navigate to the page with the CAPTCHA await page.goto('https://2captcha.com/demo/normal'); // take a screenshot of the CAPTCHA const screenshot = await page.screenshot(); // convert the screenshot to a base64 encoded string const image = new Buffer(screenshot).toString('base64'); // send the image to the 2Captcha API request.post({ url: 'http://2captcha.com/in.php', formData: { key: 'your_2captcha_api_key', method: 'base64', body: image } }, async (error, response, body) => { if (error) { console.error(error); }
我们将使用 ID 捕获 API 响应,如下所示。
// get the CAPTCHA ID from the 2Captcha API response const captchaId = body.split('|')[1]; // request the CAPTCHA solution from the 2Captcha API request.get({ url: `http://2captcha.com/res.php?key=your_2captcha_api_key&action=get&id=${captchaId}` }, (error, response, body) => { if (error) { console.error(error); } });
一旦我们得到解决方案,我们就可以把它放在页面上来解决测试。
// get the CAPTCHA solution from the 2Captcha API response const captchaSolution = body.split('|')[1]; // use the CAPTCHA solution in your Puppeteer script await page.type('#captcha-input', captchaSolution); await page.click('#submit-button');
这就是我们的完整脚本的样子:
const puppeteer = require('puppeteer'); const request = require('request'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // navigate to the page with the CAPTCHA await page.goto('https://example.com/captcha'); // take a screenshot of the CAPTCHA const screenshot = await page.screenshot(); // convert the screenshot to a base64 encoded string const image = new Buffer(screenshot).toString('base64'); // send the image to the 2Captcha API request.post({ url: 'http://2captcha.com/in.php', formData: { key: 'your_2captcha_api_key', method: 'base64', body: image } }, async (error, response, body) => { if (error) { console.error(error); } else { // get the CAPTCHA ID from the 2Captcha API response const captchaId = body.split('|')[1]; // request the CAPTCHA solution from the 2Captcha API request.get({ url: `http://2captcha.com/res.php?key=your_2captcha_api_key&action=get&id=${captchaId}` }, async (error, response, body) => { if (error) { console.error(error); } else { // get the CAPTCHA solution from the 2Captcha API response const captchaSolution = body.split('|')[1]; // use the CAPTCHA solution in your Puppeteer script await page.type('#captcha-input', captchaSolution); await page.click('#submit-button'); } await browser.close(); }); } }); })();
你使用 Puppeteer 和 2Captcha 解决了你的第一个验证码。
问题是这项服务在大规模抓取时变得昂贵且缓慢。此外,还有一些类型的验证码无法通过 API 求解器解决。
方法#2:实施免费求解器插件
puppeteer-extra-plugin-recaptcha是一个免费的开源模块,可自动解决市场上最流行的两种反机器人技术 reCAPTCHA 和 hCAPTCHA。此外,它还带有 2Captcha 集成,因此您可以在免费模块不够用的情况下使用它。
我们将使用相同的演示页面作为示例目标。
要开始,请安装puppeteer-extra
和recaptcha
.
npm install puppeteer puppeteer-extra puppeteer-extra-plugin-recaptcha
导入库并提供您的 2Captcha API 密钥作为令牌。
const puppeteer = require('puppeteer-extra') const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha') // Use the RecaptchaPlugin with the specified provider (2captcha) and token puppeteer.use( RecaptchaPlugin({ provider: { id: '2captcha', token: 'XXXXXXX' }, visualFeedback: true // Enable visual feedback (colorize reCAPTCHAs) }) )
接下来,导航到您的目标网页并使用该方法初始化求解page.solveRecaptchas()
。
// Launch a headless browser instance puppeteer.launch({ headless: true }).then(async browser => { // Create a new page const page = await browser.newPage() // Navigate to a page containing a reCAPTCHA challenge await page.goto('https://2captcha.com/demo/recaptcha-v2') // Automatically solve the reCAPTCHA challenge await page.solveRecaptchas()
现在,等待解决方案并单击提交按钮。
// Wait for the navigation and click the submit button await Promise.all([ await Promise.all([ page.waitForNavigation(), page.click(`#recaptcha-demo-submit`) ])
完整的代码应该是这样的:
const puppeteer = require('puppeteer-extra') const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha') // Use the RecaptchaPlugin with the specified provider (2captcha) and token puppeteer.use( RecaptchaPlugin({ provider: { id: '2captcha', token: 'XXXXXXX' }, visualFeedback: true // Enable visual feedback (colorize reCAPTCHAs) }) ) // Launch a headless browser instance puppeteer.launch({ headless: true }).then(async browser => { // Create a new page const page = await browser.newPage() // Navigate to a page containing a reCAPTCHA challenge await page.goto('https://2captcha.com/demo/recaptcha-v2') // Automatically solve the reCAPTCHA challenge await page.solveRecaptchas() // Wait for the navigation and click the submit button await Promise.all([ page.waitForNavigation(), page.click(`#recaptcha-demo-submit`) ]) // Take a screenshot of the response page await page.screenshot({ path: 'response.png', fullPage: true }) // Close the browser await browser.close() })
这是结果:
但是,将 CAPTCHA 求解器与 Puppeteer 一起使用主要用于测试目的,而不是大规模抓取,因为它很快就会变得过于昂贵和缓慢。出于这个原因,我们将专注于通过更好地掩盖 Puppeteer 来避免挑战的出现(并在遇到挑战时重新尝试我们的请求)。
方法#3:通过隐身来增强 Puppeteer 以绕过验证码
如前所述,使用 Puppeteer 绕过验证码有两种主要方法:解决和避免。是时候探索第二种方法,让你的爬虫无法被发现了。
Puppeteer Stealth是一个插件,包含多项功能,可解决网站用于检测无头 Chrome 的大多数方法。让我们看看它是如何通过抓取OpenSea来做到这一点的,OpenSea 是一个受反机器人保护的网站,当请求不符合其自然用户阈值时,该网站会显示验证码。
要开始,您必须安装puppeteer-extra
并puppeteer-extra-plugin-stealth
:
npm install puppeteer-extra puppeteer-extra-plugin-stealth
然后,导入模块,将库保存到executablePath
,并启用puppeteer-stealth
使用puppeteer.use(pluginStealth())
:
const puppeteer = require("puppeteer-extra"); const pluginStealth = require("puppeteer-extra-plugin-stealth"); //save to executable path const { executablePath } = require("puppeteer"); // Use stealth puppeteer.use(pluginStealth());
接下来的步骤包括设置视口、导航到页面 URL、等待加载以及截取屏幕截图以跟踪该过程。
// Launch puppеteer-stealth puppeteer.launch({ executablePath: executablePath() }).then(async browser => { // Create a new page const page = await browser.newPage(); // Set page view await page.setViewport({ width: 1280, height: 720 }); // navigate to the website await page.goto("https://www.opensea.io/"); // Wait for page to load await page.waitForTimeout(1000); // Take a screenshot await page.screenshot({ path: "image.png" }); // Close the browser await browser.close(); });
这是完整的代码:
const puppeteer = require("puppeteer-extra"); // Add stealth plugin and use defaults const pluginStealth = require("puppeteer-extra-plugin-stealth"); const { executablePath } = require("puppeteer"); // Use stealth puppeteer.use(pluginStealth()); // Launch puppeteer-stealth puppeteer.launch({ executablePath: executablePath() }).then(async browser => { // Create a new page const page = await browser.newPage(); // Set page view await page.setViewport({ width: 1280, height: 720 }); // navigate to the website await page.goto("https://www.opensea.io/"); // Wait for page to load await page.waitForTimeout(1000); // Take a screenshot await page.screenshot({ path: "image.png" }); // Close the browser await browser.close(); });
恭喜!您离成为网络抓取专家又近了一步。你只是让你的蜘蛛更不易被发现。
但是,更高级的网站保护可以检测到 Puppeteer Stealth。让我们通过在G2 的产品页面上运行相同的脚本来确认:
到目前为止,基础 Puppeteer、puppeteer-extra-plugin-recaptcha 和 2Captcha 并没有解决抓取可扩展性问题。接下来我们将看看最终的解决方案。
方法 #4:ZenRows 的最佳验证码绕过
Puppeteer 是一个强大的工具,但如上面的示例所示,它有其自身的一系列限制。我们要不要找个替代品?
ZenRows 是一款一体化工具,可在单个 API 调用中实现大规模抓取,包括无头浏览器和反验证码功能。让我们看看它的实际效果!我们将尝试抓取 Puppeteer Stealth 失败的 G2 页面。
要开始使用,请注册您的免费 API 密钥。
您将进入 Request Builder,您必须在其中粘贴https://www.g2.com/products/asana/reviews
为目标 URL 并激活Antibot
,JavaScript Rendering
和Premium Proxy
。在这种情况下,我们将使用 SDK 模式。
现在,切换到您的代码编辑器并使用npm
命令安装 ZenRows。
npm install zenrows
最后,将提供的代码粘贴到 Request Builder 和console.log()
响应中。
const { ZenRows } = require("zenrows"); (async () => { const client = new ZenRows("YOUR_API_KEY"); const url = "https://www.g2.com/products/asana/reviews"; try { const { data } = await client.get(url, { "js_render": "true", "antibot": "true", "premium_proxy": "true" }); console.log(data); } catch (error) { console.error(error.message); if (error.response) { console.error(error.response.data); } } })();
这是成功的结果:
<!DOCTYPE html><html class=" cors history json svg es6object promises cssgradients fontface csstransitions"><head><style type="text/css">.turbo-progress-bar { position: fixed; display: block; top: 0; left: 0; height: 3px; background: #0076ff; z-index: 9999; transition: width 300ms ease-out, opacity 150ms 150ms ease-in; transform: translate3d(0, 0, 0); } </style><meta charset="utf-8"><link href="https://www.g2.com/assets/favicon-fdacc4208a68e8ae57a80bf869d155829f2400fa7dd128b9c9e60f07795c4915.ico" rel="shortcut icon" type="image/x-icon"><title>Business Software and Services Reviews | G2</title><meta content="78D210F3223F3CF585EB2436D17C6943" name="msvalidate.01"><meta content="width=device-width, initial-scale=1" name="viewport"><meta content="GNU Terry Pratchett" http-equiv="X-Clacks-Overhead"><meta content="ie=edge" http-equiv="x-ua-compatible"><meta content="en-us" http-equiv="content-language"><meta content="website" property="og:type"><meta content="G2" property="og:site_name"><meta content="@G2dotcom" name="twitter:site"><meta content="Business Software and Services Reviews | G2" property="og:title"><meta content="https://www.g2.com/" property="og:url"><meta content="Compare the best business software and services based on user ratings and social data. Reviews for CRM, ERP, HR, CAD, PDM and Marketing software." property="og:description">
结论
一些使用 Puppeteer 绕过 CAPTCHA的解决方案包括集成求解器和更好地屏蔽浏览器,但它们在很多情况下都无法交付并且无法扩展。对于成功的数据提取项目,您需要一个可扩展且高效的解决方案。