Python Requests表单提交遇reCAPTCHA阻碍,求获取g-recaptcha-response方法
首先得指出,你当前代码里有个核心错误——你把页面上的data-sitekey值当成了g-recaptcha-response传给Google的验证接口,这完全搞混了两个东西:data-sitekey是网站用来标记reCAPTCHA实例的公开密钥,而g-recaptcha-response是用户完成验证码挑战后生成的一次性有效令牌,这俩根本不是一回事。
接下来一步步给你讲清楚怎么处理:
先搞懂reCAPTCHA的基本逻辑
你遇到的是reCAPTCHA v2(就是那个带"I'm not a robot"复选框的),它的工作流程是:
- 用户在真实浏览器里完成验证码挑战(点复选框,可能还要选对应图片)
- 浏览器调用Google的API生成一个
g-recaptcha-response令牌 - 表单提交时,这个令牌会和其他表单数据一起发给目标网站
- 目标网站再把这个令牌+自己的服务器端secret密钥发给Google的
siteverify接口,验证令牌是否有效
关键点在于:这个令牌必须由真实用户在浏览器环境下完成挑战后生成,纯Requests这种无浏览器的HTTP请求工具,根本没法直接生成或获取它——reCAPTCHA会检测请求环境,连无头浏览器都可能被识别,更别说直接发请求了。
可行的两种解决方案
方案一:用浏览器自动化工具模拟真实操作(推荐)
你可以用Selenium或者Playwright这类工具打开真实浏览器,要么让用户手动完成验证码,要么结合后续的识别服务。这里给你个Selenium的简单示例:
from selenium import webdriver from selenium.webdriver.common.by import By import requests # 初始化Chrome浏览器(需要提前下载对应版本的chromedriver) driver = webdriver.Chrome() # 打开目标页面 driver.get("你的商品页面URL") # 提示用户完成验证码 input("请完成页面上的reCAPTCHA验证,完成后按回车继续...") # 获取生成的g-recaptcha-response令牌 captcha_response = driver.find_element(By.ID, "g-recaptcha-response").get_attribute("value") # 用Requests保持会话提交表单 session = requests.Session() # 先获取页面的会话信息(Cookie等) session.get("你的商品页面URL") # 构造表单数据 payload = { # 这里填你的其他表单字段,比如商品ID、数量等 "g-recaptcha-response": captcha_response } # 提交表单 submit_response = session.post("表单提交的URL", data=payload) # 检查提交结果 if submit_response.status_code == 200: print("表单提交成功!") else: print(f"提交失败,状态码:{submit_response.status_code}") # 关闭浏览器 driver.quit()
方案二:用第三方验证码识别服务(自动化场景)
如果需要完全自动化处理,你可以用2Captcha、Anti-Captcha这类服务,它们会通过人工或AI识别验证码,返回有效的g-recaptcha-response令牌。不过要注意:
- 这类服务需要付费
- 务必确认目标网站的服务条款允许这种操作,避免被封禁账号或IP
给你个2Captcha的示例代码:
import requests import time # 替换成你的2Captcha API密钥 CAPTCHA_API_KEY = "你的2Captcha密钥" # 从页面获取的data-sitekey值 SITE_KEY = "你之前拿到的sitekey" # 目标页面的完整URL PAGE_URL = "商品页面的完整URL" # 第一步:向2Captcha提交验证码识别任务 task_response = requests.post( "http://2captcha.com/in.php", data={ "key": CAPTCHA_API_KEY, "method": "userrecaptcha", "googlekey": SITE_KEY, "pageurl": PAGE_URL } ) # 提取任务ID task_id = task_response.text.split("|")[1] # 第二步:轮询获取识别结果 captcha_response = None while True: result_response = requests.get( f"http://2captcha.com/res.php?key={CAPTCHA_API_KEY}&action=get&id={task_id}" ) result_text = result_response.text if result_text.startswith("OK|"): captcha_response = result_text.split("|")[1] break # 还没识别完成,等待5秒再查 time.sleep(5) # 第三步:用获取到的令牌提交表单 session = requests.Session() session.get(PAGE_URL) payload = { # 你的其他表单字段 "g-recaptcha-response": captcha_response } submit_response = session.post("表单提交URL", data=payload) print(f"提交状态码:{submit_response.status_code}")
修正你现有代码的核心错误
你现在的代码里,把data-sitekey传给了siteverify接口的response参数,这是完全错误的。正确的siteverify调用应该是在你拿到有效g-recaptcha-response之后,示例如下:
# 假设已经拿到了正确的captcha_response verify_result = requests.post( "https://www.google.com/recaptcha/api/siteverify", data={ "secret": "你的服务器端secret密钥(注意不是前端的sitekey)", "response": captcha_response, "remoteip": ip } ).json() if verify_result["success"]: print("验证码验证通过") else: print(f"验证失败,错误码:{verify_result['error-codes']}")
最后提醒一句:reCAPTCHA的设计初衷就是阻止自动化脚本,所以任何绕过手段都可能被检测到,使用时一定要遵守目标网站的规则,别搞违规操作哦。
内容的提问来源于stack exchange,提问作者lucky simon

