Como você envia uma solicitação HEAD HTTP no Python 2?


114

O que estou tentando fazer aqui é obter os cabeçalhos de um determinado URL para determinar o tipo de MIME. Eu quero ser capaz de ver se http://somedomain/foo/retornarei um documento HTML ou uma imagem JPEG, por exemplo. Portanto, preciso descobrir como enviar uma solicitação HEAD para poder ler o tipo MIME sem ter que baixar o conteúdo. Alguém conhece uma maneira fácil de fazer isso?

Respostas:


104

editar : Esta resposta funciona, mas hoje em dia você deve apenas usar a biblioteca de solicitações conforme mencionado nas outras respostas abaixo.


Use httplib .

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

Também existe um getheader(name)para obter um cabeçalho específico.


2
esta resposta foi marcada como respondida, mas deve-se olhar para a biblioteca de solicitações . Veja a resposta de Dalius um pouco abaixo.
Bahadir Cambel

Isso é muito bom, mas requer que você tenha valores separados para o host e o caminho da solicitação. É útil ter urlparseà mão, o que é mostrado por algumas respostas de classificação inferior.
Tomasz Gandor

7
Nota para Python 3; httplibfoi renomeado para http.client.
Santosh Kumar

2
Infelizmente, requestsnão é fornecido com Python por padrão.
torre

@rook também não é o seu programa :)
Eevee

109

urllib2 pode ser usado para executar uma solicitação HEAD. Isso é um pouco melhor do que usar o httplib, já que o urllib2 analisa a URL para você em vez de exigir que você divida a URL em nome de host e caminho.

>>> import urllib2
>>> class HeadRequest(urllib2.Request):
...     def get_method(self):
...         return "HEAD"
... 
>>> response = urllib2.urlopen(HeadRequest("http://google.com/index.html"))

Os cabeçalhos estão disponíveis via response.info () como antes. Curiosamente, você pode encontrar o URL para o qual foi redirecionado:

>>> print response.geturl()
http://www.google.com.au/index.html

1
response.info () .__ str __ () retornará o formato de string do cabeçalho, caso você queira fazer algo com o resultado obtido.
Shane,

6
exceto que tentar isso com python 2.7.1 (ubuntu natty), se houver um redirecionamento, ele faz um GET no destino, não um HEAD ...
eichin

1
Essa é a vantagem do httplib.HTTPConnection, que não controla os redirecionamentos automaticamente.
Ehtesh Choudhury

mas com a resposta de Doshea. como definir o tempo limite? Como lidar com URLs ruins, ou seja, URLs que não estão mais vivos.
fanchyna de

65

RequestsForma obrigatória :

import requests

resp = requests.head("http://www.google.com")
print resp.status_code, resp.text, resp.headers

36

Eu acredito que a biblioteca Requests deve ser mencionada também.


5
Essa resposta merece mais atenção. Parece uma biblioteca muito boa que torna o problema trivial.
Nick Retallack

3
Concordo. Era muito simples fazer solicitações: {code} import requests r = requests.head (' github.com' ) {code}
Luis R.

@LuisR .: se houver um redirecionamento, ele também seguirá GET / POST / PUT / DELETE.
jfs de

@Nick Retallack: não há uma maneira fácil de desabilitar redirecionamentos. allow_redirectspode desativar apenas redirecionamentos POST / PUT / DELETE. Exemplo: solicitação principal sem redirecionamento
jfs de

@JFSebastian O link para o seu exemplo parece estar quebrado. Você poderia explicar o problema dos redirecionamentos a seguir?
Piotr Dobrogost

17

Somente:

import urllib2
request = urllib2.Request('http://localhost:8080')
request.get_method = lambda : 'HEAD'

response = urllib2.urlopen(request)
response.info().gettype()

Edit: Acabei de perceber que existe httplib2: D

import httplib2
h = httplib2.Http()
resp = h.request("http://www.google.com", 'HEAD')
assert resp[0]['status'] == 200
assert resp[0]['content-type'] == 'text/html'
...

Texto do link


Um pouco desagradável porque você está deixando get_method como uma função não vinculada em vez de vinculá-la a request. (Viz, vai funcionar, mas é um estilo ruim e se você quiser usar selfnele - difícil.)
Chris Morgan

4
Você poderia elaborar um pouco mais sobre os prós e os contras dessa solução? Não sou um especialista em Python, como você pode ver, então poderia me beneficiar sabendo quando ele pode ficar ruim;) Pelo que eu entendo, a preocupação é que é um hack que pode ou não funcionar dependendo da mudança na implementação.
Paweł Prażak

Esta segunda versão neste código é a única que funcionou para mim para um URL com 403 Forbidden. Outros estavam lançando uma exceção.
dualidade_

10

Para ser completo, tenha uma resposta Python3 equivalente à resposta aceita usando httplib .

É basicamente o mesmo código, só que a biblioteca não é mais chamada de httplib, mas de http.client

from http.client import HTTPConnection

conn = HTTPConnection('www.google.com')
conn.request('HEAD', '/index.html')
res = conn.getresponse()

print(res.status, res.reason)

2
import httplib
import urlparse

def unshorten_url(url):
    parsed = urlparse.urlparse(url)
    h = httplib.HTTPConnection(parsed.netloc)
    h.request('HEAD', parsed.path)
    response = h.getresponse()
    if response.status/100 == 3 and response.getheader('Location'):
        return response.getheader('Location')
    else:
        return url

Quais são os cifrões antes import? +1 para o urlparse- junto com httplibeles fornecem o conforto de urllib2, ao lidar com URLs no lado da entrada.
Tomasz Gandor

1

Como um aparte, ao usar o httplib (pelo menos em 2.5.2), tentar ler a resposta de uma solicitação HEAD irá bloquear (em readline) e subsequentemente falhar. Se você não emitir ler na resposta, você não conseguirá enviar outra solicitação na conexão, você precisará abrir uma nova. Ou aceite um longo atraso entre os pedidos.


1

Eu descobri que o httplib é um pouco mais rápido que o urllib2. Cronometrei dois programas - um usando httplib e outro usando urllib2 - enviando solicitações HEAD para 10.000 URLs. O httplib foi mais rápido por vários minutos. As estatísticas totais de httplib foram: real 6m21.334s usuário 0m2.124s sys 0m16.372s

E as estatísticas totais do urllib2 foram: real 9m1.380s usuário 0m16.666s sys 0m28.565s

Alguém mais tem opinião sobre isso?


Entrada? O problema é vinculado ao IO e você está usando bibliotecas de bloqueio. Mude para eventlet ou twisted se quiser melhor desempenho. As limitações do urllib2 que você menciona são vinculadas à CPU.
Devin Jeanpierre

3
urllib2 segue redirecionamentos, portanto, se algum de seus URLs redirecionar, provavelmente esse será o motivo da diferença. E ,httplib é mais de baixo nível, urllib2 analisa o url, por exemplo.
Marian

1
urllib2 é apenas uma camada fina de abstração sobre o httplib. Eu ficaria muito surpreso se você estivesse vinculado à CPU, a menos que os urls estejam em uma LAN muito rápida. É possível que alguns dos URLs tenham sido redirecionados? urllib2 seguirá os redirecionamentos, ao passo que httplib não. A outra possibilidade é que as condições da rede (qualquer coisa que você não tenha controle explícito neste experimento) flutuaram entre as 2 execuções. você deve fazer pelo menos 3 execuções intercaladas de cada para reduzir essa probabilidade
John La Rooy

0

E ainda outra abordagem (semelhante à resposta de Pawel):

import urllib2
import types

request = urllib2.Request('http://localhost:8080')
request.get_method = types.MethodType(lambda self: 'HEAD', request, request.__class__)

Apenas para evitar métodos ilimitados no nível da instância.


-4

Provavelmente mais fácil: use urllib ou urllib2.

>>> import urllib
>>> f = urllib.urlopen('http://google.com')
>>> f.info().gettype()
'text/html'

f.info () é um objeto semelhante a um dicionário, então você pode fazer f.info () ['content-type'], etc.

http://docs.python.org/library/urllib.html
http://docs.python.org/library/urllib2.html
http://docs.python.org/library/httplib.html

Os documentos observam que httplib normalmente não é usado diretamente.


14
No entanto, o urllib fará um GET e a questão é sobre como realizar um HEAD. Talvez o autor da postagem não queira recuperar um documento caro.
Philippe F
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.