Восстановление из HTTPError в Mechanize

Я пишу функцию для некоторого существующего кода на 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__(), как описано здесь.

Я также попытался использовать browser.back(), но получить NoneType ошибки.

Есть ли у кого-нибудь хорошее решение?

 

Решение (с помощью karnesJ.R ниже):

Отличное решение ниже использует отличную библиотеку requests (docs здесь). requests имеет функциональность для заполнения формы и отправки через post или get, что существенно не изменяет состояние объекта br.

отличный веб-сайт позволяет нам проверять различные коды ошибок и иметь интерфейс формы наверху, на котором я тестировал это. Я создаю объект 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!

Ответ 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

Здесь вы можете найти документацию о requests библиотеке здесь. Я лично считаю, что requests лучше для вашего дела, чем mechanize... но для этого вам требуется немного больше накладных расходов, поскольку вам нужно разбить подачу на необработанную POST с помощью какого-то перехватчика RESTful в вашем браузере.

В конечном счете, хотя, проходя в br, вы ограничиваете себя тем, как механизация обрабатывает состояния браузера на br.submit().

Ответ 2

Я предполагаю, что вы хотите, чтобы представление было выполнено, даже если оно требует нескольких попыток.

Решение, о котором я думал, конечно, неэффективно, но оно должно работать.

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

В принципе, он вызывается функцией до тех пор, пока действие не будет выполнено без HTTPError s.