Recuperación de HTTPError en Mechanize

Estoy escribiendo una función para un código Python existente al que se pasará un objeto de navegador de Mechanize como parámetro.

Completo algunos detalles en un formulario en el navegador, y uso response = browser.submit() para mover el navegador a una nueva página, y recostackr cierta información de él.

Desafortunadamente, ocasionalmente me sale el siguiente error:

httperror_seek_wrapper: HTTP Error 500: Internal Server Error

He navegado a la página en mi propio navegador y, efectivamente, veo este error directamente, por lo que creo que esto es un problema del servidor, no tiene nada que ver con robots.txt , encabezados o similar.

El problema es que después de enviar, el estado del objeto del browser cambia y no puedo seguir usándolo. Mi primer pensamiento fue intentar tomar una copia profunda primero y usar eso si tengo problemas, pero eso da el error TypeError: object.__new__(cStringIO.StringO) is not safe, use cStringIO.StringO.__new__() como se describe aquí .

También he intentado usar browser.back() pero obtengo errores de tipo de entrada.

¿Alguien tiene una buena solución para esto?

Solución (con agradecimiento a karnesJ.R abajo):

Una gran solución a continuación utiliza la excelente biblioteca de requests (docs aquí ). requests tienen una funcionalidad para rellenar un formulario y enviarlo por post u get , lo que es importante que no cambie el estado del objeto br .

Un excelente sitio web nos permite probar varios códigos de error y tiene una interfaz de formulario en la parte superior en la que he probado esto. Creo un objeto br en este sitio, luego defino una función que selecciona el formulario de br , extrae la información relevante, pero realiza el envío a través de requests , de modo que el objeto br no haya cambiado y sea reutilizable. Los códigos de error hacen que las requests devuelvan basura, pero no hacen que el br inutilizable.

Como se indica a continuación, esto implica un poco más de tiempo de configuración, pero vale la pena.

 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! 

Ha pasado un tiempo desde que escribí para python, pero creo que tengo una solución para su problema. Prueba este método:

 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 

Puede encontrar documentación sobre la biblioteca de requests aquí . Personalmente, creo que las requests son mejores para su caso que mechanize de mechanize … pero requieren un poco más de sobrecarga, ya que necesita desglosar el envío a POST sin procesar utilizando algún tipo de interceptor RESTful en su navegador.

En última instancia, sin embargo, al pasar a br te estás restringiendo a la manera en que mecanizar maneja los estados del navegador en br.submit() .

Supongo que desea que la presentación se realice aunque se realicen varios bashs.

La solución en la que pensé ciertamente no es eficiente, pero debería funcionar.

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

Básicamente, llamará a la función hasta que la acción se realice sin HTTPError s.