用 requests.post() 提交账号密码之后,很多人习惯只看一眼返回的状态码是 200 就认为登录成功了,其实这个判断非常不可靠。状态码 200 只说明服务器收到了请求并给出了响应,和登录是否成功没有任何必然关系——登录失败的页面同样会返回 200。真正可靠的验证需要结合响应体内容、Cookie 变化以及受保护页面的访问结果综合判断,本文就来详细讲讲这套验证思路。

一、为什么只看状态码不靠谱
首先要理解 HTTP 状态码的含义。200 表示服务器正常处理了请求,但登录接口通常无论账号密码对不对,都会正常处理并返回结果。比如密码错误时服务器返回一个带有错误提示的 HTML 页面,状态码同样是 200。只有极少数设计不规范的接口才会用 401 或 403 来表示登录失败。
还有一种常见情况是重定向。登录成功后服务器往往返回 302,把请求跳转到用户中心页面;登录失败则可能返回 200 并附带错误信息。这时候如果你只看状态码,结论可能正好和实际情况相反。Requests 默认会自动跟随重定向,最终拿到的 response.status_code 是最后一个请求的状态码,中间的 302 被隐藏掉了。
如果想观察原始的重定向行为,可以在请求时禁用自动跳转:
import requests
resp = requests.post(
"https://www.bbccb.com/login",
data={"username": "test", "password": "123456"},
allow_redirects=False # 禁止自动跟随重定向
)
print(resp.status_code) # 302 通常意味着登录成功即将跳转
print(resp.headers.get("Location")) # 查看跳转目标
这种做法并非万能,但可以作为辅助判断手段。更稳妥的方式还是下面要讲的响应体分析和 Cookie 检查。
二、通过响应体内容判断登录结果
大多数网站登录成功和失败返回的内容是有明显区别的。典型的情况有三种:返回 JSON 数据、返回 HTML 页面、返回一段跳转脚本。针对不同的返回形式,判断方法也不同。
如果接口返回 JSON,直接解析并检查其中的状态字段即可:
import requests
resp = requests.post(
"https://www.bbccb.com/api/login",
json={"username": "test", "password": "123456"}
)
result = resp.json()
if result.get("code") == 0:
print("登录成功,Token 为:", result.get("data", {}).get("token"))
else:
print("登录失败:", result.get("message"))
如果返回的是 HTML 页面,可以先获取文本内容,再查找登录失败特有的关键字,比如提示语中出现的具体文字:
import requests
resp = requests.post(
"https://www.bbccb.com/login",
data={"username": "test", "password": "wrong"},
)
html = resp.text
# 检查失败提示是否出现在页面中
if "密码错误" in html or "用户名不存在" in html:
print("登录失败")
elif "退出登录" in html or "我的账户" in html:
print("登录成功")
else:
print("无法判断,需人工检查页面内容")
需要注意编码问题。如果页面是 GBK 编码而 Requests 用 UTF-8 解码,中文关键字匹配就会失效。可以通过 resp.encoding = 'gbk' 手动指定编码,或者用 resp.apparent_encoding 让 chardet 自动识别。另外,判断关键字要尽量选取登录成功页面特有的内容,比如用户昵称、退出链接,避免选择在登录页也存在的词。
三、用 Session 和 Cookie 验证登录状态
更可靠的验证方式是借助 requests.Session()。Session 对象会自动保存服务器返回的 Cookie,并在后续请求中带上,这正是浏览器维持登录状态的原理。很多网站登录成功后会种下一个会话 Cookie(比如 sessionid、PHPSESSID 或 token),登录失败则不会。检查这个 Cookie 是否出现,就是一个很好的判断依据。
import requests
session = requests.Session()
session.post(
"https://www.bbccb.com/login",
data={"username": "test", "password": "123456"}
)
# 查看 Session 中已保存的 Cookie
cookies = session.cookies.get_dict()
print(cookies)
if "sessionid" in cookies:
print("检测到会话 Cookie,登录很可能成功")
else:
print("没有获取到会话 Cookie,登录可能失败")
Session 最大的价值在于可以直接拿去访问需要登录才能查看的页面,做二次确认。比如访问个人中心、订单列表,如果能看到真实数据,登录必然是成功的;如果被重定向回登录页,说明会话没有建立。这种方式比分析登录响应本身更加可靠,因为它验证的是最终结果而不是中间过程:
import requests
session = requests.Session()
login_resp = session.post(
"https://www.bbccb.com/login",
data={"username": "test", "password": "123456"}
)
# 访问只有登录用户才能查看的页面
profile = session.get("https://www.bbccb.com/user/profile")
final_url = profile.url # 最终停留的 URL
if "login" in final_url:
print("被重定向回登录页,登录失败")
elif "test" in profile.text:
print("成功读取到个人信息,登录确认成功")
else:
print("页面结构未知,建议打印 profile.text 人工确认")
四、常见陷阱和注意事项
第一个常见的坑是登录前需要先请求一次登录页面。很多网站会在登录页的表单里放置一个隐藏的随机字段(CSRF Token),提交时必须带上这个字段,否则无论密码对不对都会被拒绝。正确的做法是先用 Session 请求登录页,从返回的 HTML 中解析出隐藏字段,再一起提交。
import requests
import re
session = requests.Session()
page = session.get("https://www.bbccb.com/login")
# 从表单中提取隐藏的 csrf token
match = re.search(r'name="csrf_token" value="([^"]+)"', page.text)
csrf_token = match.group(1) if match else ""
resp = session.post(
"https://www.bbccb.com/login",
data={
"username": "test",
"password": "123456",
"csrf_token": csrf_token
},
headers={"Referer": "https://www.bbccb.com/login"}
)
print(resp.status_code)
第二个坑是请求头不完整导致被拦截。有些网站会校验 User-Agent 和 Referer,发现请求来自 Python 脚本就直接返回错误页面或空内容。建议构造一个尽量接近真实浏览器的请求头,并保持使用同一个 Session 对象发请求,让 Cookie 全程连贯。
最后一个建议是把验证逻辑封装成函数,返回布尔值并附带失败原因,这样在写爬虫或自动化脚本时可以复用,出问题时也能快速定位是账号密码错误、Token 缺失还是被风控拦截。综合来看,状态码只能做粗筛,响应体关键字负责初步判断,而访问受保护页面做最终确认,这套组合拳才是验证登录是否成功的完整方案。
Python Requests验证登录Session会话修改时间:2026-09-14 12:45:55