2009-02-16 9 views
43

Attualmente sto tentando di accedere a un sito utilizzando Python, tuttavia il sito sembra inviare un cookie e un'istruzione di reindirizzamento sulla stessa pagina. Python sembra seguire questo reindirizzamento impedendomi così di leggere il cookie inviato dalla pagina di accesso. Come posso evitare che urllib (o urllib2) di urlopen di Python segua il reindirizzamento?Come impedire a Python di urllib (2) di seguire un reindirizzamento

+0

Du plicate: http://stackoverflow.com/questions/110498/is-there-an-easy-way-to-request-a-url-in-python-and-not-follow-redirects/110808 –

+0

una domanda simile: http://stackoverflow.com/questions/9890815/python-get-headers-only-using-urllib2 – newtover

risposta

33

Si potrebbe fare un paio di cose:

  1. Costruisci il tuo HTTPRedirectHandler che intercetta ogni reindirizzare
  2. Creare un'istanza HTTPCookieProcessor ed installare che apri in modo da avere accesso al Cookiejar.

Questa è una cosa veloce poco che mostra sia

import urllib2 

#redirect_handler = urllib2.HTTPRedirectHandler() 

class MyHTTPRedirectHandler(urllib2.HTTPRedirectHandler): 
    def http_error_302(self, req, fp, code, msg, headers): 
     print "Cookie Manip Right Here" 
     return urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers) 

    http_error_301 = http_error_303 = http_error_307 = http_error_302 

cookieprocessor = urllib2.HTTPCookieProcessor() 

opener = urllib2.build_opener(MyHTTPRedirectHandler, cookieprocessor) 
urllib2.install_opener(opener) 

response =urllib2.urlopen("WHEREEVER") 
print response.read() 

print cookieprocessor.cookiejar 
+0

Sembra che tu non stia usando' redirect_handler = urllib2.HTTPRedirectHandler() 'nell'esempio. Volevi mostrare un secondo esempio? –

+0

Sei corretto, non sto usando redirect_handler. Invece, ho creato il mio gestore di reindirizzamento. Modificherò per rimuovere. – pope

+0

Perché non è necessario istanziare il 'MyHTTPRedirectHandler', ma piuttosto passare la classe nel metodo' build_opener() '? – Benjamin

11

urllib2.urlopen chiamate build_opener() che utilizza questo elenco di classi handler:

handlers = [ProxyHandler, UnknownHandler, HTTPHandler, 
HTTPDefaultErrorHandler, HTTPRedirectHandler, 
FTPHandler, FileHandler, HTTPErrorProcessor] 

Si potrebbe provare a chiamare urllib2.build_opener(handlers) te stesso con una lista che omette HTTPRedirectHandler, quindi chiamare il metodo open() sul risultato di aprire l'URL. Se non ti piacciono i reindirizzamenti, potresti anche chiamare urllib2.install_opener(opener) al tuo apri non reindirizzato.

Sembra che il tuo vero problema è che urllib2 non sta facendo i cookie nel modo desiderato. Vedi anche How to use Python to login to a webpage and retrieve cookies for later usage?

+6

* Puoi provare a chiamare urllib2.build_opener (handler) tu stesso con un elenco che omette HTTPRedirectHandler, quindi chiamare il metodo open() sul risultato per aprire il tuo URL. * Bene, documenti per urllib2.build_opener() dice questo * Le istanze delle seguenti classi ** saranno davanti ai gestori **, a meno che i gestori li contengano, loro istanze o sottoclassi: ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler , HTTPErrorProcessor. * Sembra che ommiting 'HTTPRedirectHandler' non funzionerà ... –

3

Questa domanda è stata aperta prima del here.

MODIFICA: Se si ha a che fare con applicazioni Web bizzarre, è consigliabile provare mechanize. È una grande libreria che simula un browser web. Puoi controllare il reindirizzamento, i cookie, l'aggiornamento della pagina ... Se il sito web non si basa [pesantemente] su JavaScript, andrai molto d'accordo con mechanize.

28

Se tutto ciò che serve è arresto reindirizzamento, poi c'è un modo semplice per farlo. Ad esempio, desidero solo ottenere i cookie e per ottenere prestazioni migliori non desidero essere reindirizzato a un'altra pagina. Inoltre spero che il codice sia mantenuto come 3xx. usiamo il 302 per esempio.

class MyHTTPErrorProcessor(urllib2.HTTPErrorProcessor): 

    def http_response(self, request, response): 
     code, msg, hdrs = response.code, response.msg, response.info() 

     # only add this line to stop 302 redirection. 
     if code == 302: return response 

     if not (200 <= code < 300): 
      response = self.parent.error(
       'http', request, response, code, msg, hdrs) 
     return response 

    https_response = http_response 

cj = cookielib.CookieJar() 
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj), MyHTTPErrorProcessor) 

In questo modo, non avrete nemmeno bisogno di andare in urllib2.HTTPRedirectHandler.http_error_302()

caso Eppure più comune è che vogliamo semplicemente smettere di reindirizzamento (come richiesto):

class NoRedirection(urllib2.HTTPErrorProcessor): 

    def http_response(self, request, response): 
     return response 

    https_response = http_response 

e normalmente usarlo in questo modo:

cj = cookielib.CookieJar() 
opener = urllib2.build_opener(NoRedirection, urllib2.HTTPCookieProcessor(cj)) 
data = {} 
response = opener.open('http://www.example.com', urllib.urlencode(data)) 
if response.code == 302: 
    redirection_target = response.headers['Location'] 
+1

Proprio quello di cui avevo bisogno, e molto conciso 'classe NoRedirection()' - non hai nemmeno bisogno di memorizzare 'codice, msg, hdrs' - Grazie Alan. –

+0

Hai ragione! E ho rimosso la linea come hai suggerito. Grazie Xtof. –

+0

È possibile utilizzare questo approccio per ottenere l'URL di reindirizzamento effettivo? – AdjunctProfessorFalcon

Problemi correlati