10 mar. 2012

Emulando la navegación en python con mechanize (parte 1)

En estos días me ha tocado programar una aplicación que permita interactuar de manera automática con otra, para ello utilicé la librería python-mechanize.

Está librería permite la interacción con aplicaciones web para automatizar dicha interacción o cuando se quiere realizar pruebas de estrés a una aplicación se usa multi-mechanize.

La página de mechanize la pueden revisar en el siguiente enlace. Hay una guía en Inglés.

En estos día he estado practicando con django (framework de desarrollo web en python) donde espero pronto poder publicar artículos al respecto.

La aplicación en Django es la de manejo de bookmarks, se tiene un inicio de sesión, una página de bienvenida al usuario registrado, luego se puede listar los bookmarks y cerrar la sesión (aplicación en desarrollo).

Pues todo esos pasos se van a automatizar con python-mechanize.

Para instalar mechanize se puede hacer a lo Debian:

#apt-get install python-mechanize

La siguiente figura muestra la aplicación en django sin mucho adorno.

Al darle clip en sesión o Inicio de Sesión aparece la solicitud de usuario y clave como lo muestra la figura:
Al darle botón derecho sobre la entrada de Usuario selecciona Inspeccionar elemento (esto en google chrome o chromium) y aparece una sección donde se muestra el código del formulario.

De esa forma se puede averiguar los nombres de los elementos del formulario para luego utilizarlo en el código python con mechanize.

Se inicia el interprete de comandos de python:
ecrespo@jewel:~$ python
Python 2.7.2+ (default, Dec  1 2011, 01:55:02)
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Se importa mechanize y el manejo de cookies:
>>> import mechanize
>>> import cookielib


Se crea la instancia browser de mechanize:
>>>br = mechanize.Browser()

Se crea la instancia del cookie:
>>>cj = cookielib.LWPCookieJar()

Se asocia la instancia del cookie con el navegador:
>>>br.set_cookiejar(cj)



Se define que no se maneja robots:
>>>br.set_handle_robots(False)

Se define el tiempo de refrescamiento:
>>>br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)

Se define las cabeceras del navegador, en este caso se le está diciendo que el navegador es un firefox desde Linux Debian:
>>>br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; es-VE; rv:1.9.0.1)Gecko/2008071615 Debian/6.0 Firefox/9')]

Se abre la aplicación web que se encuentra en localhost y puerto 8050:
>>>r = br.open('http://localhost:8050/')

Se muestra el resultado de la página:
>>>print r.read()

En la siguiente figura se muestra el resultado (el código html de la página) del comando anterior:

Ahora se revisarán los links que maneja la página para darle clip a sesión o Inicio de sesión para ingresar el usuario y clave:

Se crea un ciclo con los enlaces existentes en la página, luego se consulta el texto de cada enlace, si es sesion se abre el enlace pasado el url del mismo, luego finaliza el ciclo.
>>> for link in br.links():
...     if link.text == "sesion":
...         r= br.open("%s" %link.absolute_url)
...         break
...     else:
...         continue

Ya en este momento se encuentra en la página de ingreso de usuario y clave:

>>> print br.geturl()
http://localhost:8050/sesion/

Se puede mostrar el código html de la página de Inicio de sesión con el comando br.response().read():
>>>print br.response().read()

En la figura se muestra el resultado del comando:

Se puede mostrar los campos del formulario con el comando br.forms():
>>> for form in br.forms():
...     print form
...
<POST http://localhost:8050/sesion/ application/x-www-form-urlencoded
  <HiddenControl(csrfmiddlewaretoken=d3c9e6c2e06f5014647a1711ee3d4908) (readonly)>
  <TextControl(username=)>
  <PasswordControl(password=)>
  <SubmitControl(<None>=login) (readonly)>
  <HiddenControl(next=/) (readonly)>>

Se nota que se tiene dos campos de entrada de datos username y password y el botón de login para enviar los datos.

Como se tiene un sólo formulario se usa el parámetro nr=0, en el caso que existan varios formularios en dicha página sigue con los números consecutivos o se le pasa el nombre del formulario si existe name="nombre":
>>>br.select_form(nr=0)

Ahora se le pasa los datos de usuario y clave, luego se le da clip al botón de envío:
>>> br.form['username'] = 'usuario'
>>> br.form['password'] = 'clave'
>>> br.submit()
<response_seek_wrapper at 0xb6f0a06cL whose wrapped object = <closeable_response at 0xb6f0d4ccL whose fp = <socket._fileobject object at 0xb6eff5ac>>>


Al ejecutar response().read() se mostrará la página de bienvenida del usuario que ingreso a la aplicación:
>>>print br.response().read()

En la siguiente figura se muestra el resultado del comando:
Se muestra los enlaces disponibles y se selecciona el de publicar:
>>> for enlace in br.links():
...     if enlace.text == "Publicar":
...         s = br.open("%s" %enlace.absolute_url)
...         break
...     else:
...         continue

Se muestra el url de la página:
>>> print br.geturl()
http://localhost:8050/salvar/

Ahora se ingresará un URL de un sitio, por ejemplo www.python.org:

Primero se despliega el formulario:
>>> for form in br.forms():
...     print form
...
<POST http://localhost:8050/salvar/ application/x-www-form-urlencoded
  <HiddenControl(csrfmiddlewaretoken=d3c9e6c2e06f5014647a1711ee3d4908) (readonly)>
  <TextControl(url=)>
  <TextControl(title=)>
  <TextControl(tags=)>
  <SubmitControl(<None>=save) (readonly)>>

Se tiene que pasar el url, luego el título del url y etiquetas:
>>> br.select_form(nr=0)
>>> br.form['url'] = "www.python.org"
>>> br.form['title'] = "Python"
>>> br.form['tags'] = "Python Programacion"
>>> br.submit()
<response_seek_wrapper at 0xb6efee0cL whose wrapped object = <closeable_response at 0xb6f12aacL whose fp = <socket._fileobject object at 0xb6eff86c>>>


Se muestra el contenido de la página luego de ingresar los datos:
 >>> print br.response().read()

En la siguiente figura se muestra el resultado:

Para finalizar se presenta los enlaces disponibles para luego cerrar la sesión del usuario:
>>> for link in br.links():
...     if  link.text == "Cerrar Sesion":
...         r = br.open("%s" %link.absolute_url)
...         break
...     else:
...         continue

Se muestra el código html de la página resultante luego de dar clip en cerrar sesión y la figura donde aparece dicho código:
>>>print br.response().read()
En el siguiente artículo sobre mechanize se explicará el uso de formularios más complejos que sólo entrar datos.



Publicar un comentario en la entrada

AddThis