2009-05-09 27 views
41

¿urllib2 recupera toda la página cuando se realiza una llamada urlopen?Python: Obtenga los encabezados HTTP de la llamada urllib2.urlopen?

Me gustaría leer el encabezado de respuesta HTTP sin obtener la página. Parece que urllib2 abre la conexión HTTP y luego obtiene la página HTML real ... ¿o simplemente comienza a almacenar en búfer la página con la llamada urlopen?

import urllib2 
myurl = 'http://www.kidsidebyside.org/2009/05/come-and-draw-the-circle-of-unity-with-us/' 
page = urllib2.urlopen(myurl) // open connection, get headers 

html = page.readlines() // stream page 

Respuesta

42

Utilice el método response.info() para obtener los encabezados.

Desde el urllib2 docs:

urllib2.urlopen (url [, datos] [, tiempo de espera])

...

Esta función devuelve un objeto de tipo fichero con dos adicionales métodos:

  • geturl() - devuelve la URL del recurso recuperado, comúnmente utilizado para determinar si se siguió un redireccionamiento
  • información() - devuelve el meta-información de la página, como los encabezados, en forma de una instancia httplib.HTTPMessage (ver Referencia Rápida de encabezados HTTP)

Así, por ejemplo, su , intente revisar el resultado de response.info().headers para lo que está buscando.

Tenga en cuenta que la principal advertencia al uso de httplib.HTTPMessage está documentada en python issue 4773.

+17

*** Python 3 Nota *** Primero, no hay nada como 'response.info(). Headers', do a' dict (response.info()) '. En segundo lugar, para el código de estado HTTP, haga 'response.status'. – treecoder

+1

¿Esto ** solo recibe ** el encabezado o ** solo imprime ** el encabezado? –

+2

¿Dónde se documentan los 'encabezados'? También considere usar 'response.info(). Items()' que devuelve un valor clave dict. –

40

¿Qué pasa con el envío de una solicitud HEAD en lugar de una solicitud GET normal. El siguiente recorte (copiado de un question similar) hace exactamente eso.

>>> import httplib 
>>> conn = httplib.HTTPConnection("www.google.com") 
>>> conn.request("HEAD", "/index.html") 
>>> res = conn.getresponse() 
>>> print res.status, res.reason 
200 OK 
>>> print res.getheaders() 
[('content-length', '0'), ('expires', '-1'), ('server', 'gws'), ('cache-control', 'private, max-age=0'), ('date', 'Sat, 20 Sep 2008 06:43:36 GMT'), ('content-type', 'text/html; charset=ISO-8859-1')] 
+2

creo que lo haría! – shigeta

8

urllib2.urlopen hace un HTTP GET (o POST si usted proporciona un argumento de datos), no una cabeza de HTTP (si lo hiciera este último, no se podía hacer readlines u otros accesos al cuerpo de la página, por supuesto).

+0

oh gracias - eso responde la pregunta – shigeta

20

En realidad, parece que urllib2 puede hacer una solicitud HTTP HEAD.

El question que @reto vinculado a, arriba, muestra cómo obtener urllib2 para hacer una solicitud HEAD.

Aquí está mi opinión sobre ella:

import urllib2 

# Derive from Request class and override get_method to allow a HEAD request. 
class HeadRequest(urllib2.Request): 
    def get_method(self): 
     return "HEAD" 

myurl = 'http://bit.ly/doFeT' 
request = HeadRequest(myurl) 

try: 
    response = urllib2.urlopen(request) 
    response_headers = response.info() 

    # This will just display all the dictionary key-value pairs. Replace this 
    # line with something useful. 
    response_headers.dict 

except urllib2.HTTPError, e: 
    # Prints the HTTP Status code of the response but only if there was a 
    # problem. 
    print ("Error code: %s" % e.code) 

Si marca esto con algo como la red Wireshark protocolo analazer, se puede ver que en realidad está enviando una petición HEAD, en lugar de un GET.

Esta es la petición HTTP y la respuesta desde el código anterior, como capturados por Wireshark:

CABEZA/doFeT HTTP/1.1
Accept-Encoding: identidad
Host: bit.ly
Connection: close
User-Agent: Python-urllib/2.7

HTTP/1.1 301 Moved
Servidor: nginx
Fecha: Dom 19 Feb 2012 13:20:56 GMT
Content-Type: text/html; charset = utf-8
Control de caché: privado; max-edad = 90
Lugar: http://www.kidsidebyside.org/?p=445
MIME-Version: 1.0
Content-Length: 127
Connection: close
Set-Cookie: _bit = 4f40f738-00153-02ed0-421cf10a; domain = .bit.ly; expira = vie 17 de agosto 13:20:56 2012; path = /; HttpOnly

Sin embargo, como se menciona en uno de los comentarios en la otra pregunta, si la URL en cuestión incluye una redirección a continuación urllib2 hacer una solicitud GET para el destino, no una cabeza. Esto podría ser una deficiencia importante, si realmente quisiera hacer solo solicitudes HEAD.

La solicitud anterior implica un redireccionamiento. Aquí está la solicitud al destino, como se recoge en Wireshark:

GET/2009/05/come-and-sorteo-del-circulo-de-unidad-con-nosotros/HTTP/1.1
Accept-Encoding : identidad
anfitrión: www.kidsidebyside.org
Connection: close
User-Agent: Pitón-urllib/2,7

Una alternativa al uso urllib2 es utilizar httplib2 biblioteca de Joe Gregorio:

import httplib2 

url = "http://bit.ly/doFeT" 
http_interface = httplib2.Http() 

try: 
    response, content = http_interface.request(url, method="HEAD") 
    print ("Response status: %d - %s" % (response.status, response.reason)) 

    # This will just display all the dictionary key-value pairs. Replace this 
    # line with something useful. 
    response.__dict__ 

except httplib2.ServerNotFoundError, e: 
    print (e.message) 

Tiene la ventaja de usar solicitudes HEAD tanto para la solicitud HTTP inicial como para la solicitud redirigida a la URL de destino.

Aquí está la primera solicitud:

CABEZA/doFeT HTTP/1.1
Host: bit.ly
Accept-Encoding:
de agente de usuario gzip, desinflar: Python-httplib2/0.7.2 (gzip)

Aquí está la segunda petición, al destino:

CABEZA/2009/05/come-and-sorteo-la -círculo-de-unidad-con-nosotros/HTTP/1.1
Host: www.kidsidebyside.org
Accept-Encoding: gzip, desinflar
de agente de usuario: Python-httplib2/0.7.2 (gzip)

+0

Me lo perdí la primera vez que leí la respuesta, pero 'response.info(). dict' es exactamente lo que estaba buscando. Esto * no * se explica [en los documentos] (https://docs.python.org/2.6/library/mimetools.html#mimetools.Message). – Coderer

5

de una sola línea:

$ python -c "import urllib2; print urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)).open(urllib2.Request('http://google.com'))" 
-1
def _GetHtmlPage(self, addr): 
    headers = { 'User-Agent' : self.userAgent, 
      ' Cookie' : self.cookies} 

    req = urllib2.Request(addr) 
    response = urllib2.urlopen(req) 

    print "ResponseInfo=" 
    print response.info() 

    resultsHtml = unicode(response.read(), self.encoding) 
    return resultsHtml 
Cuestiones relacionadas