Чи є простий спосіб запитати URL-адресу в python і НЕ слідувати за переспрямуваннями?


96

Дивлячись на джерело urllib2, здається, найпростішим способом було б зробити підклас HTTPRedirectHandler, а потім використовувати build_opener, щоб замінити HTTPRedirectHandler за замовчуванням, але це здається великою (порівняно складною) роботою, щоб зробити те, що здається, що повинно бути. досить просто.


2
Для гуглерів: використання бібліотеки запитів позбавить вас від головного болю: docs.python-requests.org і див. Відповідь Маріан нижче, вона дуже елегантна.
Alojz Janez

Я згоден з тим, що прохання - це шлях у наші дні. Я підтримав цей коментар та відповідь Маріан, але я залишаю відповідь як присуджену, оскільки вона була найкращою на той час.
Джон

1
Нагороди @John хороші, але час іде, і це сайт, відредагований спільнотою. Основна увага приділяється хорошим відповідям, а не людям. Він буде дотримуватися своїх очок підтримки. Ви вводите в оману багато інших програмістів у застарілі бібліотеки.
mit

1
Гаразд, справедливо. Я прийняв відповідь на запити.
Джон

Відповіді:


180

Ось спосіб запитів :

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

5
Тоді подивіться на те, r.headers['Location']куди б це вас відправило
patricksurry

Зверніть увагу, що, схоже, запити нормалізуються Locationдо location.
Хаміш,

2
@Hamish requestsдозволяє отримати доступ до заголовків як у канонічній формі, так і в нижньому регістрі. Див. Docs.python-requests.org/en/master/user/quickstart/…
Маріан

1
Починаючи з 2019 року в Python 3, це більше не працює для мене. (Я отримую ключову помилку з
Макс фон Гіппель

35

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

Посилання на "Занурення в 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 і маю справу з методом входу, який перенаправляє на сторінку, яка мене не хвилює, але не надсилає бажаний сеансовий файл cookie з відповіддю на перенаправлення. Це саме те, що мені для цього було потрібно.
Тім Уайлдер

9

Ключовим redirectionsсловом у httplib2методі запиту є червоний оселедець. Замість того, щоб повернути перший запит, він викличе RedirectLimitвиняток, якщо отримає код стану перенаправлення. Щоб повернути щіток відповідь вам потрібно встановити , 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 на Dive into Python . Ось реалізація з використанням обробників перенаправлення 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
Як це найкоротший шлях? Він навіть не містить імпорту або фактичного запиту.
Маріан

Я вже збирався опублікувати це рішення і був дуже здивований, знайшовши цю відповідь внизу. Це дуже лаконічно і, на мій погляд, має бути головною відповіддю.
користувач

Більше того, це дає вам більше свободи, таким чином, ви можете контролювати, які URL-адреси слід переходити .
користувач

Підтверджую, це найпростіший спосіб. Коротке зауваження для тих, хто хоче налагодити. Не забувайте, що при встановленні сошника ви можете встановити декілька обробників, наприклад: opener = urllib.request.build_opener(debugHandler, NoRedirect())де debugHandler=urllib.request.HTTPHandler()і debugHandler.set_http_debuglevel (1). Врешті-решт:urllib.request.install_opener(opener)
StashOfCode
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.