PAYATHON 2026

requests.Session() 提交 CAPTCHA 后仍停留在验证页,如何排查?

数据小陈

结论

先移除把 POST 表单改成 GET 的备用重试。记录显示,页面表单声明 method=POST,这次 POST 收到 ddos-guard 返回的 403,之后的 GET 仍返回 CAPTCHA 页面。由此只能判断提交未成功,无法确定原因是验证码答案未通过、表单字段不匹配、会话状态变化,还是站点防护层拒绝了请求。

requests.Session() 会在请求之间维护 Cookie,但这不能证明表单提交成功或服务端接受了当前会话。响应中出现 Set-Cookie 时,应检查它是否更新或删除了 Cookie,并确认后续请求实际发送的值。

先检查表单提交方式和字段

问题中的表单声明为 POST,提交时应按表单指定的方法发送数据。把同一份表单数据放进 GET 查询参数,会生成不同的请求,不能重试原来的 POST,也不等同于表单提交。GET 通常用于读取资源,不能代替表单声明的 POST。

检查提交数据是否来自这次 GET 返回的表单,包括 action、_xsrf 和其他隐藏字段。不要假设可以复用旧页面或之前请求中的字段值。对于 isBot,应确认提交值是否与页面表单及站点预期一致。现有记录无法确定它应使用哪种值或编码形式。

可先在本地记录以下信息,并对 Cookie、令牌和验证码值做脱敏:

  • 获取表单后,session.cookies 中相关 Cookie 的名称和值是否按预期更新。
  • POST 的 PreparedRequest 是否携带了当前 Session 的 Cookie,以及是否意外覆盖了 Session 默认值。
  • POST 响应的 Set-Cookie 是否改变了后续请求使用的 Cookie。
  • 提交的表单字段、编码和 Content-Type 是否与页面中的表单一致。
  • action 是否完整保留页面提供的查询参数。不要把日志中的脱敏片段当作可直接复用的 URL。

同一 Session 的请求若经过不同代理、出口 IP 或 Cookie jar,服务端看到的状态可能不一致。现有材料没有说明这些条件,只能将它们列为待核对项,不能据此断定发生了会话错配。

如何看待 403 和请求头

POST 响应的 Server 为 ddos-guard,响应体包含 hhcaptcha 和 isBot 字段。这些信息表明请求收到了该防护链路的拒绝响应,但无法单独确定拒绝原因,也不能证明手动输入的答案正确或错误。

请求使用了 Android 应用风格的 User-Agent,同时由 requests 发出。请求头与真实客户端请求之间的差异可以作为排查线索。逐项复制浏览器或应用的请求头并不能保证请求会被接受,也不能代替站点支持的验证流程。若站点要求在其支持的浏览器或客户端中完成人工验证,应在该客户端中完成,停止用 GET 或构造其他请求来绕过拒绝结果。

建议的处理顺序

  1. 删除 POST 失败后将相同数据改为 GET 的逻辑。
  2. 重新获取当前 CAPTCHA 页面,从该响应解析表单的 method、完整 action 和当前字段值。
  3. 按表单指定的方法提交,并核对请求是否包含刚获取的字段和 Session Cookie。
  4. 将 403 响应体和 Set-Cookie 与提交前的状态一起记录,脱敏后检查服务端是否更新了会话状态。
  5. 如果仍收到 ddos-guard 的拒绝响应,停止自动重试,改用站点支持的人工验证方式或联系站点支持。

备注:内容仅供参考。