2008-11-19 18 views
52

Estoy tratando de probar la funcionalidad de una aplicación web escribiendo una secuencia de inicio de sesión en Python, pero estoy teniendo algunos problemas.Python: urllib/urllib2/httplib confusion

Esto es lo que tengo que hacer:

  1. hacer un post con algunos parámetros y cabeceras.
  2. Seguir una redirección
  3. Recuperar el cuerpo del HTML.

Ahora, soy relativamente nuevo en python, pero las dos cosas que he probado hasta ahora no han funcionado. Primero usé httplib, con putrequest() (pasando los parámetros dentro de la URL) y putheader(). Esto no parece seguir los redireccionamientos.

Luego probé urllib y urllib2, pasando ambos encabezados y parámetros como dicts. Esto parece devolver la página de inicio de sesión, en lugar de la página en la que estoy intentando iniciar sesión, supongo que es por falta de cookies o algo así.

¿Echo de menos algo simple?

Gracias.

+1

Utilice la biblioteca python requests. – hughdbrown

Respuesta

31

Enfoque en urllib2 para esto, funciona bastante bien. No te metas con httplib, no es la API de nivel superior.

Lo que está notando es que urllib2 no sigue el redireccionamiento.

Debe doblar en una instancia de HTTPRedirectHandler que atrapará y seguirá los redireccionamientos.

Además, es posible que desee subclasificar el valor predeterminado HTTPRedirectHandler para capturar la información que luego comprobará como parte de las pruebas de su unidad.

cookie_handler= urllib2.HTTPCookieProcessor(self.cookies) 
redirect_handler= HTTPRedirectHandler() 
opener = urllib2.build_opener(redirect_handler,cookie_handler) 

A continuación, puede utilizar este objeto opener a POST y GET, tratando las redirecciones y galletas correctamente.

Es posible que desee agregar su propia subclase de HTTPHandler para capturar y registrar varios códigos de error, también.

+12

urllib2.urlopen parece manejar redirecciones muy bien. –

+0

@Sridhar Lo he encontrado también - urllib2.urlopen sigue redirecciones perfectamente. – mikemaccana

0

Además del hecho de que puede que falte una cookie, puede haber algunos campos en el formulario que no está PUBLICANDO en el servidor web. La mejor manera sería capturar el POST real desde un navegador web. Puede usar LiveHTTPHeaders o WireShark para husmear el tráfico e imitar el mismo comportamiento en su secuencia de comandos.

+0

Gracias por un buen consejo de complemento de Firefox :) Pero no, parece que estoy pasando los datos y los encabezados necesarios. – Ace

6

Pruebe twill - un lenguaje sencillo que permite a los usuarios navegar por la Web desde una interfaz de línea de comandos. Con sarga, puede navegar a través de sitios web que usan formularios, cookies y la mayoría de las funciones estándar de la Web. Más al punto, sarga está escrito en Python y tiene una python API, por ejemplo:

from twill import get_browser 
b = get_browser() 

b.go("http://www.python.org/") 
b.showforms() 
0

Funkload es una gran herramienta de prueba de aplicaciones web también. Encapsula webunit para manejar la emulación del navegador, luego le ofrece características funcionales y de prueba de carga en la parte superior.

11

Tuve que hacer esto mismo recientemente. Solo necesitaba clases de la biblioteca estándar. Aquí hay un extracto de mi código:

from urllib import urlencode 
from urllib2 import urlopen, Request 

# encode my POST parameters for the login page 
login_qs = urlencode([("username",USERNAME), ("password",PASSWORD)]) 

# extract my session id by loading a page from the site 
set_cookie = urlopen(URL_BASE).headers.getheader("Set-Cookie") 
sess_id = set_cookie[set_cookie.index("=")+1:set_cookie.index(";")] 

# construct headers dictionary using the session id 
headers = {"Cookie": "session_id="+sess_id} 

# perform login and make sure it worked 
if "Announcements:" not in urlopen(Request(URL_BASE+"login",headers=headers), login_qs).read(): 
    print "Didn't log in properly" 
    exit(1) 

# here's the function I used after this for loading pages 
def download(page=""): 
    return urlopen(Request(URL_BASE+page, headers=headers)).read() 

# for example: 
print download(URL_BASE + "config") 
13

@ S.Lott, gracias. Tu sugerencia funcionó para mí, con algunas modificaciones. Así es como lo hice.

data = urllib.urlencode(params) 
url = host+page 
request = urllib2.Request(url, data, headers) 
response = urllib2.urlopen(request) 

cookies = CookieJar() 
cookies.extract_cookies(response,request) 

cookie_handler= urllib2.HTTPCookieProcessor(cookies) 
redirect_handler= HTTPRedirectHandler() 
opener = urllib2.build_opener(redirect_handler,cookie_handler) 

response = opener.open(request) 
15

Aquí está mi opinión sobre este problema.

#!/usr/bin/env python 

import urllib 
import urllib2 


class HttpBot: 
    """an HttpBot represents one browser session, with cookies.""" 
    def __init__(self): 
     cookie_handler= urllib2.HTTPCookieProcessor() 
     redirect_handler= urllib2.HTTPRedirectHandler() 
     self._opener = urllib2.build_opener(redirect_handler, cookie_handler) 

    def GET(self, url): 
     return self._opener.open(url).read() 

    def POST(self, url, parameters): 
     return self._opener.open(url, urllib.urlencode(parameters)).read() 


if __name__ == "__main__": 
    bot = HttpBot() 
    ignored_html = bot.POST('https://example.com/authenticator', {'passwd':'foo'}) 
    print bot.GET('https://example.com/interesting/content') 
    ignored_html = bot.POST('https://example.com/deauthenticator',{}) 
+0

Esta es la única respuesta que realmente hace que este proceso sea simple. – EMI