【问题标题】:Recovering from HTTPError in Mechanize从 Mechanize 中的 HTTPError 中恢复
【发布时间】:2015-08-28 07:20:12
【问题描述】:

我正在为一些现有的 python 代码编写一个函数,该函数将传递一个 Mechanize 浏览器对象作为参数。

我在浏览器的一个表单中填写了一些细节,并使用response = browser.submit()将浏览器移动到一个新页面,并从中收集一些信息。

很遗憾,我偶尔会收到以下错误:

httperror_seek_wrapper: HTTP Error 500: Internal Server Error

 

我已经在自己的浏览器中导航到该页面,果然,我偶尔会直接看到这个错误,所以我认为这是一个服务器问题,与robots.txt、标题或类似内容无关。

问题是提交后browser对象的状态发生变化,无法继续使用。我的第一个想法是先尝试获取深层副本,并在遇到问题时使用它,但这会产生错误 TypeError: object.__new__(cStringIO.StringO) is not safe, use cStringIO.StringO.__new__(),如 here 所述。

我也尝试过使用browser.back(),但得到NoneType 错误。

有人有好的解决办法吗?

 

解决方案(感谢下面的 karnesJ.R):

下面的一个很好的解决方案使用了优秀的requests 库(文档here)。 requests 具有填写表单并通过postget 提交的功能,重要的是不会更改br 对象的状态。

excellent website 允许我们测试各种错误代码,并在顶部有一个我已经测试过的表单界面。我在这个站点上创建了一个br 对象,然后定义了一个从br 中选择表单的函数,提取相关信息,但通过requests 提交 - 这样br 对象没有改变并且可以重复使用。错误代码会导致 requests 返回垃圾,但不会使 br 无法使用。

如下所述,这需要更多的设置时间,但非常值得。

import mechanize
import requests

def testErrorCodes(br,theCodes):
    for x in theCodes:
        
        br.select_form(nr=0)
        
        theAction = br.action
        payload = {'code': x}

        response = requests.post(theAction, data=payload)
        print response.status_code

br=mechanize.Browser()
br.set_handle_robots(False)
response = br.open("http://savanttools.com/test-http-status-codes")

testErrorCodes(br,[401,402,403,404,500,503,504]) # Prints the error codes 

testErrorCodes(br,[404]) # The browser is still alive and well to be used again!

【问题讨论】:

  • 你能用你目前使用的代码更新我们吗?
  • 你可以尝试使用 selenuim。
  • 您能否显示您的代码或提供您尝试访问的站点 URL?
  • 上面添加了一些卡通代码

标签: python mechanize http-error


【解决方案1】:

自从我为 python 编写代码以来已经有一段时间了,但我想我有一个解决你问题的方法。试试这个方法:

import requests
except Mechanize.HTTPError:
    while true: ## DANGER ##
        ## You will need to format and/or decode the POST for your form
        response = requests.post('http://yourwebsite.com/formlink', data=None, json=None)
        ## If the server will accept JSON formatting, this becomes trivial
        if response.status_code == accepted_code: break

您可以找到有关 requestshere 的文档。我个人认为requestsmechanize 更适合您的情况...但它确实需要您付出更多的开销,因为您需要在浏览器中使用某种RESTful 拦截器将提交分解为原始POST .

但最终,通过传入br,您将自己限制为机械化处理br.submit() 上的浏览​​器状态的方式。

【讨论】:

  • 这行得通 - 我在上面编辑了我的问题以纳入您的见解。 requests 肯定是比mechanize 更好的界面。赏金好赚!
【解决方案2】:

我假设您希望提交发生,即使它需要多次尝试。

我想到的解决方案肯定效率不高,但应该可以。

def do_something_in_mechanize():
    <...insert your code here...>
    try:
        browser.submit()
        <...rest of your code...>
    except mechanize.HTTPError:
        do_something_in_mechanize()

基本上,它会调用该函数,直到在没有HTTPErrors 的情况下执行该操作。

【讨论】:

  • 问题是浏览器是作为参数传入的——我需要在except 块中重复browser.submit() 步骤,但是到那个阶段浏览器已经改变了状态并重新调用 browser.submit() 会导致 NoneType 错误 - 如果您将 browser 放入 do_something_in_mechanize() 中,则在 HTTPError 之后它将无法工作
  • do_something_in_mechanize() 函数应该包含从浏览器实例化到结束的整个代码。如果这是可行的,那么这个解决方案会奏效。
  • 不幸的是,这正是问题所在 - browser 作为参数传递给我的代码,我无法控制。
猜你喜欢
  • 2011-04-15
  • 2021-01-04
  • 2012-05-26
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 2010-11-17
相关资源
最近更新 更多