Python'da bir URL talep etmenin ve yönlendirmeleri takip ETMEMenin kolay bir yolu var mı?


101

Urllib2'nin kaynağına bakıldığında, bunu yapmanın en kolay yolu HTTPRedirectHandler'ı alt sınıflamak ve ardından varsayılan HTTPRedirectHandler'ı geçersiz kılmak için build_opener kullanmak gibi görünüyor, ancak bu, olması gerektiği gibi görünen şeyi yapmak için çok fazla (nispeten karmaşık) iş gibi görünüyor. oldukça basit.


2
Google çalışanları için: istek kitaplığını kullanmak size çok fazla baş ağrısından kurtulacaktır : docs.python-requests.org ve aşağıdaki Marian'ın cevabına bakın, çok zarif.
Alojz Janez

İsteklerin bugünlerde gitmenin yolu olduğuna katılıyorum. Bu yorumu ve Marian'ın cevabını destekledim ama o zamanın en iyisi olduğu için cevabı ödül olarak bırakıyorum.
John

1
@John ödülleri iyi ama zaman geçiyor ve bu topluluk tarafından düzenlenen bir site. İnsanlara değil, iyi cevaplara odaklanılır. Ek puanlarını koruyacak. Tonlarca kodlayıcıyı, kullanımdan kaldırılan kitaplıklara yönlendiriyorsunuz.
mit

1
Tamam, yeterince adil. İsteklerin yanıtını kabul ettim.
John

Yanıtlar:


186

İşte İstekler yolu:

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

6
Sonra r.headers['Location']sizi nereye göndermiş olacağına bakın
patricksurry

Not o İstekler normalleştirmek edeceğini görünüyor Locationiçin location.
Hamish

2
@Hamish requests, başlıklara hem kanonik biçimde hem de küçük harflerle erişmenizi sağlar. Bkz docs.python-requests.org/en/master/user/quickstart/...
Marian

1
Python 3'te 2019 itibariyle, bu artık benim için çalışmıyor gibi görünüyor. (Önemli bir dikt hatası alıyorum.)
Max von Hippel

36

Dive Into Python , urllib2 ile yeniden yönlendirmeleri ele alma konusunda iyi bir bölüme sahiptir. Diğer bir çözüm de 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
Buraya google'dan gelen herkes, lütfen en güncel yolun bu olduğunu unutmayın: stackoverflow.com/a/14678220/362951 İstekler kitaplığı sizi çok fazla baş ağrısından kurtaracaktır.
mit

"Python'a Dalın" bağlantısı kesildi.
guettli

11

Bu, yönlendirmeleri izlemeyecek bir urllib2 işleyicisidir:

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)

Bir API birimini test ediyorum ve umursamadığım bir sayfaya yönlendirme yapan, ancak yönlendirmeye yanıtla birlikte istenen oturum çerezini göndermeyen bir oturum açma yöntemiyle uğraşıyorum. Bunun için tam olarak ihtiyacım olan şey buydu.
Tim Wilder

9

redirectionsAnahtar kelime httplib2isteği yöntemiyle kırmızı ringa. İlk isteği döndürmek yerine RedirectLimit, bir yeniden yönlendirme durum kodu alırsa bir istisna oluşturur. Eğer sette gereken açmasının tepkisini dönmek için follow_redirectsiçin Falseüzerine Httpnesne:

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

8

Sanırım bu yardımcı olur

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

Python'a Dalmak için ikinci işaretçi oldum . İşte urllib2 yönlendirme işleyicilerini kullanan bir uygulama, olması gerekenden daha fazla iş mi? Belki omuz silkme.

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
Yanlış görünüyor ... Bu kod aslında yönlendirmeleri takip ediyor (orijinal işleyiciyi çağırarak, dolayısıyla bir HTTP isteği göndererek) ve sonra bir istisna
yaratıyor

5

Ancak en kısa yol

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

noredir_opener = urllib2.build_opener(NoRedirect())

1
Bu nasıl en kısa yol? İçe aktarımı veya gerçek talebi bile içermiyor.
Marian

Zaten bu çözümü yayınlayacaktım ve bu cevabı en altta bulduğumda oldukça şaşırdım. Çok kısa ve bence en iyi cevap olmalı.
kullanıcı

Dahası, size daha fazla özgürlük verir, bu şekilde hangi URL'lerin izleneceğini kontrol etmek mümkündür .
kullanıcı

Onaylıyorum, bu kolay yol. Hata ayıklamak isteyenler için kısa bir açıklama. Unutmayın, açıcıyı şu şekilde doldururken çoklu işleyicileri belirleyebileceğinizi unutmayın: opener = urllib.request.build_opener(debugHandler, NoRedirect())nerede debugHandler=urllib.request.HTTPHandler()ve debugHandler.set_http_debuglevel (1). Sonunda:urllib.request.install_opener(opener)
StashOfCode
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.