2009-05-09 36 views
41

urllib2 tìm nạp toàn bộ trang khi cuộc gọi urlopen được thực hiện không?Python: Nhận tiêu đề HTTP từ cuộc gọi urllib2.urlopen?

Tôi muốn đọc tiêu đề phản hồi HTTP mà không nhận được trang. Có vẻ như urllib2 mở kết nối HTTP và sau đó nhận được trang HTML thực tế ... hoặc nó chỉ bắt đầu đệm trang bằng lệnh gọi 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 

Trả lời

42

Sử dụng phương thức response.info() để nhận tiêu đề.

Từ urllib2 docs:

urllib2.urlopen (url [, dữ liệu] [, timeout])

...

Hàm này trả về một đối tượng tập tin giống như với hai thêm phương pháp:

  • geturl() - trả về URL của tài nguyên được truy xuất, thường được sử dụng để xác định xem chuyển hướng có được theo dõi không
  • thông tin() - trả lại meta-thông tin của trang, như tiêu đề, dưới hình thức của một thể hiện httplib.HTTPMessage (xem tham khảo nhanh để HTTP Headers)

Vì vậy, ví dụ bạn , thử bước qua kết quả của response.info().headers cho những gì bạn đang tìm kiếm.

Lưu ý cảnh báo chính khi sử dụng httplib.HTTPMessage được ghi lại trong python issue 4773.

+17

*** Python 3 Lưu ý *** Đầu tiên, không có gì giống như 'response.info(). Headers', làm một' dict (response.info()) '. Thứ hai, cho mã trạng thái HTTP làm 'response.status'. – treecoder

+1

Điều này ** chỉ được ** tiêu đề hoặc ** chỉ in ** tiêu đề? –

+2

Tài liệu 'tiêu đề' ở đâu? Cũng xem xét việc sử dụng 'response.info(). Items()' trả về giá trị khóa dict. –

40

Còn việc gửi yêu cầu HEAD thay vì yêu cầu GET bình thường. Sau đây bị cắt (sao chép từ một question tương tự) thực hiện chính xác điều đó.

>>> 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')] 
+2

tôi nghĩ rằng sẽ làm điều đó! – shigeta

8

urllib2.urlopen làm một HTTP GET (hoặc POST nếu bạn cung cấp một cuộc tranh luận dữ liệu), không phải là một TRỤ HTTP (nếu nó đã làm sau này, bạn không thể làm readlines hoặc khác truy cập vào cơ thể Trang, tất nhiên).

+0

oh thanks - câu trả lời cho câu hỏi – shigeta

20

Thực ra, có vẻ như urllib2 có thể thực hiện yêu cầu HEAD HTTP.

Số question mà @reto liên kết đến ở trên, cho biết cách nhận urllib2 thực hiện yêu cầu HEAD.

Dưới đây là quan điểm của tôi về nó:

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) 

Nếu bạn kiểm tra điều này với một cái gì đó giống như mạng Wireshark giao thức analazer, bạn có thể thấy rằng nó thực sự là gửi đi một yêu cầu HEAD, chứ không phải là một GET.

Đây là yêu cầu HTTP và phản hồi từ các mã trên, như bắt bởi Wireshark:

HEAD/doFeT HTTP/1.1
Accept-Encoding: sắc
Host: bit.ly
kết nối: gần
Tác nhân người dùng: Python-urllib/2.7

HTTP/1.1 301 Moved
Server: nginx
Ngày: Chủ nhật, 19 tháng 2 năm 2012 13:20:56 GMT
Content-Type: text/html; charset = utf-8
Kiểm soát bộ nhớ cache: riêng tư; max-age = 90
Location: http://www.kidsidebyside.org/?p=445
MIME-Version: 1.0
Content-Length: 127
kết nối: gần
Set-Cookie: _bit = 4f40f738-00153-02ed0-421cf10a; domain = .bit.ly; hết hạn = Thứ Sáu ngày 17 tháng 8 13:20:56 2012; đường dẫn = /; HttpOnly

Tuy nhiên, như được đề cập trong một trong các nhận xét trong câu hỏi khác, nếu URL được đề cập bao gồm chuyển hướng thì urllib2 sẽ thực hiện yêu cầu GET đến đích chứ không phải HEAD. Đây có thể là một thiếu sót lớn, nếu bạn thực sự muốn chỉ thực hiện các yêu cầu HEAD.

Yêu cầu ở trên bao gồm chuyển hướng. Đây là yêu cầu đến đích vì bị bắt bởi Wireshark:

GET/2009/05/đến-và-hòa-the-tròn-of-đoàn kết-với-us/HTTP/1.1
Accept-Encoding : bản sắc
host: www.kidsidebyside.org
kết nối: gần
User-Agent: Python-urllib/2,7

Một thay thế cho việc sử dụng urllib2 là sử dụng thư viện httplib2 Joe Gregorio:

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) 

Điều này có lợi thế là sử dụng các yêu cầu HEAD cho cả yêu cầu HTTP ban đầu và yêu cầu được chuyển hướng đến URL đích.

Dưới đây là yêu cầu đầu tiên:

HEAD/doFeT HTTP/1.1
Host: bit.ly
Accept-Encoding: gzip, deflate
user-agent: Python-httplib2/0.7.2 (gzip)

đây là yêu cầu thứ hai, đến đích:

HEAD/2009/05/đến-và-hòa-the -circle-of-đoàn kết-với-us/HTTP/1.1
Host: www.kidsidebyside.org
Accept-Encoding: gzip, deflate
user-agent: Python-httplib2/0.7.2 (gzip)

+0

Tôi đã bỏ lỡ nó lần đầu tiên tôi đọc câu trả lời, nhưng 'response.info(). dict' là chính xác những gì tôi đang tìm kiếm. Đây là * không * giải thích [trong tài liệu] (https://docs.python.org/2.6/library/mimetools.html#mimetools.Message). – Coderer

5

One-liner:

$ python -c "import urllib2; print urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)).open(urllib2.Request('http://google.com'))" 
-1
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 
Các vấn đề liên quan