2015-06-12 14 views
12

Sto scrivendo una funzione per un codice Python esistente che verrà passato come oggetto a un oggetto Mechanize del browser.Ripristino da HTTPError in Mechanize

Compilare alcuni dettagli in un modulo nel browser e utilizzare response = browser.submit() per spostare il browser in una nuova pagina e raccogliere alcune informazioni da esso.

Purtroppo, di tanto in tanto il seguente errore:

httperror_seek_wrapper: HTTP Error 500: Internal Server Error

 

ho navigato alla pagina nel mio browser e abbastanza sicuro, ho avuto occasione di vedere direttamente questo errore, quindi penso che questo sia un problema del server, non ha nulla a che fare con robots.txt, intestazioni o simili.

Il problema è che dopo aver inviato, lo stato dell'oggetto browser cambia e non posso continuare a utilizzarlo. Il mio primo pensiero è stato quello di provare prima a prendere una copia profonda e usarla se ho avuto dei problemi, ma questo mi dà l'errore TypeError: object.__new__(cStringIO.StringO) is not safe, use cStringIO.StringO.__new__() come descritto here.

Ho anche provato a utilizzare browser.back() ma ottenere errori NoneType.

Qualcuno ha una buona soluzione a questo?

 

Solution (con grazie a karnesJ.R sottostante):

Una grande soluzione qui di seguito utilizza l'eccellente requests biblioteca (docc here). requests ha la funzionalità per compilare un modulo e inviare tramite post o get, che non modifica lo stato dell'oggetto br.

Un excellent website ci permette di testare vari codici di errore, e ha una interfaccia di modulo in alto che ho provato su questo. Creo un oggetto br in questo sito, quindi definisco una funzione che seleziona il modulo da br, estrae le informazioni pertinenti, ma invia l'articolo tramite requests - in modo che l'oggetto br non sia stato modificato ed è riutilizzabile. I codici di errore causano requests per restituire spazzatura, ma non rendono inutilizzabile lo br.

Come indicato di seguito, ciò comporta un po 'più di tempo di configurazione, ma ne 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! 
+2

Puoi aggiornarci con il codice che hai utilizzato fino ad ora? –

+0

Si potrebbe provare a usare selenuim. – ssundarraj

+0

Puoi mostrare il tuo codice o fornire l'URL del sito a cui stai tentando di accedere? – 0605002

risposta

4

È da un po 'che non scrivo per Python, ma penso di avere una soluzione alternativa al problema.Provare questo metodo:

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 

È possibile trovare la documentazione circa la requests libreria here. Personalmente ritengo che requests sia migliore per il tuo caso rispetto a mechanize ... ma richiede un po 'più di overhead da parte tua, in quanto devi abbattere l'invio a POST raw usando una specie di intercettore RESTful nel tuo browser.

In definitiva, tuttavia, passando a br ci si limita al modo in cui mechanize gestisce gli stati del browser su br.submit().

+0

Funziona - Ho modificato la mia domanda sopra per incorporare la tua visione. 'requests' è sicuramente un'interfaccia molto più carina di' mechanize'. Bounty ben guadagnato! – StackG

1

Suppongo che si desideri che l'invio avvenga anche se sono necessari più tentativi.

La soluzione che ho pensato non è certamente efficiente, ma dovrebbe funzionare.

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

Fondamentalmente, si chiamerà la funzione fino a quando viene eseguita l'azione senza HTTPError s.

+0

Il problema è che il browser viene passato come parametro - Devo ripetere il passaggio 'browser.submit()' all'interno del blocco 'except', ma a quel punto il browser ha già cambiato stato e richiamando il 'browser.submit()' provoca errori 'NoneType' - se si mette' browser' in 'do_something_in_mechanize()' non funzionerà dopo un 'HTTPError' – StackG

+0

la funzione do_something_in_mechanize() dovrebbe contenere l'intero codice dall'istanza del browser alla fine. Se ciò è fattibile, questa soluzione funzionerebbe. – ssundarraj

+0

Sfortunatamente questo è esattamente il problema - il 'browser' viene passato al mio codice come parametro, di cui non ho il controllo. – StackG