如何使用 Puppeteer 从 iframe 检索 reCAPTCHA 令牌?

Dev*_*ron 1 javascript screen-scraping recaptcha electron puppeteer

我正在编写一个机器人,在任务完成后我试图用它来抓取 reCAPTCHA 令牌。我正在尝试使用:

await page.evaluate(() => document.getElementById('recaptcha-token').value)
Run Code Online (Sandbox Code Playgroud)

验证码加载到页面后,但是每次我都会收到相同的错误:Uncaught (in promise) Error: Evaluation failed: TypeError: Cannot read property 'value' of null

我认为此错误部分是由于我尝试获取的元素属于隐藏类型而引起的:

<input type="hidden" id="recaptcha-token value="[very long string of letters and numbers]">
Run Code Online (Sandbox Code Playgroud)

我该如何绕过这个?

the*_*ton 6

首先,我强烈建议您阅读Thomas Dondorf在 Puppeteer + reCAPTCHA 主题上的回答。

如果你还愿意走这条路,请阅读我下面的回答:


事实上,这<input>type=hidden不会影响 puppeteer 与元素的交互方式,因为它已经在 DOM 中了。您甚至可以通过运行从 Chrome DevTools Console选项卡测试它$('#recaptcha-token').value:您将毫无问题地获得它的值。事实上问题出在其他地方。

您当前面临两个问题:

1.) reCAPTCHA 位于内部,iframe您需要进入其中才能让 Puppeteer 与所需的元素进行交互。为了实现这一点,您需要通过元素句柄获取确切的 iframe,然后使用contentFrame()从“浏览器”上下文切换到“框架”上下文。

2.) 您还需要以下安全禁用参数来启动 puppeteer:args: ['--disable-web-security', '--disable-features=IsolateOrigins,site-per-process']因为由于同源策略,默认情况下不允许您进入 iframe 内部。

示例 reCAPTCHA 页面:https://patrickhlauke.github.io/recaptcha/

示例脚本:

const puppeteer = require('puppeteer')

async function getToken() {
  const browser = await puppeteer.launch({
    headless: false,
    args: ['--disable-web-security', '--disable-features=IsolateOrigins,site-per-process']
  })
  const page = await browser.newPage()

  try {
    await page.goto('https://patrickhlauke.github.io/recaptcha/')

    await page.waitForSelector('.g-recaptcha > div > div > iframe')
    const elementHandle = await page.$('.g-recaptcha > div > div > iframe')
    const frame = await elementHandle.contentFrame()
    const value = await frame.evaluate(() => document.getElementById('recaptcha-token').value)
    console.log(value)
  } catch (e) {
    console.error(e)
  }

  await browser.close()
}
getToken()
Run Code Online (Sandbox Code Playgroud)