在Puppeteer中进行Web Scraping时验证码如何处理?

IT技术 javascript web-scraping captcha puppeteer
2021-03-07 21:56:14

我正在使用 Puppeteer 进行网页抓取,但我刚刚注意到,有时,由于我通过计算机进行的访问量太大,我尝试抓取的网站会要求提供验证码。验证码表单如下所示:

验证码

所以,我需要关于如何处理这个问题的帮助。我一直在考虑将验证码表单发送到客户端,因为我使用 Express 和 EJS 以便将值发送到我的索引网站,但我不知道 Puppeteer 是否可以发送类似的东西。

有任何想法吗?

4个回答

这是一个 reCAPTCHA(第 2 版,在此处查看演示),向您显示该页面的所有者不希望您自动抓取该页面。

您的选择如下:

选项 1:停止抓取或尝试使用官方 API

由于页面所有者不希望您抓取该页面,您可以简单地尊重该决定并停止抓取。也许有一个文档化的 API 可供您使用。

选项 2:自动化/外包验证码解决方案

整个行业都有人(通常在发展中国家)为其他人的机器人填写验证码。我不会链接到任何特定站点,但您可以查看Md. Abu Taher的其他答案以获取有关该主题的更多信息或搜索验证码求解器

选项 3:自己解决验证码

为此,让我解释一下 reCAPTCHA 的工作原理以及使用它访问页面时会发生什么。


reCAPTCHA (v2) 的工作原理

每个页面都有一个ID,可以通过查看源代码来查看,例如:

<div class="g-recaptcha form-field" data-sitekey="ID_OF_THE_WEBSITE_LONG_RANDOM_STRING"></div>

加载 reCAPTCHA 代码后,它将向表单添加一个没有值响应文本区域。它看起来像这样:

<textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="... display: none;"></textarea>

在您解决挑战后,当提交表单时,reCAPTCHA 将向此文本字段添加一个很长的字符串(稍后可以由后端的服务器/reCAPTCHA 服务进行检查)。


如何自己解决验证码

通过复制该textarea字段的值,您可以将“已解决的挑战”从一个浏览器转移到另一个浏览器(这也是解决方案为您提供的服务)。整个过程如下所示:

  1. 检测页面是否.g-recaptcha在“爬行”浏览器中使用 reCAPTCHA(例如检查
  2. 使用相同的 URL 以非无头模式打开第二个浏览器
  3. 自己解决验证码
  4. 从以下位置读取值: document.querySelector('#g-recaptcha-response').value
  5. 将该值放入第一个浏览器: document.querySelector('#g-recaptcha-response').value = '...'
  6. 提交表格

更多信息/阅读

谷歌没有太多公开信息,reCAPTCHA 究竟是如何工作的,因为这是机器人创建者和谷歌检测算法之间的猫捉老鼠游戏,但网上有一些资源提供更多信息:

  • 来自 Google 的官方文档:显然,他们只是解释了基础知识,而不是“背后”的工作原理
  • InsideReCaptcha:这是 2014 年的一个项目,它试图“逆向工程”reCAPTCHA。虽然这已经很老了,但页面上仍然有很多有用的信息。
  • 关于 stackoverflow 的另一个问题:这个问题包含一些关于 reCAPTCHA 的有用信息,但也包含许多关于如何欺骗 reCAPTCHA 的推测性(并且很可能)过时的方法。
如果该站点允许您在显示 CAPTCHA 之前至少提出一个请求,则还有第四种选择,即使用具有“住宅”IP 地址的代理提供商。他们给你一堆 IP 地址,你从一个 IP 地址发出请求,直到你获得 CAPTCHA,然后切换到一个新的 IP 地址。
2021-04-22 21:56:14
@sumeet AFAIK 验证码未绑定到浏览器或 IP 地址。如果您解决了验证码,则可以通过,无论您的浏览器“指纹”多么可疑。
2021-04-23 21:56:14
@ThomasDondorf 你能向我解释一下第三方验证码解决方案是如何使用另一个 IP 和浏览器打开包含验证码的页面的吗?谷歌不跟踪正在解决验证码的 IP 和浏览器吗?以及如何使用使用其他浏览器、IP 和位置解决的响应?
2021-04-29 21:56:14

您应该使用以下组合:

  • 如果目标网站提供 API,请使用该 API。这是最合法的方式。
  • 增加抓取请求之间的等待时间,不要向服务器发送大量请求。
  • 经常更改/轮换 IP。
  • 更改用户代理、浏览器视口大小和指纹。
  • 使用第三方解决方案进行验证码。
  • 自己解决验证码,检查 Thomas Dondorf 的答案。基本上你需要等待验证码出现在另一个浏览器上,从那里解决它。第三方解决方案会为您做到这一点。

免责声明:请勿使用反验证码插件/服务来滥用资源。资源很贵。


基本上这个想法是使用像 (2captcha) 这样的反验证码服务来处理持久化的验证码。

您可以使用puppeteer-extra-plugin-recaptcha由 berstend调用这个插件

// puppeteer-extra is a drop-in replacement for puppeteer,
// it augments the installed puppeteer with plugin functionality
const puppeteer = require('puppeteer-extra')

// add recaptcha plugin and provide it your 2captcha token
// 2captcha is the builtin solution provider but others work as well.
const RecaptchaPlugin = require('puppeteer-extra-plugin-recaptcha')
puppeteer.use(
  RecaptchaPlugin({
    provider: { id: '2captcha', token: 'XXXXXXX' },
    visualFeedback: true // colorize reCAPTCHAs (violet = detected, green = solved)
  })
)

之后,您可以照常运行浏览器。它将获取页面上的任何验证码并尝试解决它。您必须找到不同站点的提交按钮(如果存在)。

// puppeteer usage as normal
puppeteer.launch({ headless: true }).then(async browser => {
  const page = await browser.newPage()
  await page.goto('https://www.google.com/recaptcha/api2/demo')

  // That's it, a single line of code to solve reCAPTCHAs 🎉
  await page.solveRecaptchas()

  await Promise.all([
    page.waitForNavigation(),
    page.click(`#recaptcha-demo-submit`)
  ])
  await page.screenshot({ path: 'response.png', fullPage: true })
  await browser.close()
})

PS:

  • 还有其他插件,即使我做了一个非常简单的插件,因为即使是像我这样的人,验证码也越来越难解决。您可以在此处阅读代码
  • 我强烈不隶属于 2Captcha 或上述任何其他第三方服务。
  • 我创建了自己的解决方案,类似于 Thomas Dondorf 的另一个答案,但很快就放弃了,因为 Captcha 变得越来越荒谬,而且我没有精力去解决它们。
不,您从 2captcha 购买积分,使用他们的 API(我不隶属于他们)。如果您不想使用金钱,那么唯一的另一种方法是自己解决验证码,我没有将其添加到我的答案中,但 Thomas Dondorf 在另一个答案中添加了它。有人必须解决验证码,您或其他人。:D
2021-04-20 21:56:14
遗憾的是,目标网站没有提供可使用的 API。我已经搜索过了...我已经测试了您的代码,但似乎有问题。它不能解决验证码,因为它周围出现一个红色边框,它告诉我证明我不是机器人:i.imgur.com/jIVPvuE.png是因为我的语言与英语不同吗?
2021-04-23 21:56:14
另外,我应该在令牌中放入什么?我已将那些 XXX 替换为 data-sitekey 值。那是对的吗?
2021-05-15 21:56:14

可以使用代理服务器,以便目标站点不会检测到来自单个 IP 地址的大量响应。

(翻译成谷歌翻译)

我尝试了@Thomas Dondorf 的建议,但我认为“如何自己解决验证码”部分中描述的步骤的问题在于验证码的令牌仅有效一次。我将尝试在下面详细解释所有内容。

我在用什么

我使用第一个浏览器(无法解决验证码的浏览器)Google Chrome,以及第二个浏览器(我解决验证码并获取令牌的浏览器)Firefox。

脚步

  1. 我在这个网站上手动解决了验证码https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php
  2. document.querySelector('#g-recaptcha-response').value在 google chrome 控制台中输入以下代码,但出现错误(VM22:1 Uncaught TypeError: Cannot read property 'value' of null at :1:48),所以我只是通过在 Google Chrome 中打开 Elements 来搜索令牌并g-recaptcha-response使用 CTRL+F搜索
  3. 我复制了 recaptcha 的令牌(这是一张图像,在以绿色突出显示的文本之后显示令牌的位置)这是具有令牌的网页代码的一部分
  4. document.querySelector('#g-recaptcha-response').value = '...'在 firefox 控制台中键入以下代码,用刚刚复制的 recaptcha 令牌替换“...”
  5. 我收到以下错误错误,如果您然后单击链接文档,您会读到该错误是由于令牌只能使用一次这一事实,当然它已经用于您的 CAPTCHA刚刚解决了获取令牌本身(所以似乎令牌的唯一目标是说 CAPTCHA 已经解决了,这似乎是一种防止重放攻击的防御措施,如官方文档中所述重新验证