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

Python脚本执行GET请求返回401,但命令行运行正常的问题求助

解决脚本运行时GET请求返回401但命令行正常的问题

看起来你遇到了一个挺让人困惑的会话保持问题——命令行直接跑代码时POST和GET都能正常返回200,但把代码作为脚本运行时,GET请求就莫名返回401了。我来帮你分析几个常见的原因和对应的解决办法:

1. 请求头差异导致服务器拒绝会话

很多网站会校验请求的User-Agent等请求头,命令行环境下requests的默认User-Agent和脚本在其他环境(比如定时任务、服务进程)运行时的可能存在差异,服务器会因此判定会话无效。

解决办法:手动设置模拟浏览器的请求头,让脚本的请求和浏览器/命令行环境保持一致:

import requests

url = 'https://website.com'
credentials = {'user': 'my_name', 'password' : 'my_password'}

# 模拟浏览器的请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'
}

with requests.Session() as sesh:
    # 给会话设置统一的请求头
    sesh.headers.update(headers)
    
    init = sesh.post(url+'/login', data=credentials)
    print(init.status_code)
    
    # 可以打印会话的Cookie,对比命令行和脚本运行时的差异
    print("Session cookies:", sesh.cookies)
    
    xml = sesh.get(url+'/different/path')
    if xml.status_code == 200:
        print(xml.content)
    else:
        print(xml.status_code)

2. 忽略了CSRF令牌验证

不少网站的登录接口需要CSRF令牌才能完成有效登录,你当前的代码直接POST用户名密码,命令行运行时可能刚好会话中保留了之前的CSRF令牌(比如你之前手动访问过登录页),但脚本运行时是全新会话,没有获取CSRF就直接登录,虽然返回200,但其实并没有真正建立有效会话。

解决办法:先请求登录页面获取CSRF令牌,再携带令牌进行登录:

import requests
import re

url = 'https://website.com'
credentials = {'user': 'my_name', 'password' : 'my_password'}

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

with requests.Session() as sesh:
    sesh.headers.update(headers)
    
    # 先获取登录页面,提取CSRF令牌
    login_page = sesh.get(url+'/login')
    # 这里根据实际页面的CSRF字段名调整正则,比如name="csrfmiddlewaretoken"
    csrf_match = re.search(r'name="csrf_token" value="(.*?)"', login_page.text)
    if csrf_match:
        credentials['csrf_token'] = csrf_match.group(1)
    else:
        print("Failed to get CSRF token")
    
    init = sesh.post(url+'/login', data=credentials)
    print(init.status_code)
    
    xml = sesh.get(url+'/different/path')
    if xml.status_code == 200:
        print(xml.content)
    else:
        print(xml.status_code)

3. 环境差异导致会话状态异常

脚本运行的环境(比如不同用户身份、虚拟环境、网络代理)可能和命令行环境不一致,比如:

  • 脚本运行用户没有访问目标网站的网络权限
  • 虚拟环境中requests版本和命令行不同,导致会话处理逻辑有差异
  • 脚本环境存在代理,而命令行没有,代理拦截了会话Cookie

排查思路:

  • 对比脚本和命令行运行时的环境变量、Python版本、requests版本
  • 在脚本中打印请求的完整信息(比如print(xml.request.headers)),和命令行运行时的请求头对比,找出差异点

4. 登录后跳转未正确处理

有些网站登录后会自动跳转,虽然requests的Session默认开启了allow_redirects=True,但少数情况下跳转过程中可能丢失Cookie,或者需要额外处理跳转后的响应。

解决办法:可以手动处理跳转,或者检查登录响应的跳转目标,确保会话Cookie被正确保存:

init = sesh.post(url+'/login', data=credentials, allow_redirects=False)
print("Login redirect status:", init.status_code)
# 如果有跳转,手动跟进
if init.status_code in [301, 302]:
    sesh.get(init.headers['Location'])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:27:23