Python mechanize follow_link()和back()的问题

Python mechanize follow_link()和back()的问题,python,mechanize,Python,Mechanize,我遇到了以下链接的机械化问题。以下是我的目标: for link in mech.links(url_regex='/test/'): mech.follow_link(link) // Do some processing on that link mech.back() 根据mechanize示例,这应该可以正常工作。但事实并非如此。尽管调用了.back(),但循环结束,即使有更多链接要访问。如果我注释掉mech.follow_link(link)和mech.b

我遇到了以下链接的机械化问题。以下是我的目标:

for link in mech.links(url_regex='/test/'):
    mech.follow_link(link)

    // Do some processing on that link

    mech.back()

根据mechanize示例,这应该可以正常工作。但事实并非如此。尽管调用了.back(),但循环结束,即使有更多链接要访问。如果我注释掉mech.follow_link(link)和mech.back(),将它们替换为print link.text,它将打印出大约50个链接。但是…一旦我取消注释mech.follow_链接,循环将在第一个follow_链接后立即终止。back()正在工作,如果我打印mech.title(),然后调用mech.back()并再次打印mech.title(),它会清楚地显示第一个标题,然后是“back”页面的标题。我真的很困惑,这就是在文档中是如何做到的。我不知道发生了什么。

海盗,我同意,这不应该发生,你所做的与wwwsearch.sourceforge.net/mechanize/上的文档页面所说的差不多;我尝试了与您类似的代码,并在第一次迭代后停止时得到了相同的结果

但是,我确实找到了解决方法,即将links()中的链接URL保存到一个列表中,然后跟踪该列表中的每个URL:

from mechanize import Browser
br = Browser()
linklist = []
br.open(your_page_here)
for link in br.links(url_regex='/test/'): linklist.append(link.url)
for url in linklist:
    br.open(url)
    print br.title()
这很难看,你不应该这么做,但它似乎奏效了


对于mechanize这样的缺陷(我也遇到了一个问题),我并不是很高兴,但它安装起来非常简单,看起来非常便携,并且可以脱机运行(通过简单的cron作业),与其他测试框架(如seleniumhq.org)相比非常容易,这看起来很棒,但实际设置和使用起来似乎要复杂得多。

一个比保存链接列表更简单的解决方法是只获取第二个浏览器对象。这相当于在“真实”浏览器中打开第二个选项卡。如果还需要身份验证,则需要在浏览器实例之间共享cookie jar:

import mechanize
import cookielib

br = mechanize.Browser()
br2 = mechanize.Browser()
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
br2.set_cookiejar(cj)

br.open("http://yoursite.com/login")
br.select_form(nr=0)
br["username"] = "..."   # The hash keys are the names of the form fields
br["password"] = "..."
br.submit()    # This will save the authentication cookie to the shared cookie jar!
br.open("http://yoursite.com/page-to-parse")

for link in br.links(url_regex="/link_text"):
    req = br.click_link(url=link.url)
    html = br2.open(req).read()

请注意,有必要从第一个实例获取请求对象,然后与第二个实例一起提交。这相当于“真实”浏览器中的“在新窗口/选项卡中打开”命令。

每次页面访问都会将links()迭代器重置为该新页面上的链接。因此,您需要将其保存到一个单独的变量中,例如:
links=mech.links()
,或者正如Chirael所指出的那样,
links=list(mech.links())
,其优点是可以使用
print>>sys.stderr'.#links:%d'%len(links)
。这不是mechanize.Browser中的错误,它只是有状态对象的副作用

我在玩这个游戏时注意到的另一个问题是,如果从一开始就没有设置
mech.back()
,则不能使用
mech.request
,因为如果使用
mech.set\u response()
来设置原始页面内容,则不能使用
mech.back()。在这种情况下,您必须显式地将第一个请求设置为:
mech.request=mechanize.request('about://config)
。否则,您将得到一个
浏览器状态错误:已在历史记录的开头


为了完整起见,如果有人像我一样通过谷歌搜索来到这里,请确保在
mechanize中设置标题。至少将响应设置为
(('content-type','text/html'),
mech。查看html
将保持
False
mech.links()
将引发
浏览器状态错误(“不查看HTML”)

您是否介意解释为什么需要从第一个实例获取请求对象并与第二个实例一起提交?为什么我们不能做
br2.open(link.url)
?好吧,已经有一段时间了,我已经有一段时间没有使用mechanize了;据我回忆,真正需要的是使用两个单独的浏览器实例,因此链接的连接不会在第一个实例中重置链接列表。我不记得为什么我必须使用click_链接,也许这只是我的编码习惯,也许它设置了一些我必须在jar中共享的cookies。如果一个简单的
open
在你的情况下起作用,那就继续吧……我研究了
click\u link
方法,我认为关键在于它与
self一起使用。\添加\u referer\u头(请求)