Python Selenium注册Discord账号 hcaptcha token提交回调问题
Discord自动注册hCaptcha回调触发解决方案
你遇到的问题核心是Discord把hCaptcha的验证成功回调封装在React组件闭包内,没有挂载到全局window对象上,所以常规查找全局回调函数的方法无效。以下是可直接落地的实现方案,按稳定性排序:
方案1:直接读取hCaptcha容器绑定的回调执行(优先使用)
hCaptcha渲染时会把回调函数名存在容器DOM的data-callback属性上,不需要逆向React逻辑,直接取出来传token执行即可。
把你代码末尾# code to submit captcha token的位置替换为以下代码:
# 注入token的逻辑保留,替换为querySelector写法兼容性更好 driver.execute_script(""" const captchaToken = arguments[0]; // 给两个验证响应域赋值 document.querySelector('textarea[name="g-recaptcha-response"]').value = captchaToken; document.querySelector('textarea[name="h-captcha-response"]').value = captchaToken; // 定位hCaptcha容器,取出绑定的回调函数 const hcaptchaIframe = document.querySelector('iframe[src*="hcaptcha.com"]'); if (hcaptchaIframe) { const captchaBox = hcaptchaIframe.closest('[data-callback]'); const callbackName = captchaBox.dataset.callback; // 执行回调传入token window[callbackName](captchaToken); } """, captcha_token) # 回调执行后等待2秒页面跳转即可,不需要重复点提交 time.sleep(2)
方案2:派发验证成功事件(兼容闭包加密场景)
如果方案1取不到data-callback属性,说明Discord做了额外的属性混淆,直接模拟hCaptcha验证完成的事件流,让页面监听逻辑自动接收验证成功信号:
driver.execute_script(""" const captchaToken = arguments[0]; document.querySelector('textarea[name="g-recaptcha-response"]').value = captchaToken; document.querySelector('textarea[name="h-captcha-response"]').value = captchaToken; // 派发hCaptcha全局成功事件 const successEvent = new CustomEvent('hcaptcha-success', {detail: {token: captchaToken}}); window.dispatchEvent(successEvent); // 兜底触发表单提交 setTimeout(() => { const regForm = document.querySelector('form'); if (regForm) regForm.dispatchEvent(new Event('submit', {bubbles: true, cancelable: true})); }, 800); """, captcha_token)
必须修复的代码逻辑坑
你当前的代码顺序有致命问题,会导致token失效:
- 你现在是填完注册信息后先点击了提交按钮触发验证码弹窗,再异步请求capmonster获取token,等你拿到token时hCaptcha的验证上下文已经过期,就算触发回调也会被判定无效。
- 正确执行顺序调整为:
- 填写所有注册信息(邮箱、用户名、密码、生日、协议勾选)
- 不要点击提交按钮,先调用capmonster接口获取captcha token
- 注入token到两个响应文本域
- 执行上述回调触发/事件派发逻辑
- 最后再点击提交按钮,或者直接触发表单submit事件
额外避坑提示
Discord默认会检测Selenium自动化特征,就算验证码验证通过也可能被拦截,建议启动Chrome时加上以下参数规避检测:
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--disable-blink-features=AutomationControlled') chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) chrome_options.add_experimental_option('useAutomationExtension', False) driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options) # 覆盖navigator.webdriver标识 driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})" })
内容的提问来源于stack exchange,提问作者Anton Goncharuk
相关产品推荐
相关产品推荐

