You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Requests POST请求返回400而非200,请求排查问题

排查Python Requests POST请求400错误的问题

让我帮你一步步揪出这个400错误的根源,先看代码里几个明显的问题:

1. Headers里的格式错误与冗余设置

  • Origin和Referer的URL多了空格:你写的"Origin" : "https: //www.bonuscard.ch"和"Referer" : "https: //www.bonuscard.ch/myos/en/login"中,https:后面的空格是多余的,应该改成https://——这种格式错误会直接被服务器判定为无效请求。
  • 手动硬编码Content-Length:你在headers里固定了"Content-Length" : "151",但Requests会自动根据你发送的payload计算并设置这个头。手动设置的话,一旦实际payload长度和这个数值不匹配,服务器就会返回400,直接删掉这个头即可。

2. Payload的键包含多余空格

你的payload里几个字段的键末尾都带了空格,比如:

"userName-border:userName-border_body:userName ": "jon@doe.com",
"password-border:password-border_body:password ": "123",
"login " : ""

服务器端的表单字段名是没有这些空格的,必须和页面上表单元素的name属性完全一致(可以通过浏览器开发者工具查看真实字段名),把这些多余空格去掉。

3. Hidden Token的处理逻辑错误

你获取了hidden元素的id作为payload的键,但这类CSRF token通常是通过name属性提交的,而且它的value属性不是空字符串——你需要获取这个元素的value值,而不是把键对应的内容设为空。比如调整token的获取逻辑:

# 先打印查看hidden元素的真实属性,确认name和value
hidden_elements = SELECTOR(tree)
for elem in hidden_elements:
    print(elem.attrib)

# 假设第一个hidden元素是需要的token,取它的name和value
token_name = hidden_elements[0].get('name')
token_value = hidden_elements[0].get('value')

再把这个键值对加入payload,而不是设为空字符串。

修改后的示例代码

import requests
import lxml.html
from lxml.cssselect import CSSSelector

SELECTOR = CSSSelector('[type=hidden]')
BASE_URL = 'https://www.bonuscard.ch/myos/en/login'
LOGIN_URL = BASE_URL + '1.IFormSubmitListener-homePanel-loginPanel-loginForm'

# 修正后的headers:去掉冗余的Content-Length,修正URL空格
headers = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en,de;q=0.9",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Content-Type": "application/x-www-form-urlencoded",
    "DNT": "1",
    "Host": "www.bonuscard.ch",
    "Origin": "https://www.bonuscard.ch",
    "Pragma": "no-cache",
    "Referer": "https://www.bonuscard.ch/myos/en/login",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
}

with requests.Session() as session:
    response = session.get(BASE_URL)
    tree = lxml.html.fromstring(response.content)
    hidden_elements = SELECTOR(tree)
    
    # 获取正确的token键值对
    token_name = hidden_elements[0].get('name')
    token_value = hidden_elements[0].get('value')
    
    payload = {
        token_name: token_value,
        "userName-border:userName-border_body:userName": "jon@doe.com",
        "password-border:password-border_body:password": "123",
        "login": ""
    }
    response = session.post(LOGIN_URL, headers=headers, data=payload)
    print(response.status_code)
    print(response.text)  # 可以查看服务器返回的具体错误信息,进一步排查

额外提示

  • 不要用json=payload发送请求,因为服务器预期的是application/x-www-form-urlencoded格式,不是JSON。
  • 如果还是有问题,可以用requests.utils.dump_response(response)打印出实际发送的请求详情,对比浏览器开发者工具Network面板里的请求,看看哪里还有差异。

内容的提问来源于stack exchange,提问作者jjk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:50:11