我需要以编程方式从网站上抓取数据并使用mechanize
(v0.2.5)来执行此操作。由于我无法控制的原因,HTTP身份验证的确切密码经常更改,但是以可预测的方式。
所以我尝试循环遍历每个要尝试的密码,并忽略身份验证错误,直到找到一个有效的密码:
br = mechanize.Browser()
br.set_handle_robots(False)
for pwd in various_permutations_of_password():
try:
print "Trying password: %s" % pwd
br.add_password(site, username, pwd)
response = br.open(url)
break
except Exception as e:
pass
else:
raise e
令人惊讶的是,即使添加了正确的密码,这也不起作用。据我所知,问题是Browser
对象保留并尝试使用以前的错误密码,而不是使用最新添加的密码。
我提出的最佳解决方法是在每次迭代时创建一个新的Browser
实例:
for pwd in various_permutations_of_password():
try:
br = mechanize.Browser()
br.set_handle_robots(False)
print "Trying password: %s" % pwd
br.add_password(site, username, pwd)
response = br.open(url)
break
except Exception as e:
pass
else:
raise e
有更好的方法吗?有没有办法让Browser
对象“忘记”特定网站的凭据而不会丢失其中的其他有状态浏览信息?
我还查看了库代码,并且不明白为什么当我添加一个具有相同add_password
的新密码时,url
的底层实现不会覆盖以前的密码:< / p>
class UserAgentBase:
...
def add_password(self, url, user, password, realm=None):
self._password_manager.add_password(realm, url, user, password)
class HTTPPasswordMgr:
...
def add_password(self, realm, uri, user, passwd):
# uri could be a single URI or a sequence
if isinstance(uri, basestring):
uri = [uri]
if not realm in self.passwd:
self.passwd[realm] = {}
for default_port in True, False:
reduced_uri = tuple(
[self.reduce_uri(u, default_port) for u in uri])
self.passwd[realm][reduced_uri] = (user, passwd)