Python: Получить HTTP-заголовки от вызова urllib2.urlopen? - PullRequest
46 голосов
/ 09 мая 2009

Получает ли urllib2 всю страницу при вызове urlopen?

Я хотел бы просто прочитать заголовок ответа HTTP, не получая страницу. Похоже, urllib2 открывает HTTP-соединение, а затем получает реальную HTML-страницу ... или он просто начинает буферизовать страницу с помощью вызова 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

Ответы [ 6 ]

48 голосов
/ 29 октября 2009

Используйте метод response.info() для получения заголовков.

Из документов urllib2 :

urllib2.urlopen (url [, данные] [, тайм-аут])

...

Эта функция возвращает файловый объект с двумя дополнительными методами:

  • geturl () - возвращает URL-адрес полученного ресурса, обычно используемого для определения того, был ли выполнен редирект
  • info () - возвращает метаинформацию страницы, такую ​​как заголовки, в форме экземпляра httplib.HTTPMessage (см. Краткий справочник по заголовкам HTTP)

Итак, для вашего примера попробуйте пошагово просмотреть результат response.info().headers для того, что вы ищете.

Обратите внимание, что основное предупреждение при использовании httplib.HTTPMessage описано в выпуске python 4773 .

40 голосов
/ 09 мая 2009

Как насчет отправки запроса HEAD вместо обычного запроса GET. Следующий фрагмент (скопированный из аналогичного вопроса ) делает именно это.

>>> 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')]
20 голосов
/ 19 февраля 2012

На самом деле, похоже, что urllib2 может выполнить HTTP-запрос HEAD.

Вопрос , на который @reto ссылается выше, показывает, как заставить urllib2 выполнить запрос HEAD.

Вот мое мнение:

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)

Если вы проверите это с помощью анализатора сетевого протокола Wireshark, вы увидите, что он фактически отправляет запрос HEAD, а не GET.

Это HTTP-запрос и ответ из приведенного выше кода, записанные Wireshark:

HEAD / doFeT HTTP / 1.1
Accept-Encoding: идентификация
Хост: bit.ly
Подключение: закрыть
Пользователь-агент: Python-urllib / 2.7

HTTP / 1.1 301 Перемещено
Сервер: nginx
Дата: воскресенье, 19 февраля 2012 г. 13:20:56 GMT
Content-Type: text / html; кодировка = UTF-8
Кэш-контроль: частный; max-age = 90
Расположение: http://www.kidsidebyside.org/?p=445
MIME-версия: 1.0
Длина содержимого: 127
Соединение: закрыть
Установить-Cookie: _bit = 4f40f738-00153-02ed0-421cf10a; домен = .bit.ly; срок действия истекает пт 17 августа 13:20:56 2012; путь = /; HttpOnly

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

Запрос выше включает перенаправление. Вот запрос к месту назначения, зафиксированный Wireshark:

GET / 2009/05 / Приди и нарисуй круг единства с нами / HTTP / 1.1
Accept-Encoding: личность
Хост: www.kidsidebyside.org
Подключение: закрыть
Пользователь-агент: Python-urllib / 2.7

Альтернативой использованию urllib2 является использование библиотеки httplib2 Джо Грегорио:

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)

Преимущество этого заключается в использовании запросов HEAD как для первоначального HTTP-запроса, так и для перенаправленного запроса на целевой URL.

Вот первый запрос:

HEAD / doFeT HTTP / 1.1
Хост: bit.ly
принять кодировку: gzip, deflate
user-agent: Python-httplib2 / 0.7.2 (gzip)

Вот второй запрос к месту назначения:

HEAD / 2009/05 / Приди и нарисуй круг единства с нами / HTTP / 1.1
Хост: www.kidsidebyside.org
принять кодировку: gzip, deflate
user-agent: Python-httplib2 / 0.7.2 (gzip)

8 голосов
/ 09 мая 2009

urllib2.urlopen выполняет HTTP GET (или POST, если вы предоставляете аргумент данных), а не HTTP HEAD (если это было последним, вы, конечно, не могли бы выполнять readlines или другие обращения к телу страницы).

5 голосов
/ 30 марта 2012

One-вкладыш:

$ python -c "import urllib2; print urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)).open(urllib2.Request('http://google.com'))"
0 голосов
/ 28 июля 2014
def _GetHtmlPage(self, addr):
  headers = { 'User-Agent' : self.userAgent,
            '  Cookie' : self.cookies}

  req = urllib2.Request(addr)
  response = urllib2.urlopen(req)

  print "ResponseInfo="
  print response.info()

  resultsHtml = unicode(response.read(), self.encoding)
  return resultsHtml  
...