Curl有效但Python请求无效

27 投票
5 回答
32882 浏览
提问于 2025-04-18 14:51

我正在尝试从 http://erdos.sdslabs.co/users/shagun.json 获取一个JSON格式的响应。用浏览器或者Python的 Requests 库去请求时出现了认证错误,但用curl命令却能正常工作。

curl http://erdos.sdslabs.co/users/shagun.json 

这会返回JSON响应。

为什么curl请求可以成功,而普通的浏览器请求或者使用Requests库的请求却失败呢?

5 个回答

0

为了以后参考,遇到同样的问题,但这是因为 netrc 文件的原因。Python 的 requests 库会在找到匹配的 netrc 条目时,覆盖掉 Authorization 这个头信息。

你可以查看这个链接了解更多信息:https://requests.readthedocs.io/en/latest/user/authentication/#netrc-authentication

3

我之前遇到过这样的情况:有段用Python写的请求代码,之前一直能正常工作,结果有一天突然不行了,而用curl却没问题。代码没有问题,服务器也没问题。看了这个讨论后,我意识到可能是连接的某些东西发生了变化。我把Wifi关掉再打开,结果它又能用了。

我没有进一步调查,可能是请求缓存了一些不再有效的东西。抱歉我这个说法不够专业,但希望能对某些人有所帮助。

4

如果你的环境中配置了代理,那么在你的会话或请求中也要定义这个代理。

比如在会话中:

    my_proxies = {  
        'http': 'http://myproxy:8080',  
        'https': 'https://myproxy:8080'  
    }

    session = requests.Session()  
    request = requests.Request('POST', 'http://my.domain.com', data=params_template, headers=req_headers, proxies=my_proxies)  
    prepped = session.prepare_request(request)  
    response = session.send(prepped)  

查看文档:
请求的文档 http://docs.python-requests.org/en/master/user/quickstart/
会话的文档 http://docs.python-requests.org/en/master/user/advanced/

8

对于像我这样的后知后觉者:

在我的情况下,问题出在我用 requests.get(url, data={...}) 这种方式提供了网址参数。后来我把它改成了 requests.get(url, params={...}),问题就解决了。

18

使用telnet来检查:

$ telnet erdos.sdslabs.co 80
Trying 62.141.37.215...
Connected to erdos.sdslabs.co.
Escape character is '^]'.
GET http://erdos.sdslabs.co/users/shagun.json HTTP/1.0

HTTP/1.1 302 Found
Date: Sat, 26 Jul 2014 11:18:58 GMT
Server: Apache
Set-Cookie: PHPSESSID=juvg7vrg3vs4t00om3a95m4sc7; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Location: /login
Access-Control-Allow-Origin: http://erdos.sdslabs.co
X-Powered-By: PleskLin
Content-Length: 1449
Connection: close
Content-Type: application/json

{"email":"sshagun.sodhani@gmail.com","username":"shagun","name":"Shagun      
[...]

我们看到,网页服务器返回了302状态码,这意味着它正在重定向到 /login 页面。请求和网页浏览器会遵循这个指令,最终到达登录界面。不过,我们也发现网页服务器同时还返回了你想要的json数据,而curl(和telnet)很简单,就能直接接受这些数据。

最佳做法是修复网页服务器,让它要么不需要你登录,要么在要求用户登录时不同时提供受密码保护的数据。

如果你无法更改网页服务器,你可以告诉requests模块忽略重定向:

import requests
result = requests.get('http://erdos.sdslabs.co/users/shagun.json', allow_redirects=False)
print result.content

撰写回答