มีวิธีง่ายๆในการขอ URL ใน python และไม่ติดตามการเปลี่ยนเส้นทางหรือไม่?


101

เมื่อดูที่มาของ urllib2 ดูเหมือนว่าวิธีที่ง่ายที่สุดในการทำคือซับคลาส HTTPRedirectHandler จากนั้นใช้ build_opener เพื่อแทนที่ HTTPRedirectHandler เริ่มต้น แต่ดูเหมือนว่าจะมีงาน (ค่อนข้างซับซ้อน) มากในการทำสิ่งที่ควรจะเป็น ค่อนข้างเรียบง่าย


2
สำหรับ googler: การใช้ไลบรารีคำขอจะช่วยให้คุณไม่ต้องปวดหัวได้มาก: docs.python-requests.orgและดูคำตอบของ Marian ด้านล่างนี้ถือว่าสวยงามมาก
Alojz Janez

ฉันยอมรับว่าคำขอคือหนทางที่จะดำเนินไปในทุกวันนี้ ฉันได้เพิ่มคะแนนความคิดเห็นนี้และคำตอบของ Marian แต่ฉันจะปล่อยให้คำตอบเป็นรางวัลเนื่องจากเป็นสิ่งที่ดีที่สุดในเวลานั้น
John

1
@John รางวัลเป็นสิ่งที่ดี แต่เวลาผ่านไปและนี่คือไซต์ที่แก้ไขโดยชุมชน มุ่งเน้นไปที่คำตอบที่ดีและไม่ได้อยู่ที่ประชาชน เขาจะรักษาคะแนนโหวตเพิ่ม คุณกำลังทำให้ผู้เขียนโค้ดหลายคนเข้าใจผิดในไลบรารีที่เลิกใช้แล้ว
mit

1
โอเคยุติธรรมพอ ฉันยอมรับคำตอบของคำขอแล้ว
จอห์น

คำตอบ:


186

นี่คือวิธีการร้องขอ :

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

6
จากนั้นr.headers['Location']ดูว่าจะส่งคุณไปที่ไหน
patricksurry

หมายเหตุว่ามันดูเหมือนว่าจะจองปกติไปLocation location
Hamish

2
@ Hamish requestsช่วยให้คุณเข้าถึงส่วนหัวทั้งในรูปแบบบัญญัติและตัวพิมพ์เล็ก ดูdocs.python-requests.org/en/master/user/quickstart/…
Marian

1
ตั้งแต่ปี 2019 ใน Python 3 ดูเหมือนว่าสิ่งนี้จะไม่ได้ผลสำหรับฉันอีกต่อไป (ฉันได้รับข้อผิดพลาดของคำสั่งที่สำคัญ)
Max von Hippel

36

Dive Into Pythonมีบทที่ดีในการจัดการการเปลี่ยนเส้นทางด้วย urllib2 ทางออกก็คือ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
ทุกคนที่มาที่นี่จาก google โปรดทราบว่าวิธีที่เป็นปัจจุบันคือ: stackoverflow.com/a/14678220/362951ไลบรารีคำขอจะช่วยให้คุณปวดหัวได้มาก
mit

ลิงก์ไปยัง "Dive Into Python" ตายแล้ว
guettli

11

นี่คือตัวจัดการ urllib2 ที่จะไม่ติดตามการเปลี่ยนเส้นทาง:

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)

ฉันกำลังทดสอบ API และจัดการกับวิธีการเข้าสู่ระบบที่เปลี่ยนเส้นทางไปยังหน้าที่ฉันไม่สนใจ แต่ไม่ได้ส่งคุกกี้เซสชันที่ต้องการพร้อมกับการตอบสนองต่อการเปลี่ยนเส้นทาง นี่คือสิ่งที่ฉันต้องการสำหรับสิ่งนั้น
Tim Wilder

9

redirectionsคำหลักในhttplib2วิธีการร้องขอเป็นปลาชนิดหนึ่งสีแดง แทนที่จะส่งคืนคำขอแรกจะเพิ่มRedirectLimitข้อยกเว้นหากได้รับรหัสสถานะการเปลี่ยนเส้นทาง จะกลับมาตอบสนอง inital คุณจะต้องตั้งfollow_redirectsไปFalseบนHttpวัตถุ:

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

8

ฉันคิดว่าสิ่งนี้จะช่วยได้

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

ตัวชี้ฉัน olt สองของการดำน้ำในหลาม นี่คือการใช้งานโดยใช้ตัวจัดการการเปลี่ยนเส้นทาง urllib2 ทำงานได้มากกว่าที่ควรจะเป็น? บางทียัก

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
ดูไม่ถูกต้อง ... รหัสนี้เป็นไปตามการเปลี่ยนเส้นทางจริง ๆ (โดยการเรียกตัวจัดการดั้งเดิมจึงออกคำขอ HTTP) จากนั้นจึงเพิ่มข้อยกเว้น
Carles Barrobés

5

วิธีที่สั้นที่สุดคือ

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

noredir_opener = urllib2.build_opener(NoRedirect())

1
วิธีนี้เป็นวิธีที่สั้นที่สุด? ไม่มีแม้แต่การนำเข้าหรือคำขอจริง
Marian

ฉันกำลังจะโพสต์วิธีแก้ปัญหานี้แล้วและค่อนข้างแปลกใจที่พบคำตอบนี้ที่ด้านล่าง มันกระชับมากและน่าจะเป็นคำตอบอันดับต้น ๆ ในความคิดของฉัน
ผู้ใช้

นอกจากนี้ยังช่วยให้คุณมีอิสระมากขึ้นด้วยวิธีนี้คุณสามารถควบคุม URL ที่จะติดตามได้
ผู้ใช้

ฉันยืนยันว่านี่เป็นวิธีที่ง่ายที่สุด ข้อสังเกตสั้น ๆ สำหรับผู้ที่ต้องการแก้ไขข้อบกพร่อง อย่าลืมว่าคุณอาจตั้งค่าขนย้ายวัสดุหลายเมื่อ bullding เปิดที่ชอบ: opener = urllib.request.build_opener(debugHandler, NoRedirect())ที่และdebugHandler=urllib.request.HTTPHandler() debugHandler.set_http_debuglevel (1)ในตอนท้าย:urllib.request.install_opener(opener)
StashOfCode
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.