Python y la Web

download Python y la Web

of 5

Transcript of Python y la Web

  • 7/31/2019 Python y la Web

    1/5

    Python y la Web

    ENREDADOS

    Digamos que llegas un da por

    la maana a la oficina. El jefe

    se acerca y te pide que vuelvas

    a pasar, otra vez!, un montn de

    informacin a otra empresa a travs

    del peor interfaz jams diseado: una

    web.Carga la pgina, introduce tus datos

    de acceso, pincha aqu, pincha all.

    Cuando ests en la pgina con el for-

    mulario en cuestin debes introducir

    los datos y pinchar en un enlace o

    botn para enviarlos. Una y otra vez,

    una y otra vez. Quiz durante horas.

    Acaso no hay una mejor manera de

    hacer esto? Lo ideal sera poder usar

    tu hoja de clculo preferida, rellenar

    los campos en ella de forma rpida

    (aquellos que se repitan pueden sercopiados y pegados) y cuando estu-

    viese lista hacer algo(magia vud?) y

    que se cargasen solos en la dichosa

    DESARROLLO Python

    54 Nmero 29

    Podemos automatizar comandos y programas grficos, por qu no

    automatizar la interaccin con pginas web? En este artculo crearemos

    un pequeo script que puede ahorrarnos mucho trabajo con el ratn.

    POR JOSE MARA RUIZ

    web. Y por supuesto, sin que se ente-

    rase el jefe, as tendras ms tiempo

    para leer artculos como ste ;).

    Pues s, existe una manera de hacer

    exactamente lo que acabas de leer! Y

    vamos a explicarlo en este captulo.

    As podrs decirle a tu jefe que estarevista har a la empresa mucho ms

    productiva.

    Mechanize

    No es la primera vez que hago esto.

    Hace algunos aos tuve este mismo

    problema en la oficina en la que traba-

    jaba. Haba que rellenar un formulario

    web para dar parte de unas mismas.

    Esa tarea, debido al volumen de las

    ventas, requera que una persona per-

    diese toda una maana simplementeporque a nadie en la otra empresa se

    le ocurri la idea de hacer el proceso

    ms rpido.

    W W W . L I NUX- M A GA Z I NE . E S

    As que ni corto ni perezoso mi jefe

    cre un script en Perl que haca este

    trabajo a partir de un fichero de texto

    CSV. El problema es que lo hizo en

    Perl y esta seccin va sobre Python.

    Hemos de mudarnos todos a Perl

    para poder disfrutar de este tipo deventajas? No, gracias a que John J.

    Lee decidi portar la librera Mecha-

    nize que Andy Lester cre en Perl (ver

    Recurso [1]) a Python (ver Recurso

    [2]).

    Las distribuciones de Linux suelen

    permitir instalarla como paquete. El

    problema es que la versin ms com-

    pleta no est an liberada, y es reco-

    mendable emplear la que se encuentra

    en el servidor de Subversion de John.

    El proceso es simple, instalamos elcliente de Subversion que ms nos

    guste, aqu usar el estndar, y des-

    cargamos el cdigo fuente con:

  • 7/31/2019 Python y la Web

    2/5

    > svn co http://U

    codespeak.net/svn/wwwsearch/U

    mechanize/trunk mechanize

    John emplea la librera setuptools de

    Python para compilar e instalar la libre-ra, as que deberamos proceder a insta-

    larla antes de continuar. Despus slo

    debemos ejecutar:

    > python setup.py build

    > sudo python setup.py install

    Y listo. Ya tenemos nuestra librera

    mechanize lista para trabajar.

    Juguemos con una WebComencemos con algo simple. Vamos a

    conectar con la web de Linux Magazine

    y a pedirle que busque la palabra

    python para, a continuacin, conse-

    guir una lista de las urls de los primeros

    artculos que contengan esa palabra

    (sern enlaces a ficheros PDF), ver

    Figura [1]. De esta forma veremos cmo

    se trabaja con mechanize, ya que tiene

    una forma peculiar de tratar el cdigo

    HTML.

    Para ello debemos comenzar por

    arrancar python e importar la librera

    mechanize y re (expresiones regulares):

    >>> import re

    >>> import mechanize

    No ocurre nada particularmente vistoso,

    a no ser que no hallamos instalado

    correctamente la librera. Muy bien,

    ahora necesitamos crear un navegador:

    >>> br = mechanize.Browser()

    Ahora ya lo tenemos en la variable br.

    No me refiero a un navegador grfico,sino a todo lo que un navegador puede

    hacer pero sin la parte grfica. Me

    explico, un navegador posee un motor

    que interacta con los servidores web y

    un interfaz grfico que interacta con el

    usuario. La librera mechanize nos da lo

    primero sin lo segundo. Nuestro inter-

    faz de usuario sern llamadas a mto-

    dos del objeto Browser.

    Un problema que nos podemos encon-

    trar, ya desde el principio, es que nuestra

    red disponga de un proxy para acceder a

    Internet. Este caso es bastante comn,

    as que debemos indicrselo al objeto

    almacenado en br:

    >>> br.set_proxies(U

    {http : 192.168.1.254:8000,U

    ftp : 192.168.1.254:8000})

    Aqu he especificado un proxy para http

    y otro para ftp, que suele ser lo normal.Ya tenemos nuestro navegador listo. Slo

    tenemos que abrir una pgina:

    >>>> respuesta= br.openU

    (http://www.linuxmagazine.es/)

    Una vez abierta se nos devuelve un

    objeto de respuesta. Este objeto contiene

    todos los mtodos necesarios para poder

    trabajar con la informacin devuelta por

    el servidor web. Por ejemplo, podramos

    imprimir el contenido HTML de la

    pgina:

    >>>> printU

    respuesta.read()

    ....

    No pongo aqu la informacin devuelta

    porque podra ocupar una pgina com-

    pleta. Adems es de poca utilidad. Lo

    interesante de mechanize es que genera

    la pgina y nos permite acceder a las

    partes jugosas de la misma de forma

    muy sencilla. Digamos que queremos

    saber qu formularios contiene la

    pgina:

    >>> for form in br.forms():

    ... print form

    ...

    Mechanize tiene su propio lenguaje para

    representar partes de la pgina y aqu

    podemos ver un ejemplo del mismo. Nos

    dice que hay dos formularios, que

    emplean POSTcomo mtodo de comuni-

    cacin con la pgina. Muy bien, nosotros

    queremos acceder al segundo puesto que

    Python DESARROLLO

    55Nmero 29W W W . L I NUX- M A GA Z I NE . E S

    01 import re

    02 import mechanize

    03

    04 br = mechanize.Browser()

    05

    06 br.set_handle_robots(False)

    07

    08 respuesta =

    br.open(http://www.linuxmagaz

    ine.es/)09

    10 br.select_form(nr=1)

    11

    12 br[words]=python

    13

    14 br.submit()

    15

    16 # Estamos en la pgina de

    resultados

    17

    18 #primer resultado

    19 urls = [url.absolute_url for

    url inbr.links(url_regex=re.compile(

    rpdf$))]

    20

    21 #eliminamos duplicados

    22

    23 urls =

    dict(zip(urls,urls)).keys()

    24

    25

    2 6 r =

    re.compile(.*/(\d+)/(.*)$)

    2728

    29 for url in urls:

    30

    31 m= r.match(url)

    32 nombre =

    m.group(1)+-+m.group(2)

    33 print nombre

    34

    35 respuesta = br.open(url)

    36 datos = respuesta.read()

    37

    38 fichero = open (nombre,w)

    39 fichero.write(datos)40 fichero.close()

    Listado 1: Nuestra araa web

  • 7/31/2019 Python y la Web

    3/5

    zando en 0. Con este mtodo ya

    tenemos seleccionado el formulario,pero ste se compone a su vez de

    varios elementos incrustados. Cmo

    podemos seleccionarlos? Por suerte

    para nosotros, John, el desarrollador,

    ha empleado toda la potencia de

    Python y ha realizado un truco de

    magia: hacer que el objeto almace-

    nado en br se comporte como un tipo

    diccionario Python. Si el elemento

    input donde hay que escribir las

    palabras a buscar se llama words,

    entonces todo lo que tenemos que

    hacer es:

    >>> br[words]=python

    As de simple! Es o no maravilloso

    este mdulo? Esto s que es cdigo

    compacto en estado puro. Despus

    de la euforia debemos volver al

    asunto que nos ha trado hasta aqu:

    queremos los enlaces con la palabra

    python. Ya tenemos nuestro formu-

    lario relleno, ahora debemos pu lsar

    el botn. Pero cmo? Pues con el

    mtodo submit:

    >>> respuesta = br.sumbit()

    Lo que acabamos de hacer es ms com-

    plejo de lo que parece, qu ha ocu-rrido? Al ejecutar submit hemos

    enviado los datos del formulario al ser-

    vidor, que nos habr respondido rediri-

    gindonos a la pgina con los resulta-

    dos. El contenido de esta interaccin se

    almacena en respuesta, que no es ni

    ms ni menos que otro objeto que

    envuelve un documento HTML. Debe-

    mos recoger todos los enlaces que nos

    interesan.

    Y aqu viene otro punto fuerte de

    mechanize: su integracin con las

    expresiones regulares. Desde luego queJohn no nos iba a fallar en este aspecto.

    Podemos elegir un enlace usando una

    expresin regular, de forma que no

    tenemos que ir buscando a tontas y a

    locas. Con saber ms o menos qu for-

    mato tendr el enlace que deseamos,

    podremos conseguir la informacin que

    contiene. Pero antes veamos qu debe-

    ramos hacer si no supiramos muy

    bien qu buscamos. Al igual que con

    los formularios, los enlaces se pueden

    recorrer como si fuesen una lista:

    >>> for link in br.links():

    ... print link

    es el que emplea la url http://www.linux-

    magazine.es/search. Este formulariotiene un campo de texto llamado words.

    Al principio cuesta un poco entender

    este lenguaje pero con un poco de prc-

    tica no es tan complicado.

    De acuerdo, tenemos que acceder al

    segundo formulario, as que le indica-

    mos a br, nuestro navegador virtual,

    que emplee este formulario. Es posible

    realizar la seleccin por posicin o por

    nombre. El nombre vendra indicado

    por el parmetro HTML name, que el

    desarrollador de la web de Linux Maga-

    zine ha decidido ignorar, al fin y alcabo no es obligatorio.

    Si se diese el caso de que el formula-

    rio tuviese un nombre podramos selec-

    cionarlo con:

    >>> br.select_formU

    (name = miformulario)

    Pero como no es este nuestro caso, lo

    seleccionaremos por posicin:

    >>> br.select_form(nr = 1)

    Empleamos el nmero 1, porque los

    formularios estn numerados comen-

    DESARROLLO Python

    56 Nmero 29 W W W . L I NUX- M A GA Z I NE . E S

    Figura 1: Pgina de resultados de bsqueda de Linux Magazine.

  • 7/31/2019 Python y la Web

    4/5

  • 7/31/2019 Python y la Web

    5/5

    DESARROLLO Python

    58 Nmero 29 W W W . L I NUX- M A GA Z I NE . E S

    extraer las llaves obtenemos la misma

    lista pero eliminando los duplicados.

    Complicado? S, como lneas ante-

    riores, pero indudablemente til y

    requiere muy pocas pulsaciones del

    teclado.De acuerdo, ya tenemos los enla-

    ces y qu hacemos con ellos

    ahora? Pues podramos descargarlos:

    recorriendo la lista y usando la fun-

    cin br.open() para cargarlos, y res-

    puesta .read() para leer el contenido

    del fichero, guardndolo en un

    fichero con nombre igual a la ltima

    parte de la URL. Por desgracia,

    muchos de ellos se llaman

    Python.pdf, as que vamos a usar

    el nmero de esa revista en el nom-

    bre. Puedes ver el cdigo completo

    en el Listado [1].

    Pero, con este cdigo slo pode-

    mos conseguir los primeros resulta-

    dos no? S, para mejorarlo y que

    descargue todos los resultados slo

    tendramos que localizar el enlace a

    siguiente resultado y pulsar en l

    con el mtodo br.follow_link(). Dejo

    al lector que piense cmo hacerlo,

    dando una sola pista: emplea un

    bucle hasta que no encuentres links

    que se correspondan con la expre-sin regular.

    Conclusin

    No es de extraar que Google emplee

    Python. De hecho, el propio Guido

    Van Rossum cre una araa web con

    una de las primeras implementacio-

    nes de Python ya hace algunos ai-

    tos. Hemos podido comprobar cmo

    podemos usar una pgina web como

    si estuvisemos delante de un nave-

    gador mediante la magnfica, y an

    en estado Beta, librera mechanize yempleando un nmero de lneas de

    cdigo realmente minsculo. La pr-

    xima vez que el lector se enfrente a

    un trabajo tedioso con una pgina

    web, puede que tenga un par de

    ideas para hacer que el ordenador

    trabaje por l gracias a cierta ser-

    piente. I

    ...

    Link(base_url=http://U

    www.linux-magazine.es/,U

    url=/,text=logoOL.gif[IMG],U

    tag=a, attrs=[(href, /)])

    Link(base_url=http://Uwww.linux-magazine.es/,U

    url=/,text=logoOR.gif[IMG],U

    tag=a, attrs=[(href, /)])

    ....

    Aqu slo se muestran los dos prime-

    ros. Si pruebas esto mismo en tu

    equipo vers que hay un nmero res-

    petable de enlaces en esta pgina en

    concreto. De nuevo mechanize nos

    muestra lo que entiende por un

    enlace. Pero como nosotros sabemos

    lo que queremos, podemos pasar

    directamente a la accin con las

    expresiones regulares:

    >>> urls =U

    [url.absolute_url for url inU

    br.links(url_regex=re.compileU

    (rpdf$))]

    Python comprime en poco cdigo

    mucho trabajo, as que esta nica

    lnea requiere una explicacin.

    Comencemos por la lista de compre-sin. En Python es posible crear listas

    a partir de definiciones de lo que se

    supone que va en las mismas. En este

    caso hay que comenzar por el cdigo:

    br.links(url_regex=U

    re.compile(rpdf$))

    Este cdigo localiza todos aquellos

    enlaces que se puedan identificar con

    el argumento que pasemos al mtodo

    br.links() . Es posible usar un nmero,

    como hicimos con el formulario ante-riormente, pero en lugar de eso vamos

    a emplear una expresin regular. As

    que usamos la funcin re.compile(),

    que no hace otra cosa que generar un

    objeto que contiene un reconocedor

    de la expresin regular que pasamos

    como parmetro. En nuestro caso es

    pdf$, (la rde delante le indica a la

    funcin que la cadena se corresponde

    con una expresin regular), que no

    hace otra cosa que localizar cadenas

    acabadas en la letras pdf, y para

    ello podemos el smbolo $ al final

    de pdf. Como decamos, re.com-

    pile() devuelve un objeto que reco-

    noce la expresin regular, lo que

    podramos llamar una expresin

    regular compilada, y lo almacenamos

    en el argumento con nombre

    url_regex. La funcin br.links() lo

    reconoce y sabe que debe buscarenlaces que al reconocerlos con la

    expresin regular devuelvan True.

    br.links() generar as una lista de

    enlaces, y aqu entra en funcin la

    clusula for ... in ..., que no hace

    otra cosa que recorrer la lista y

    devolver los enlaces bajo el nombre

    de variable url. La lista de compre-

    sin se compone de cada uno de esos

    enlaces, con nombre url, de lo que

    nos quedamos con su atributo abso-

    lute_url: su ruta completa. Y con

    esto acabamos. Todo se reduce a una

    sola lnea de Python, escribimos

    poco pero vale por decenas de

    lneas!

    An tenemos un problema, la web

    de resultado de bsqueda de Linux

    Magazine devuelve los resultados

    duplicados. Aplicando un poco de

    Kung Fu Python podemos deshacer-

    nos de ellos en una lnea:

    >>> urls = dict(U

    zip(urls,urls)).keys()

    Zip significa cremallera en ingls, y

    eso es precisamente lo que hace la

    funcin zip() . Cierra dos listas como

    si fuese una cremallera:

    >>> zip([uno,dos,U

    tres],[1,2,3])

    [(uno,1),(dos,2),U

    (tres,3)]

    Esto puede resultar muy conveniente,

    porque precisamente una lista contuplas de 2 valores es lo que necesita-

    mos para crear un diccionario.

    >>> dict(zip([uno,dos,U

    tres],[1,2,3]))

    {dos: 2, tres: 3,U

    uno: 1}

    Y del diccionario podemos obtener las

    llaves usando el mtodo keys(). Si

    hacemos todo esto con un lista,

    cerrndola con ella misma en crema-

    llera, y teniendo en cuenta que en un

    diccionario no pueden existir dos lla-

    ves iguales, el resultado es que al

    [1] http://search.cpan.org/dist/

    WWW-Mechanize/[2] http://wwwsearch.sourceforge.net/

    mechanize/

    RECURSOS