我是Python的新手,如果我遗漏了一些明显的东西,请原谅我。
我正在使用urllib.FancyURLopener来检索网络文档。在Web服务器上禁用身份验证时,它可以正常工作,但在启用身份验证时会失败。
我的猜测是我需要子类化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()”,它也会失败。
我已经验证我的my_opener()类是通过使用简单的“print'Got 401 error'”覆盖http_error_401()方法来工作的。我也试图覆盖prompt_user_passwd()方法,但这也不会发生。
我认为无法主动指定用户名和密码。
那么如何让urllib重试请求?
感谢。
答案 0 :(得分:0)
我刚刚在我的网络服务器(nginx)上尝试了你的代码,它按预期工作:
HTTP / 1.1 401未经授权从带有标题的服务器
Connection: close
WWW-Authenticate: Basic realm="Restricted"
客户端再次尝试使用授权标头
Authorization: Basic <Base64encoded credentials>
服务器响应200 OK +内容
所以我猜你的代码是正确的(我用python 2.7.1尝试过),也许你试图访问的网络服务器没有按预期工作。这是使用免费的http basic auth testsite 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!"