Как отправить HTTP-запрос HEAD в Python 2?


114

Я пытаюсь получить заголовки данного URL-адреса, чтобы определить тип MIME. Я хочу увидеть http://somedomain/foo/, вернет ли, например, документ HTML или изображение JPEG. Таким образом, мне нужно выяснить, как отправить запрос HEAD, чтобы я мог читать тип MIME, не загружая контент. Кто-нибудь знает простой способ сделать это?

Ответы:


104

изменить : этот ответ работает, но в настоящее время вы должны просто использовать библиотеку запросов, как указано в других ответах ниже.


Используйте 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')]

Также есть getheader(name)возможность получить конкретный заголовок.


2
этот ответ помечен как отвеченный, но нужно посмотреть запросы lib. Посмотрите на ответ Далиуса, который находится чуть ниже.
Бахадир Камбель

Это действительно хорошо, но требует, чтобы у вас были отдельные значения для хоста и пути запроса. Полезно иметь urlparseпод рукой, о чем свидетельствует ответ более низкого ранга.
Tomasz Gandor

7
Примечание для Python 3; httplibпереименован в http.client.
Сантош Кумар

2
К сожалению, requestsпо умолчанию не поставляется с Python.
ладья

@rook тоже не твоя программа :)
Eevee

109

urllib2 может использоваться для выполнения запроса HEAD. Это немного лучше, чем использование httplib, поскольку urllib2 анализирует URL-адрес для вас, вместо того, чтобы требовать, чтобы вы разделяли URL-адрес на имя хоста и путь.

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

Заголовки, как и раньше, доступны через response.info (). Интересно, что вы можете найти URL-адрес, на который вы были перенаправлены:

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

1
response.info () .__ str __ () вернет строковый формат заголовка, если вы хотите что-то сделать с полученным результатом.
Шейн

6
за исключением того, что пытаюсь это сделать с помощью python 2.7.1 (ubuntu natty), если есть перенаправление, он выполняет GET в пункте назначения, а не в HEAD ...
eichin

1
Это преимущество httplib.HTTPConnection, которое не обрабатывает перенаправления автоматически.
Эхтеш Чоудхури,

но с ответом доши. как установить тайм-аут? Как обрабатывать неправильные URL-адреса, т. Е. URL-адреса, которых больше нет.
fanchyna

65

Обязательный Requestsспособ:

import requests

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

36

Я считаю, что следует упомянуть и библиотеку запросов .


5
Этот ответ заслуживает большего внимания. Похоже, неплохая библиотека, которая делает проблему тривиальной.
Ник Реталлак,

3
Я согласен. Делать запросы было очень просто: {code} запросы на импорт r = requests.head (' github.com' ) {code}
Луис Р.

@LuisR .: если есть перенаправление, то оно также следует за GET / POST / PUT / DELETE.
jfs

@Nick Retallack: нет простого способа отключить перенаправления. allow_redirectsможно отключить только перенаправления POST / PUT / DELETE. Пример: запрос
заголовка

@JFSebastian Ссылка на ваш пример вроде не работает. Не могли бы вы подробнее рассказать о проблеме со следующими переадресациями?
Петр Доброгост

17

Просто:

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

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

Изменить: я только что понял, что есть 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'
...

текст ссылки


Немного неприятно, потому что вы оставляете get_method как несвязанную функцию, а не привязываете ее к request. (То есть, это будет работать, но это плохой стиль, и если вы захотите использовать selfего - сложно.)
Крис Морган

4
Не могли бы вы подробнее рассказать о плюсах и минусах этого решения? Я не эксперт по Python, как вы можете видеть, поэтому мне было бы полезно знать, когда это может стать плохим;) Насколько я понимаю, проблема заключается в том, что это хак, который может или не может сработать в зависимости от изменения реализации?
Paweł Praak

Эта вторая версия в этом коде - единственная, которая работала у меня для URL-адреса с запрещенным кодом 403. Другие бросали исключение.
duality_

10

Для полноты, чтобы получить ответ Python3, эквивалентный принятому ответу с использованием httplib .

Это в основном тот же код, только библиотека больше не называется httplib , а 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

Какие знаки доллара были раньше import? +1 за urlparse- вместе с ними httplibдают удобство urllib2при работе с URL-адресами на стороне ввода.
Tomasz Gandor

1

Кстати, при использовании httplib (по крайней мере, в 2.5.2) попытка прочитать ответ на запрос HEAD будет блокироваться (в строке чтения) и впоследствии завершаться ошибкой. Если вы не выдадите read в ответе, вы не сможете отправить другой запрос на соединение, вам нужно будет открыть новый. Или согласитесь с большой задержкой между запросами.


1

Я обнаружил, что httplib немного быстрее urllib2. Я рассчитал время для двух программ - одна с использованием httplib, а другая с использованием urllib2 - отправка запросов HEAD на 10 000 URL-адресов. Httplib был быстрее на несколько минут. Общая статистика httplib была: real 6m21.334s user 0m2.124s sys 0m16.372s

И urllib2 «s общая статистика была: реальная 9m1.380s пользователя 0m16.666s SYS 0m28.565s

Кто-нибудь еще имеет мнение по этому поводу?


Вход? Проблема связана с вводом-выводом, и вы используете блокирующие библиотеки. Переключитесь на eventlet или twisted, если вам нужна лучшая производительность. Упомянутые вами ограничения urllib2 зависят от ЦП.
Девин Жанпьер,

3
urllib2 следует за перенаправлениями, поэтому если некоторые из ваших URL-адресов перенаправляют, это, вероятно, будет причиной разницы. И httplib более низкоуровневый, urllib2, например, анализирует URL-адрес.
Мариан

1
urllib2 - это просто тонкий слой абстракции поверх httplib, я был бы очень удивлен, если бы вы были привязаны к процессору, если URL-адреса не находятся в очень быстрой локальной сети. Возможно ли, что некоторые из URL-адресов были перенаправленными? urllib2 будет следовать перенаправлениям, а httplib - нет. Другая возможность заключается в том, что условия сети (все, что вы не можете явно контролировать в этом эксперименте) колебались между двумя запусками. вам следует сделать по крайней мере 3 чередующихся прогона каждого, чтобы уменьшить эту вероятность
Джон Ла Рой

0

И еще один подход (похожий на ответ Павла):

import urllib2
import types

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

Просто чтобы избежать неограниченных методов на уровне экземпляра.


-4

Наверное, проще: использовать urllib или urllib2.

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

f.info () - объект, подобный словарю, поэтому вы можете использовать f.info () ['content-type'] и т. д.

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

В документации отмечается, что httplib обычно не используется напрямую.


14
Однако urllib выполнит GET, и вопрос будет в выполнении HEAD. Возможно, плакат не хочет получать дорогой документ.
Philippe F,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.