使用 2captcha 绕过验证码

之前 SteamDB 自带 Cloudflare 的 5 秒等待防 DDOS,近期又添加了 hcaptcha 验证,这使之前写的爬虫失效了,现需要绕过验证页面,获取真实的网页信息

下文将展示如何绕过 hcaptcha,语言为 python,需要接入 2captcha 验证码识别平台

2captcha 也适用于其他验证码,如 reCaptcha、TikTok captcha、Arkose Labs FunCaptcha、文字验证码等等,绕过流程基本相同(非广告,仅作介绍)

准备

  • 2captcha API Key
    • 需充值,$2.99/1000次请求
  • python 3 环境
    • 使用 selenium 作为自动化测试工具
    • 需要引入 2captcha 官方 SDK 2captcha-python

参考

步骤

步骤大致如下:

浏览器打开页面,hcaptcha 出现

此时我们需要做的就是在本页面的 HTML 代码内找到代表当前验证会话的 sitekey,将 sitekey 连同网页 URL 提交到 2captcha 平台

之后等待 2captcha 运行自己的一套验证码破解流程,2captcha 破解完毕后会返回一个 token,拿到这个 token 后,将其提交到当前的 hcaptcha 页面

之后浏览器会自动跳转,相当于人工完成了验证

流程图如下:

安装 python 环境

执行指令安装 SDK

pip3 install 2captcha-python

selenium 相关问题详见

获取 2captcha API Key

前往 2captcha,注册账号并保证钱包内有足够余额

如果愿意可以使用我的 ref

注册后即可在用户主页看到 API Key

获取 sitekey

不同种类验证码的 sitekey 格式不同,对于 hcaptcha,sitekey 是格式形如 10000000-ffff-ffff-ffff-000000000001 的字符串

以 hcaptcha 为例,寻找 sitekey 需要检查 iframe 标签内的 src 属性,sitekey 在 src 内的 URL 参数中,如下图:

获取 sitekey 代码:

def get_sitekey():  # get captcha sitekey
    logger.debug("Getting sitekey...")
    browser.get(URL) # 打开网页
    time.sleep(FIRST_DELAY)  # 等待验证码加载完毕
    html = BeautifulSoup(browser.page_source, 'lxml') # 使用 CSS Selector
    iframe = html.select('iframe') # 找到 iframe
    source = iframe[0].get('src') # 获取 src 内的 URL
    sitekey = str(source).split("sitekey=")[1] # 以 ‘sitekey=’ 拆分 URL,获取 sitekey 值

    logger.info("Sitekey: " + sitekey)
    return sitekey

使用了 BeautifulSoup 4 筛选 HTML,筛选方式使用 CSS Selector,也可以使用 Selenium 自带的方法替代

注意:不要关闭 selenium 的图片加载,否则可能导致 hcaptcha 无法加载

提交 sitekey 并获取 token

这一步 2captcha 提供了示例代码(可查看参考链接的 GitHub),稍加改动即可使用

def solv_captcha(sitekey):  # solve captcha
    solver = TwoCaptcha(API_KEY) # 填入 2captcha API Key
    try:
        result = solver.hcaptcha(
            sitekey=sitekey,
            url=URL, # 填入待验证的网页 URL
        )
    except Exception as e:
        logger.warning("Solve captcha failed!")
        sys.exit(e)
    else:
        return result['code'] # 只返回结果中的 token

注意:2captcha 的返回结果是一个字典,其中包含了会话 ID 和 token,上述代码只返回了 token

提交 token

将 token 填入 h-captcha-response 和 g-recaptcha-response 两个隐藏元素内,然后提交表单

这一步可以通过在当前页面执行 Javascript 代码来实现,官方提供了可用的代码,如下:

let submitToken = (token) => {
        document.querySelector('[name=g-recaptcha-response]').innerText = token
        document.querySelector('[name=h-captcha-response]').innerText = token
        document.querySelector('.challenge-form').submit()
}
submitToken('TOKEN_STRING')

但是上述代码无法直接交给 selenium 的 execute_script() 方法执行,代码中 submitToken 方法不会保存在当前页面中

稍加修改,将其分配给 window 对象即可:

window.submitToken = function(token) { 
    document.querySelector('[name=g-recaptcha-response]').innerText = token;
    document.querySelector('[name=h-captcha-response]').innerText = token;
    document.querySelector('.challenge-form').submit();
}
submitToken('TOKEN_STRING')

最终代码如下

SUBMIT_SCRIPT = "window.submitToken = function(token) { " \
                "document.querySelector('[name=g-recaptcha-response]').innerText = token;" \
                "document.querySelector('[name=h-captcha-response]').innerText = token;" \
                "document.querySelector('.challenge-form').submit();" \
                "}"

def main():
    logger.debug("Solving captcha...")
    result_code = solv_captcha(sitekey=get_sitekey())
    logger.debug("Done")

    #inject javascript submit function
    logger.debug("Submitting captcha code...")
    browser.execute_script(SUBMIT_SCRIPT)
    browser.execute_script("submitToken('" + result_code + "')")
    logger.debug("Done")

效果

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据