Python urllib2.urlopen:即使存在HTTP头错误,也要读取site-body

时间:2014-12-03 11:39:31

标签: python urllib2

我有这个简单的URL,我想从我的python脚本调用: http://test.my-site.com/bla-blah/createAccount (由于隐私,我更改了一些字母,所有特殊字符等完全相同)

import urllib2

def myfunc(self, url):  
    result = urllib2.urlopen(url).read()
    # HTTP Error 400: Bad Request

当我调用上述网址时,收到错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
    return _opener.open(url, data, timeout)
  File "/usr/lib/python2.7/urllib2.py", line 406, in open
    response = meth(req, response)
  File "/usr/lib/python2.7/urllib2.py", line 519, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python2.7/urllib2.py", line 444, in error
    return self._call_chain(*args)
  File "/usr/lib/python2.7/urllib2.py", line 378, in _call_chain
    result = func(*args)
  File "/usr/lib/python2.7/urllib2.py", line 527, in http_error_default
    raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 400: Bad Request

我不认为它与引号(和/或空白显然)有关。 当我调用URL http://test.my-site.com/bla-blah/listAccounts时,它工作正常,结果是我在浏览器中调用URL时得到的完全相同的文本。当然我通过浏览器检查了第一个URL,它运行正常。

知道这可能是什么吗?


修改以澄清:

这两个URL应该是可调用的,没有任何其他参数或查询字符串,就像他们站在上面一样。然后该网站应显示类似&#34;错误:参数缺失&#34;。当我在浏览器中调用URL或通过bash中的curl调用时,会发生这种情况。只是python模块正在制造问题。


Edit2 (也更改为发布标题以更好地匹配情况)

谢谢,你是对的:如果我做curl -v 'http://test.my-site.com/bla-blah/createAccount',我会得到以下内容:

* About to connect() to <blackened> port 80 (#0)
*   Trying 193.46.215.110... connected
> GET <blackened> HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: <blackened>
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< content-language: en-US
< server: <blackened>
< date: Thu, 04 Dec 2014 07:20:15 GMT
< set-cookie: beng_proxy_session=e2e037e7e79c1b03; HttpOnly; Path=/; Version=1; Discard
< p3p: CP="CAO PSA OUR"
< content-length: 234
< 
error: parameter x missing
error: parameter y missing
* Connection #0 to host <blackened> left intact
* Closing connection #0

如您所见,存在HTTP标头错误。但curl(和浏览器)继续打印site-body(&#34;参数缺失...&#34;),但python urllib在看到标题错误后停止并且不打印正文。 (我猜是头错误btw是由服务器应用程序发送的。所以这与python urllib无关) 所以我们距离更近了一步,但即使出现错误,我仍然需要看到身体,因为我必须知道(并显示)到底出了什么问题。 但刚才我找到了解决方案:

try:
    response = urllib2.urlopen("http://test.my-site.com/bla-blah/createAccount")
    contents = response.read()
    print("success: %s" % contents)
except urllib2.HTTPError as e:
    contents = e.read()
    print("error: %s" % contents)

这样我就可以获得网站的正文,无论是错误还是成功。

(顺便说一下,这是我得到解决方案的帖子:Overriding urllib2.HTTPError or urllib.error.HTTPError and reading response HTML anyway

非常感谢!

1 个答案:

答案 0 :(得分:1)

修改2

Python在收到状态代码为400的HTTP响应时引发异常。响应正文中可能存在一些您没有看到的文本,因为存在异常并且未读取数据。该文本可能是“错误:参数缺失”。

可能curl正在做同样的事情,然而,它显示响应的主体,而不是适合,所以你看到“错误:参数缺失”。与您的浏览器类似的行为。

尝试运行curl -v http://test.my-site.com/bla-blah/createAccount。这将以详细模式运行curl,您将能够看到响应并检查是否返回状态代码400。如果它是状态码400,则urllib2.urlopen()没有任何问题,您只需要在查询字符串中发送参数。

修改1

以下是curl请求和urllib2.urlopen请求之间的区别......

[mhawke@localhost ~]$ python
GET /bla-blah/createAccount HTTP/1.1
Accept-Encoding: identity
Host: localhost:12345
Connection: close
User-Agent: Python-urllib/2.7

[mhawke@localhost ~]$ nc -l localhost 12345
GET /bla-blah/createAccount HTTP/1.1
User-Agent: curl/7.32.0
Host: localhost:12345
Accept: */*

也许您可以尝试在Python中添加/删除标头以实现curl生成的相同请求。

原始回答

网址http://test.my-site.com/bla-blah/listAccounts看起来像是HTTP GET请求,而http://test.my-site.com/bla-blah/createAccount可能需要HTTP POST请求,其中包含“创建帐户”所需的数据字段。

我不知道您的服务器应用程序需要什么数据,但(如果我的猜测是正确的)这通常是您需要考虑的事情:

import urllib2
from urllib import urlencode

data = {'username': 'droids', 'password': '123droids321', 'phone': '012351234'}
result = urllib2.urlopen(url, urlencode(data)).read()

urlencoded数据的存在会生成POST请求,而不是您当前代码将发出的GET请求。

请注意,HTTP有一个更可用的模块:requests。看看吧。