Як надіслати 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.