Восстановление из 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.