Có cách nào dễ dàng để yêu cầu một URL trong python và KHÔNG làm theo chuyển hướng không?


96

Nhìn vào nguồn của urllib2, có vẻ như cách dễ nhất để làm điều đó là phân lớp HTTPRedirectHandler và sau đó sử dụng build_opener để ghi đè HTTPRedirectHandler mặc định, nhưng điều này có vẻ như rất nhiều công việc (tương đối phức tạp) để thực hiện những gì có vẻ như khá đơn giản.


2
Đối với nhân viên google: sử dụng thư viện yêu cầu sẽ giúp bạn đỡ đau đầu: docs.python-requests.org và xem câu trả lời của Marian bên dưới, nó rất thanh lịch.
Alojz Janez

Tôi đồng ý rằng yêu cầu là cách để thực hiện những ngày này. Tôi đã tán thành bình luận này và câu trả lời của Marian nhưng tôi vẫn để lại câu trả lời như được trao vì nó là câu trả lời hay nhất vào thời điểm đó.
John

1
Giải thưởng @John là tốt nhưng thời gian vẫn trôi qua và đây là trang do cộng đồng chỉnh sửa. Trọng tâm là câu trả lời tốt chứ không phải con người. Anh ấy sẽ giữ số điểm ủng hộ của mình. Bạn đang đánh lạc hướng hàng tấn người viết mã thành các thư viện không dùng nữa.
mit

1
Được rồi. Tôi đã chấp nhận câu trả lời yêu cầu.
John

Câu trả lời:


180

Đây là cách Yêu cầu :

import requests
r = requests.get('http://github.com', allow_redirects=False)
print(r.status_code, r.headers['Location'])

5
Sau đó nhìn vào r.headers['Location']để xem nơi nó sẽ gửi cho bạn
patricksurry

Lưu ý rằng có vẻ như Yêu cầu sẽ bình thường hóa Locationthành location.
Hamish

2
@Hamish requestscho phép bạn truy cập các tiêu đề cả ở dạng chuẩn và chữ thường. Xem docs.python-requests.org/en/master/user/quickstart/…
Marian

1
Kể từ năm 2019 trong Python 3, điều này dường như không còn hoạt động với tôi nữa. (Tôi gặp lỗi chính tả.)
Max von Hippel

35

Dive Into Python có một chương hay về xử lý chuyển hướng với urllib2. Một giải pháp khác là httplib .

>>> import httplib
>>> conn = httplib.HTTPConnection("www.bogosoft.com")
>>> conn.request("GET", "")
>>> r1 = conn.getresponse()
>>> print r1.status, r1.reason
301 Moved Permanently
>>> print r1.getheader('Location')
http://www.bogosoft.com/new/location

7
Mọi người đến đây từ google, xin lưu ý rằng cách cập nhật để đi là cái này: stackoverflow.com/a/14678220/362951 Thư viện yêu cầu sẽ giúp bạn đỡ đau đầu.
mit

Liên kết đến "Dive Into Python" đã chết.
guettli

11

Đây là một trình xử lý urllib2 sẽ không tuân theo các chuyển hướng:

class NoRedirectHandler(urllib2.HTTPRedirectHandler):
    def http_error_302(self, req, fp, code, msg, headers):
        infourl = urllib.addinfourl(fp, headers, req.get_full_url())
        infourl.status = code
        infourl.code = code
        return infourl
    http_error_300 = http_error_302
    http_error_301 = http_error_302
    http_error_303 = http_error_302
    http_error_307 = http_error_302

opener = urllib2.build_opener(NoRedirectHandler())
urllib2.install_opener(opener)

Tôi là đơn vị đang thử nghiệm một API và xử lý phương thức đăng nhập chuyển hướng đến một trang mà tôi không quan tâm, nhưng không gửi cookie phiên mong muốn cùng với phản hồi cho chuyển hướng. Đây chính xác là những gì tôi cần cho điều đó.
Tim Wilder

9

Các redirectionstừ khóa trong các httplib2phương thức yêu cầu là một cá trích đỏ. Thay vì trả lại yêu cầu đầu tiên, nó sẽ đưa ra một RedirectLimitngoại lệ nếu nó nhận được mã trạng thái chuyển hướng. Để trở về phản ứng inital bạn cần phải thiết lập follow_redirectsđể Falsetrên Httpđối tượng:

import httplib2
h = httplib2.Http()
h.follow_redirects = False
(response, body) = h.request("http://example.com")

8

tôi cho rằng điều này sẽ giúp ích

from httplib2 import Http
def get_html(uri,num_redirections=0): # put it as 0 for not to follow redirects
conn = Http()
return conn.request(uri,redirections=num_redirections)

5

Thứ hai tôi sẽ chỉ ra con trỏ để Đi sâu vào Python . Đây là một triển khai bằng cách sử dụng trình xử lý chuyển hướng urllib2, nhiều công việc hơn mức cần thiết? Có thể, nhún vai.

import sys
import urllib2

class RedirectHandler(urllib2.HTTPRedirectHandler):
    def http_error_301(self, req, fp, code, msg, headers):  
        result = urllib2.HTTPRedirectHandler.http_error_301( 
            self, req, fp, code, msg, headers)              
        result.status = code                                 
        raise Exception("Permanent Redirect: %s" % 301)

    def http_error_302(self, req, fp, code, msg, headers):
        result = urllib2.HTTPRedirectHandler.http_error_302(
            self, req, fp, code, msg, headers)              
        result.status = code                                
        raise Exception("Temporary Redirect: %s" % 302)

def main(script_name, url):
   opener = urllib2.build_opener(RedirectHandler)
   urllib2.install_opener(opener)
   print urllib2.urlopen(url).read()

if __name__ == "__main__":
    main(*sys.argv) 

3
Vẻ sai ... Mã này thực sự theo chuyển hướng (bằng cách gọi handler gốc, do đó phát hành một yêu cầu HTTP), và sau đó nâng cao một ngoại lệ
Carles Barrobés

5

Tuy nhiên, con đường ngắn nhất là

class NoRedirect(urllib2.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, hdrs, newurl):
        pass

noredir_opener = urllib2.build_opener(NoRedirect())

1
Làm thế nào đây là con đường ngắn nhất? Nó thậm chí không chứa nhập hoặc yêu cầu thực tế.
Marian

Tôi đã định đăng giải pháp này và khá ngạc nhiên khi tìm thấy câu trả lời này ở phía dưới. Nó rất ngắn gọn và nên là câu trả lời hàng đầu theo quan điểm của tôi.
người dùng

Hơn nữa, nó mang lại cho bạn nhiều tự do hơn, bằng cách này, bạn có thể kiểm soát những URL nào cần tuân theo .
người dùng

Tôi xác nhận, đây là cách phục hưng. Một nhận xét ngắn cho những người muốn gỡ lỗi. Đừng quên rằng bạn có thể đặt các bộ xử lý bội số khi đấu giá bộ mở như: opener = urllib.request.build_opener(debugHandler, NoRedirect())ở đâu debugHandler=urllib.request.HTTPHandler()debugHandler.set_http_debuglevel (1). Cuối cùng:urllib.request.install_opener(opener)
StashOfCode
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.