Як надіслати 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
ця відповідь позначена як відповідь, але слід подивитися на область запитів . Подивіться на реакцію Даліуса, яка трохи нижче.
Bahadir Cambel

Це дійсно приємно, але для цього потрібно мати окремі значення для хоста та шляху запиту. Це корисно мати urlparseпід рукою, про що свідчать деякі відповіді нижчого рангу.
Томаш Гандор

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 у пункті призначення, а не на голову ...
eichin

1
У цьому перевага httplib.HTTPConnection, що не обробляє переадресацію автоматично.
Ehtesh Choudhury

але з відповіддю Дошеї. як встановити тайм-аут? Як поводитися з поганими URL-адресами, тобто з URL-адресами, які вже не існують.
фанчина

65

Обов’язковий Requestsспосіб:

import requests

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

36

Я вважаю, що слід також згадати бібліотеку запитів .


5
Ця відповідь заслуговує більшої уваги. Виглядає досить непогана бібліотека, яка робить проблему тривіальною.
Нік Реталак

3
Я погоджуюсь, що робити запити було дуже просто: {code} імпорт запитів r = questions.head (' github.com' ) {code}
Луїс Р.

@LuisR .: якщо є переадресація, це також слід GET / POST / PUT / DELETE.
jfs

@ Nick Retallack: не існує простого способу відключити переадресацію. allow_redirectsможе вимкнути лише переадресації POST / PUT / DELETE. Приклад: головний запит без переадресації
jfs

@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. (Viz, це буде працювати, але це поганий стиль, і якщо ви хотіли використовувати selfйого в ньому - жорстко.)
Кріс Морган

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

Ця друга версія в цьому коді є єдиною, яка працювала для мене за URL-адресою із забороненою 403. Інші кидали виняток.
подвійність_

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-адресами на стороні введення.
Томаш Гандор

1

Крім того, при використанні httplib (принаймні на 2.5.2) спроба прочитати відповідь на запит HEAD заблокується (у режимі повторного запису) і згодом не вдасться. Якщо ви не видали прочитання у відповіді, ви не можете надіслати ще один запит на з'єднання, вам потрібно буде відкрити новий. Або прийміть велику затримку між запитами.


1

Я виявив, що httplib трохи швидше urllib2. Я приурочив дві програми - одну, що використовує httplib, а іншу urllib2 - надсилання запитів HEAD до 10 000 URL-адрес. Режим httplib був швидшим на кілька хвилин. HTTPLIB «s загальна статистика була: реальна 6m21.334s користувача 0m2.124s SYS 0m16.372s

І urllib2 «s загальна статистика була: реальна 9m1.380s користувача 0m16.666s SYS 0m28.565s

Хтось ще має внесок у це?


Вхід? Проблема пов'язана з IO, і ви використовуєте блокування бібліотек. Перейдіть на eventlet або кручений, якщо хочете покращити продуктивність. Обмеження 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. Можливо, афіша не хоче отримати дорогий документ.
Філіп Ф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.