web-dev-qa-db-fra.com

Python: obtenir des en-têtes HTTP à partir de l'appel urllib2.urlopen?

Est-ce que urllib2 récupérer la page entière lors d'un appel urlopen?

Je voudrais simplement lire l'en-tête de réponse HTTP sans obtenir la page. Ça ressemble à urllib2 ouvre la connexion HTTP et obtient ensuite la page HTML réelle ... ou commence-t-elle simplement à mettre la page en mémoire tampon avec l'appel 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
46
shigeta

Utilisez la méthode response.info() pour obtenir les en-têtes.

Depuis les documents urllib2 :

urllib2.urlopen (url [ data] [ timeout])

...

Cette fonction renvoie un objet de type fichier avec deux méthodes supplémentaires:

  • geturl () - retourne l'URL de la ressource récupérée, couramment utilisée pour déterminer si une redirection a été suivie
  • info () - retourne les méta-informations de la page, telles que les en-têtes, sous la forme d'une instance httplib.HTTPMessage (voir Référence rapide aux en-têtes HTTP)

Donc, pour votre exemple, essayez de parcourir le résultat de response.info().headers pour ce que vous recherchez.

Notez la mise en garde majeure concernant l'utilisation de httplib.HTTPMessage est documentée dans problème python 477 .

48
tolmeda

Qu'en est-il de l'envoi d'une demande HEAD au lieu d'une demande GET normale. Les extraits suivants (copiés à partir d'une --- question ) similaire font exactement cela.

>>> 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')]
40
reto

En fait, il semble que urllib2 puisse faire une requête HTTP HEAD.

La question à laquelle @reto est liée, ci-dessus, montre comment demander à urllib2 de faire une requête HEAD.

Voici mon point de vue:

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 vous vérifiez cela avec quelque chose comme l'analazer du protocole réseau Wireshark, vous pouvez voir qu'il envoie en fait une demande HEAD, plutôt qu'un GET.

Il s'agit de la demande HTTP et de la réponse du code ci-dessus, telles que capturées par Wireshark:

HEAD/doFeT HTTP/1.1
Accept-Encoding: identité
Hôte: bit.ly
Connexion: fermer
User-Agent: Python-urllib/2.7

HTTP/1.1 301 déplacé
Serveur: nginx
Date: dimanche 19 février 2012 13:20:56 GMT
Type de contenu: texte/html; charset = utf-8
Cache-control: privé; âge max = 90
Emplacement: http://www.kidsidebyside.org/?p=445
Version MIME: 1.0
Longueur du contenu: 127
Connexion: fermer
Set-Cookie: _bit = 4f40f738-00153-02ed0-421cf10a; domain = .bit.ly; expire = ven 17 août 13:20:56 2012; path = /; HttpOnly

Cependant, comme mentionné dans l'un des commentaires de l'autre question, si l'URL en question comprend une redirection, alors urllib2 fera une demande GET vers la destination, pas une HEAD. Cela pourrait être une lacune majeure, si vous vouliez vraiment faire uniquement des requêtes HEAD.

La demande ci-dessus implique une redirection. Voici la demande vers la destination, telle que capturée par Wireshark:

GET/2009/05/venez dessiner le cercle de l'unité avec nous/HTTP/1.1
Accept-Encoding: identité
Hôte: www.kidsidebyside.org
Connexion: fermer
User-Agent: Python-urllib/2.7

Une alternative à l'utilisation de urllib2 est d'utiliser la bibliothèque httplib2 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)

Cela présente l'avantage d'utiliser HEAD requêtes pour la requête HTTP initiale et la requête redirigée vers l'URL de destination.

Voici la première demande:

HEAD/doFeT HTTP/1.1
Hôte: bit.ly
accept-encoding: gzip, dégonfler
user-agent: Python-httplib2/0.7.2 (gzip)

Voici la deuxième demande, à destination:

HEAD/2009/05/venez dessiner le cercle de l'unité avec nous/HTTP/1.1
Hôte: www.kidsidebyside.org
accept-encoding: gzip, dégonfler
user-agent: Python-httplib2/0.7.2 (gzip)

20
Simon Tewsi

urllib2.urlopen fait un HTTP GET (ou POST si vous fournissez un argument de données), pas un HTTP HEAD (s'il a fait ce dernier, vous ne pourriez pas ' t faire des lignes de lecture ou d'autres accès au corps de la page, bien sûr).

8
Alex Martelli

Bon mot:

$ python -c "import urllib2; print urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)).open(urllib2.Request('http://google.com'))"
5
quanta