<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mundo Geek &#187; cookies</title>
	<atom:link href="http://mundogeek.net/etiqueta/cookies/feed/" rel="self" type="application/rss+xml" />
	<link>http://mundogeek.net</link>
	<description>Mundo geek, bitácora sobre todo lo geek: software, gadgets, tecnología, internet, ...</description>
	<lastBuildDate>Wed, 08 Feb 2012 16:09:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Interactuar con webs en Python</title>
		<link>http://mundogeek.net/archivos/2008/04/15/interactuar-con-webs-en-python/</link>
		<comments>http://mundogeek.net/archivos/2008/04/15/interactuar-con-webs-en-python/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 09:00:12 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[urls]]></category>
		<category><![CDATA[webs]]></category>

		<guid isPermaLink="false">http://mundogeek.net/?p=1456</guid>
		<description><![CDATA[Existen dos módulos principales para leer datos de URLs en Python: urllib y urllib2. En esta lección aprenderemos a utilizar urllib2 ya que es mucho más completo, aunque urllib tiene funcionalidades propias que no se pueden encontrar en urllib2, por lo que también lo tocaremos de pasada. urllib2 puede leer datos de una URL usando [...]]]></description>
			<content:encoded><![CDATA[<p>Existen dos módulos principales para leer datos de URLs en Python: <code>urllib</code> y <code>urllib2</code>. En esta lección aprenderemos a utilizar <code>urllib2</code> ya que es mucho más completo, aunque <code>urllib</code> tiene funcionalidades propias que no se pueden encontrar en <code>urllib2</code>, por lo que también lo tocaremos de pasada.</p>
<p><code>urllib2</code> puede leer datos de una URL usando varios protocolos como HTTP, HTTPS, FTP, o Gopher.</p>
<p><span id="more-1456"></span></p>
<p>Se utiliza una función <code>urlopen</code> para crear un objeto parecido a un fichero con el que leer de la URL. Este objeto cuenta con métodos como <code>read</code>, <code>readline</code>, <code>readlines</code> y <code>close</code>, los cuales funcionan exactamente igual que en los objetos <code>file</code>, aunque en realidad estamos trabajando con un wrapper que nos abstrae de un socket que se utiliza por debajo.</p>
<p>El método <code>read</code>, como recordareis, sirve para leer el &#8220;archivo&#8221; completo o el número de bytes especificado como parámetro, <code>readline</code> para leer una línea, y <code>readlines</code> para leer todas las líneas y devolver una lista con ellas.</p>
<p>También contamos con un par de métodos <code>geturl</code>, para obtener la URL de la que estamos leyendo (que puede ser útil para comprobar si ha habido una redirección) e <code>info</code> que nos devuelve un objeto con las cabeceras de respuesta del servidor (a las que también se puede acceder mediante el atributo <code>headers</code>).</p>
<pre name="code" class="python">import urllib2

try:
    f = urllib2.urlopen("http://www.python.org")
    print f.read()
    f.close()
except HTTPError, e:
    print "Ocurrió un error"
    print e.code
except URLError, e:
    print "Ocurrió un error"
    print e.reason</pre>
<p>Al trabajar con <code>urllib2</code> nos podemos encontrar, como vemos, con errores de tipo <code>URLError</code>. Si trabajamos con HTTP podemos encontrarnos también con errores de la subclase de <code>URLError</code> <code>HTTPError</code>, que se lanzan cuando el servidor devuelve un código de error HTTP, como el error 404 cuando no se encuentra el recurso. También podríamos encontrarnos con errores lanzados por la librería que <code>urllib2</code> utiliza por debajo para las transferencias HTTP: <code>httplib</code>; o con excepciones lanzadas por el propio módulo <code>socket</code>.</p>
<p>La función <code>urlopen</code> cuenta con un parámetro opcional <code>data</code> con el que poder enviar información a direcciones HTTP (y solo HTTP) usando POST (los parámetros se envían en la propia petición), por ejemplo para responder a un formulario. Este parámetro es una cadena codificada adecuadamente, siguiendo el formato utilizado en las URLs:</p>
<blockquote><p>&#8216;password=contrase%A4a&#038;usuario=manuel&#8217;</p></blockquote>
<p>Lo más sencillo para codificar la cadena es utilizar el método <code>urlencode</code> de <code>urllib</code>, que acepta un diccionario o una lista de tuplas <code>(clave, valor)</code> y genera la cadena codificada correspondiente:</p>
<pre name="code" class="python">import urllib, urllib2

params = urllib.urlencode({"usuario": "manuel", "password": "contraseña"})
f = urllib2.urlopen("http://ejemplo.com/login", params)</pre>
<p>Si lo único que queremos hacer es descargar el contenido de una URL a un archivo local, podemos utilizar la función <code>urlretrieve</code> de <code>urllib</code> en lugar de leer de un objeto creado con <code>urlopen</code> y escribir los datos leídos.</p>
<p>La función <code>urlretrieve</code> toma como parámetros la URL a descargar y, opcionalmente, un parámetro <code>filename</code> con la ruta local en la que guardar el archivo, un parámetro <code>data</code> similar al de <code>urlopen</code> y un parámetro <code>reporthook</code> con una función que utilizar para informar del progreso.</p>
<p>A excepción de las ocasiones en las que se utiliza el parámetro <code>data</code> las conexiones siempre se realizan utilizando GET (los parámetros se envían en la URL). Para enviar datos usando GET basta con concatenar la cadena resultante de <code>urlencode</code> con la URL a la que nos vamos a conectar mediante el símbolo &#8220;?&#8221;.</p>
<pre name="code" class="python">params = urllib.urlencode({"usuario": "manuel", "password": "contraseña"})

f = urllib2.urlopen("http://ejemplo.com/login" + "?" + params)</pre>
<p>En <code>urllib</code> también se utiliza una función <code>urlopen</code> para crear nuestros pseudo-archivos, pero a diferencia de la versión de <code>urllib</code>, la función <code>urlopen</code> de <code>urllib2</code> también puede tomar como parámetro un objeto <code>Request</code>, en lugar de la URL y los datos a enviar.</p>
<p>La clase <code>Request</code> define objetos que encapsulan toda la información relativa a una petición. A través de este objeto podemos realizar peticiones más complejas, añadiendo nuestras propias cabeceras, como el User-Agent.   </p>
<p>El constructor más sencillo para el objeto <code>Request</code> no toma más que una cadena indicando la URL a la que conectarse, por lo que utilizar este objeto como parámetro de <code>urlopen</code> sería equivalente a utilizar una cadena con la URL directamente.</p>
<p>Sin embargo el constructor de <code>Request</code> también tiene como parámetros opcionales una cadena <code>data</code> para mandar datos por POST, un diccionario <code>headers</code> con las cabeceras y un par de campos <code>origin_req_host</code> y <code>unverifiable</code>, que quedan fuera del propósito de la lección.</p>
<p>Veamos cómo añadir nuestras propias cabeceras utilizando como ejemplo la cabecera User-Agent. El User-Agent es una cabecera que sirve para identificar el navegador y sistema operativo que estamos utilizando para conectarnos a esa URL. Por defecto <code>urllib2</code> se identifica como &#8220;Python-urllib/2.5&#8243;; si quisiéramos identificarnos como un Linux corriendo Konqueror por ejemplo, usaríamos un código similar al siguiente:</p>
<pre name="code" class="python">ua = "Mozilla/5.0 (compatible; Konqueror/3.5.8; Linux)"
h = {"User-Agent": ua}
r = urllib2.Request("http://www.python.org", headers=h)
f = urllib2.urlopen(r)
print f.read()</pre>
<p>Para personalizar la forma en que trabaja <code>urllib2</code> podemos instalar un grupo de manejadores (handlers) agrupados en un objeto de la clase <code>OpenerDirector</code> (<em>opener</em> o abridor), que será el que se utilice a partir de ese momento al llamar a <code>urlopen</code>.</p>
<p>Para construir un opener se utiliza la función <code>build_opener</code> a la que se le pasa los manejadores que formarán parte del opener. El opener se encargará de encadenar la ejecución de los distintos manejadores en el orden dado. También se puede usar el constructor de <code>OpenerDirector</code>, y añadir los manejadores usando su método <code>add_handler</code>.</p>
<p>Para instalar el opener una vez creado se utiliza la función <code>install_opener</code>, que toma como parámetro el opener a instalar. También se podría, si sólo queremos abrir la URL con ese opener una sola vez, utilizar el método <code>open</code> del opener. </p>
<p><code>urllib2</code> cuenta con handlers que se encargan de manejar los esquemas disponibles (HTTP, HTTPS, FTP), manejar la autenticación, manejar las redirecciones, etc.</p>
<p>Para añadir autenticación tendríamos que instalar un opener que incluyera como manejador <code>HTTPBasicAuthHandler</code>, <code>ProxyBasicAuthHandler</code>, <code>HTTPDigestAuthHandler</code> y/o <code>ProxyDigestAuthHandler</code>. </p>
<p>Para utilizar autenticación HTTP básica, por ejemplo, usaríamos <code>HTTPBasicAuthHandler</code>: </p>
<pre name="code" class="python">aut_h = urllib2.HTTPBasicAuthHandler()
aut_h.add_password("realm", "host", "usuario", "password")

opener = urllib2.build_opener(aut_h)
urllib2.install_opener(opener)

f = urllib2.urlopen("http://www.python.org")</pre>
<p>Si quisiéramos especificar un proxy en el código tendríamos que utilizar un opener que contuviera el manejador <code>ProxyHandler</code>. El manejador por defecto incluye una instacia de <code>ProxyHandler</code> construido llamando al inicializador sin parámetros, con lo que se lee la lista de proxies a utilizar de la variable de entorno adecuada. Sin embargo también podemos construir un <code>ProxyHandler</code> pasando como parámetro al inicializador un diccionario cuyas claves son los protocolos y los valores, la URL del proxy a utilizar para dicho protocolo.</p>
<pre name="code" class="python">proxy_h = urllib2.ProxyHandler({"http" : "http://miproxy.net:123"})

opener = urllib2.build_opener(proxy_h)
urllib2.install_opener(opener)

f = urllib2.urlopen("http://www.python.org")</pre>
<p>Para que se guarden las cookies que manda HTTP utilizamos el manejador <code>HTTPCookieProcessor</code>.</p>
<pre name="code" class="python">cookie_h = urllib2.HTTPCookieProcessor()

opener = urllib2.build_opener(cookie_h)
urllib2.install_opener(opener)

f = urllib2.urlopen("http://www.python.org")</pre>
<p>Si queremos acceder a estas cookies o poder mandar nuestras propias cookies, podemos pasarle como parámetro al inicializador de <code>HTTPCookieProcessor</code> un objeto de tipo <code>CookieJar</code> del módulo <code>cookielib</code>.</p>
<p>Para leer las cookies mandadas basta crear un objeto iterable a partir del <code>CookieJar</code> (también podríamos buscar las cabeceras correspondientes, pero este sistema es más claro y sencillo): </p>
<pre name="code" class="python">import urllib2, cookielib

cookie_j = cookielib.CookieJar()

cookie_h = urllib2.HTTPCookieProcessor(cookie_j)

opener = urllib2.build_opener(cookie_h)
opener.open("http://www.python.org")

for num, cookie in enumerate(cookie_j):
    print num, cookie.name
    print cookie.value
    print</pre>
<p>En el improbable caso de que necesitáramos añadir una cookie antes de realizar la conexión, en lugar de conectarnos para que el sitio la mande, podríamos utilizar el método <code>set_cookie</code> de <code>CookieJar</code>, al que le pasamos un objeto de tipo <code>Cookie</code>. El constructor de <code>Cookie</code>, no obstante, es bastante complicado.</p>
<link type="text/css" rel="stylesheet" href="http://mundogeek.net/sh/css/SyntaxHighlighter.css"></link>
<script language="javascript" src="http://mundogeek.net/sh/js/shCore.js"></script><br />
<script language="javascript" src="http://mundogeek.net/sh/js/shBrushPython.js"></script><br />
<script language="javascript">
dp.SyntaxHighlighter.ClipboardSwf = 'http://mundogeek.net/sh//flash/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2008/04/15/interactuar-con-webs-en-python/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
	</channel>
</rss>

