Python使用FancyURLopener时,遇到401和“Connection: close”的问题
我刚开始学Python,所以如果我漏掉了什么明显的东西,请多包涵。
我正在使用urllib.FancyURLopener来获取一个网页文档。当网页服务器没有开启身份验证时,这个方法很好用,但一旦开启身份验证就不行了。
我猜我需要创建一个新的类来继承urllib.FancyURLopener,并重写get_user_passwd()和/或prompt_user_passwd()这两个方法。所以我这样做了:
class my_opener (urllib.FancyURLopener):
# Redefine
def get_user_passwd(self, host, realm, clear_cache=0):
print "get_user_passwd() called; host %s, realm %s" % (host, realm)
return ('name', 'password')
然后我尝试打开这个页面:
try:
opener = my_opener()
f = opener.open ('http://1.2.3.4/whatever.html')
content = f.read()
print "Got it: ", content
except IOError:
print "Failed!"
我希望FancyURLopener能处理401错误,调用我的get_user_passwd()方法,然后重试请求。
但它没有这样做;当我调用“f = opener.open()”时,我得到了IOError异常。
Wireshark告诉我请求已经发送,服务器返回了“401 Unauthorized”的响应,并且有两个我需要关注的头信息:
WWW-Authenticate: BASIC
Connection: close
连接随后被关闭,我捕获了这个异常,一切都结束了。
即使在IOError之后我重试“f = opener.open()”,也还是失败。
我已经通过重写http_error_401()方法并简单地打印“Got 401 error”来验证我的my_opener()类是有效的。我也尝试重写prompt_user_passwd()方法,但也没有发生。
我看不到任何主动指定用户名和密码的方法。
那么,我该如何让urllib重试这个请求呢?
谢谢。
1 个回答
我刚在我的网络服务器(nginx)上试了你的代码,结果一切正常:
- 从urllib客户端获取数据
服务器返回了HTTP/1.1 401 未授权的状态,并附带了一些头信息
Connection: close WWW-Authenticate: Basic realm="Restricted"
客户端再次尝试,并添加了授权头信息
Authorization: Basic <Base64encoded credentials>
服务器回应了200 OK,并返回了内容
所以我猜你的代码是对的(我用的是python 2.7.1),可能你尝试访问的网络服务器没有正常工作。这里是我在免费的http基本认证测试网站browserspy.dk上测试的代码(看起来他们使用的是apache - 代码运行正常):
import urllib
class my_opener (urllib.FancyURLopener):
# Redefine
def get_user_passwd(self, host, realm, clear_cache=0):
print "get_user_passwd() called; host %s, realm %s" % (host, realm)
return ('test', 'test')
try:
opener = my_opener()
f = opener.open ('http://browserspy.dk/password-ok.php')
content = f.read()
print "Got it: ", content
except IOError:
print "Failed!"