覆盖urllib2.HTTPError或urllib.error.HTTPError并仍然读取响应HTML

72

我收到一个“HTTP错误500:内部服务器错误”的响应,但我仍想读取错误HTML中的数据。

使用Python 2.6,我通常使用以下方式获取页面:

import urllib2
url = "http://google.com"
data = urllib2.urlopen(url)
data = data.read()

尝试在无法访问的URL上使用该方法时,会抛出urllib2.HTTPError异常:

urllib2.HTTPError: HTTP Error 500: Internal Server Error

如何获取返回内部服务器错误的错误页面(使用或不使用 urllib2)?

请注意,对于Python 3,相应的异常为urllib.error.HTTPError

3个回答

136
< p > HTTPError 是一个类似文件的对象。您可以捕获并read其内容。
HTTPError是一个类似文件的对象。您可以捕获它,然后读取其内容。
try:
    resp = urllib2.urlopen(url)
    contents = resp.read()
except urllib2.HTTPError, error:
    contents = error.read()

2
一旦我们执行了error.read(),随后的error.read()将返回空字符串。有时这会影响其他代码的运行。我们如何礼貌地将错误内容放回给其他人? - Colonel Panic
1
@Matt 我从未尝试过这个,但由于它是一个类似文件的对象,你可能可以执行error.seek(0)将“文件指针”重置到流的开头。并非每个类似文件的对象都需要实现I/O接口的随机访问部分,因此不确定是否有效。如果无效,您可以考虑单独提出这个问题,以便吸引更多的观众。 - Joe Holloway
1
请注意,在退化情况下,HTTPError 可能无法像文件一样的对象那样工作。请通过 hasattr 验证 read() 方法是否可用。 - ron
2
由于底层流是http响应,因此它是不可寻址的,这意味着您无法在其上调用seek() - remcoder

9
如果您的意思是想要阅读500的正文内容:
request = urllib2.Request(url, data, headers)
try:
        resp = urllib2.urlopen(request)
        print resp.read()
except urllib2.HTTPError, error:
        print "ERROR: ", error.read()

在您的情况下,您不需要构建请求。只需执行以下操作:
try:
        resp = urllib2.urlopen(url)
        print resp.read()
except urllib2.HTTPError, error:
        print "ERROR: ", error.read()

因此,您不需要覆盖urllib2.HTTPError,只需处理异常即可。


1
不,我想读取服务器发送给用户浏览器的HTML内容,如果他们意外地访问了其中一个500内部错误页面。就像,如果urllib在任何404页面上出错(我不确定它是否会出错,我还没有尝试过),我想读取404页面提供的HTML内容(例如,如果网站使用自定义的404页面)。 - backus

-1
alist=['http://someurl.com']

def testUrl():
    errList=[]
    for URL in alist:
        try:
            urllib2.urlopen(URL)
        except urllib2.URLError, err:
            (err.reason != 200)
            errList.append(URL+" "+str(err.reason))
            return URL+" "+str(err.reason)
    return "".join(errList)

testUrl()

1
你应该在你的回答中添加描述性文本。 - Hussein Khalil
err.reason 实际上并没有提供与 err.read() 相同的信息。后者可能更具体有用。 - Asclepius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接