Làm cách nào để bạn gửi một yêu cầu HEAD HTTP trong Python 2?


114

Những gì tôi đang cố gắng làm ở đây là lấy tiêu đề của một URL nhất định để tôi có thể xác định kiểu MIME. Tôi muốn xem liệu http://somedomain/foo/sẽ trả về tài liệu HTML hay hình ảnh JPEG chẳng hạn. Do đó, tôi cần tìm ra cách gửi yêu cầu HEAD để tôi có thể đọc kiểu MIME mà không cần phải tải xuống nội dung. Có ai biết một cách dễ dàng để làm điều này?

Câu trả lời:


104

chỉnh sửa : Câu trả lời này hoạt động, nhưng ngày nay bạn chỉ nên sử dụng thư viện yêu cầu như được đề cập trong các câu trả lời khác bên dưới.


Sử dụng 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')]

Ngoài ra còn getheader(name)có một tiêu đề cụ thể.


2
câu trả lời này được đánh dấu là đã trả lời nhưng người ta nên xem các yêu cầu lib. Hãy xem phản hồi của Dalius ở bên dưới.
Bahadir Cambel

Điều này thực sự tốt, nhưng nó yêu cầu bạn phải có các giá trị riêng biệt cho máy chủ và đường dẫn của yêu cầu. Thật hữu ích khi có urlparsetrong tay, điều này được thể hiện bằng một số phản hồi xếp hạng thấp hơn.
Tomasz Gandor

7
Lưu ý cho Python 3; httplibđược đổi tên thành http.client.
Santosh Kumar

2
Thật không may, requestskhông được vận chuyển với Python theo mặc định.
rook

@rook cũng không phải là chương trình của bạn :)
Eevee

109

urllib2 có thể được sử dụng để thực hiện yêu cầu HEAD. Điều này đẹp hơn một chút so với sử dụng httplib vì urllib2 phân tích URL cho bạn thay vì yêu cầu bạn chia URL thành tên máy chủ và đường dẫn.

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

Tiêu đề có sẵn thông qua response.info () như trước đây. Điều thú vị là bạn có thể tìm thấy URL mà bạn đã được chuyển hướng đến:

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

1
response.info () .__ str __ () sẽ trả về định dạng chuỗi của tiêu đề, trong trường hợp bạn muốn làm gì đó với kết quả bạn nhận được.
Shane

6
ngoại trừ việc cố gắng này với python 2.7.1 (Ubuntu Natty), nếu có một chuyển hướng, nó hoạt động GET trên đích, không phải là một ĐẦU ...
eichin

1
Đó là lợi thế của httplib.HTTPConnection, không tự động xử lý chuyển hướng.
Ehtesh Choudhury

nhưng với câu trả lời của doshea. làm thế nào để đặt thời gian chờ? Cách xử lý URL xấu, tức là URL không còn tồn tại.
fanchyna

65

RequestsCách bắt buộc :

import requests

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

36

Tôi tin rằng thư viện Yêu cầu cũng nên được đề cập.


5
Câu trả lời này đáng được quan tâm hơn. Có vẻ như một thư viện khá tốt khiến vấn đề trở nên tầm thường.
Nick Retallack

3
Tôi đồng ý Đó là rất đơn giản để thực hiện các yêu cầu: {code} yêu cầu nhập khẩu r = requests.head ( ' github.com' ) {code}
Luis R.

@LuisR .: nếu có chuyển hướng thì nó cũng theo sau GET / POST / PUT / DELETE.
jfs

@Nick Retallack: không có cách nào dễ dàng để tắt chuyển hướng. allow_redirectschỉ có thể tắt chuyển hướng POST / PUT / DELETE. Ví dụ: head request no redirect
jfs 10/02/12

@JFSebastian Liên kết đến ví dụ của bạn dường như đã bị hỏng. Bạn có thể giải thích thêm về vấn đề với các chuyển hướng sau không?
Piotr Dobrogost

17

Chỉ:

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

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

Chỉnh sửa: Tôi mới nhận ra có 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'
...

văn bản liên kết


Hơi khó chịu ở chỗ bạn đang để get_method như một hàm không liên kết thay vì ràng buộc nó với request. (Viz, nó sẽ hoạt động nhưng đó là phong cách tồi và nếu bạn muốn sử dụng selfnó - thật khó.)
Chris Morgan

4
Bạn có thể nói rõ hơn một chút về ưu và nhược điểm của giải pháp này? Tôi không phải là một chuyên gia Python như bạn có thể thấy, vì vậy tôi có thể có lợi khi biết khi nào nó có thể trở nên tồi tệ;) Như tôi hiểu, mối lo ngại là đó là một bản hack có thể hoạt động hoặc có thể không hoạt động tùy thuộc vào sự thay đổi triển khai?
Paweł Prażak

Phiên bản thứ hai trong mã này là phiên bản duy nhất phù hợp với tôi cho URL có 403 Forbidden. Những người khác đã ném một ngoại lệ.
lưỡng tính_

10

Để có một câu trả lời Python3 tương đương với câu trả lời được chấp nhận bằng cách sử dụng httplib .

Về cơ bản nó giống như một đoạn mã chỉ khác là thư viện không được gọi là httplib nữa mà là 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

Các ký hiệu đô la trước đây là importgì? +1 cho urlparse- cùng với httplibchúng mang lại sự thoải mái urllib2khi xử lý các URL ở phía đầu vào.
Tomasz Gandor

1

Ngoài ra, khi sử dụng httplib (ít nhất là trên 2.5.2), việc cố gắng đọc phản hồi của một yêu cầu HEAD sẽ chặn (trên dòng đọc) và sau đó không thành công. Nếu bạn không đặt vấn đề đọc trên phản hồi, bạn không thể gửi một yêu cầu khác trên kết nối, bạn sẽ cần phải mở một yêu cầu mới. Hoặc chấp nhận một thời gian dài giữa các lần yêu cầu.


1

Tôi nhận thấy rằng httplib nhanh hơn urllib2 một chút. Tôi hẹn giờ hai chương trình - một chương trình sử dụng httplib và chương trình kia sử dụng urllib2 - gửi yêu cầu HEAD đến 10.000 URL. Httplib nhanh hơn vài phút. httplibTổng số thống kê của là: 6m21.334s người dùng thực 0m2.124s sys 0m16.372s

Và tổng số liệu thống kê của urllib2 là: người dùng thực 9m1.380s 0m16.666s sys 0m28.565s

Có ai khác có đầu vào về điều này?


Đầu vào? Vấn đề là bị ràng buộc IO và bạn đang sử dụng các thư viện chặn. Chuyển sang eventlet hoặc xoắn nếu bạn muốn hiệu suất tốt hơn. Những hạn chế của urllib2 mà bạn đề cập là bị ràng buộc bởi CPU.
Devin Jeanpierre

3
urllib2 theo sau chuyển hướng, vì vậy nếu một số URL của bạn chuyển hướng, đó có thể là lý do cho sự khác biệt. Và, httplib ở mức thấp hơn, ví dụ như urllib2 phân tích cú pháp url.
Marian

1
urllib2 chỉ là một lớp trừu tượng mỏng trên đầu trang httplib, tôi sẽ rất ngạc nhiên nếu bạn bị ràng buộc về cpu trừ khi các url nằm trong một mạng LAN rất nhanh. Có thể một số url được chuyển hướng không? urllib2 sẽ đi theo các chuyển hướng trong khi httplib thì không. Khả năng khác là các điều kiện mạng (bất kỳ thứ gì bạn không có quyền kiểm soát rõ ràng trong thử nghiệm này) dao động giữa 2 lần chạy. bạn nên làm ít nhất 3 chạy xen kẽ từng để giảm mất ổn định này
John La Rooy

0

Và một cách tiếp cận khác (tương tự như câu trả lời Pawel):

import urllib2
import types

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

Chỉ để tránh có các phương thức không bị ràng buộc ở cấp cá thể.


-4

Có lẽ dễ dàng hơn: sử dụng urllib hoặc urllib2.

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

f.info () là một đối tượng giống như từ điển, vì vậy bạn có thể thực hiện f.info () ['content-type'], v.v.

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

Tài liệu lưu ý rằng httplib thường không được sử dụng trực tiếp.


14
Tuy nhiên, urllib sẽ thực hiện GET và câu hỏi là về việc thực hiện HEAD. Có thể người đăng không muốn lấy một tài liệu đắt tiền.
Philippe F
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.