我正在编写一个机器人,在完成任务后,我将使用该机器人抓取reCAPTCHA令牌。我正在尝试使用:
await page.evaluate(() => document.getElementById('recaptcha-token').value)
在将验证码加载到页面上之后,但是每次遇到相同的错误时,都会出现Uncaught (in promise) Error: Evaluation failed: TypeError: Cannot read property 'value' of null
。
我相信此错误部分是由于我要获取的元素的类型为hidden:
<input type="hidden" id="recaptcha-token value="[very long string of letters and numbers]">
我将如何绕开它?
首先,我真的建议您阅读Puppeteer + reCAPTCHA主题上的Thomas Dondorf's answer。
如果您仍然愿意这样做,请在下面阅读我的答案:
<input>
为type=hidden
的事实并不影响操纵p与元素交互的方式,因为它已经在DOM中了。您甚至可以通过运行$('#recaptcha-token').value
在Chrome DevTools Console选项卡上对其进行测试:您将毫无问题地获得其价值。实际上问题出在其他地方。
您当前面临两个问题:
1。)reCAPTCHA在iframe
内,您需要进入内部使Puppeteer与所需的元素进行交互。为此,您需要通过其元素句柄来获取确切的iframe,然后使用contentFrame()从“浏览器”上下文切换到“框架”上下文。
2。)您还需要以下安全禁用参数以启动伪造者: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()