11.5. Establecer el User-Agent

El primer paso para mejorar nuestro cliente de servicios web HTTP es identificarnos adecuadamente con User-Agent. Para hacerlo nos hace falta pasar de la urllib básica y zambullirnos en urllib2.

Ejemplo 11.4. Presentación de urllib2

>>> import httplib
>>> httplib.HTTPConnection.debuglevel = 1                             1
>>> import urllib2
>>> request = urllib2.Request('http://diveintomark.org/xml/atom.xml') 2
>>> opener = urllib2.build_opener()                                   3
>>> feeddata = opener.open(request).read()                            4
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: Python-urllib/2.1
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Wed, 14 Apr 2004 23:23:12 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
header: ETag: "e8284-68e0-4de30f80"
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
1 Si aún mantiene abierto el IDE de Python tras el ejemplo de la sección anterior, puede saltarse esto, ya que es para activar la depuración de HTTP de manera que pueda ver lo que se está enviando realmente, y qué viene de vuelta.
2 Descargar un recurso HTTP con urllib2 es un proceso de tres pasos, por buenas razones que aclararé en breve. El primer paso es crear un objeto Request, que toma la URL del recurso que pretendemos descargar. Tenga en cuenta que este paso no descarga nada realmente.
3 El segundo paso es construir algo que abra la URL. Puede tomar cualquier tipo de manejador, que controlará cómo se manipulan las respuestas. Pero también podríamos crear uno de estos “abridores” sin manejadores a medida, que es lo que estamos haciendo aquí. Veremos cómo definir y usar estos manejadores más adelante en este capítulo, cuando exploremos las redirecciones.
4 El último paso es decirle al abridor que abra la URL usando el objeto Request que hemos creado. Como puede ver por toda la información de depuración que se imprime, este paso sí que descarga el recurso, y almacena los datos devueltos en feeddata.

Ejemplo 11.5. Añadir cabeceras con la Request

>>> request                                                1
<urllib2.Request instance at 0x00250AA8>
>>> request.get_full_url()
http://diveintomark.org/xml/atom.xml
>>> request.add_header('User-Agent',
...     'OpenAnything/1.0 +http://diveintopython.org/')    2
>>> feeddata = opener.open(request).read()                 3
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: OpenAnything/1.0 +http://diveintopython.org/   4
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Wed, 14 Apr 2004 23:45:17 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
header: ETag: "e8284-68e0-4de30f80"
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
1 Continuamos el ejemplo anterior; hemos creado un objeto Request con la URL a la que queremos acceder.
2 Podemos añadir cabeceras HTTP arbitrarias a la consulta usando el método add_header del objeto Request. El primer argumento es la cabecera, el segundo es el valor de la cabecera. La convención dicta que un User-Agent debería estar en este formato específico: un nombre de aplicación, seguido por una barra, seguido por un número de versión. El resto tiene forma libre, y verá muchas variaciones en el mundo real, pero en algún lado debería incluir una URL de su aplicación. El User-Agent se registra normalmente en el servidor junto a otros detalles de la consulta, e incluir una URL de la aplicación le permite a los administradores del servidor buscar en sus registros de acceso para contactar con usted si algo fue mal.
3 También podemos reutilizar el objeto opener que creó antes, y descargará de nuevo el mismo feed, pero con nuestra cabecera User-Agent modificada.
4 Y aquí estamos enviando nuestra propia User-Agent, en lugar de la genérica que Python envía por omisión. Si observa atentamente notará que hemos definido una cabecera User-Agent, pero que en realidad se envió una User-agent. ¿Ve la diferencia? urllib2 cambió las mayúsculas para que sólo la primera letra lo sea. En realidad no importa; HTTP especifica que los nombres de los campos de la cabecera son totalmente independientes de las mayúsculas.