有没有一种简单的方法可以在python中请求URL而不遵循重定向?


96

查看urllib2的源代码,看起来最简单的方法是将HTTPRedirectHandler子类化,然后使用build_opener覆盖默认的HTTPRedirectHandler,但这似乎需要很多(相对复杂的)工作来完成应有的工作很简单。


2
对于Google员工:使用请求库将为您省去很多麻烦:docs.python-requests.org并在下面查看玛丽安的答案,这非常优雅。
Alojz Janez 2014年

我同意,这些天来就是要求。我已对此评论和玛丽安(Marian)的答案表示赞同,但我认为答案是当时最好的,因此我将其保留为获奖。
约翰

1
@John奖虽然很好,但是时间还在继续,这是一个社区编辑的网站。重点在于好的答案,而不是人们。他将保留他的投票分数。您会误导成千上万的编码员进入已弃用的库。
2014年

1
好,可以。我已经接受要求的答案。
约翰

Answers:


180

这是请求的方式:

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

5
然后看看r.headers['Location']它会把您送到哪里
patricksurry

请注意,请求似乎可以标准化Locationlocation
Hamish

2
@Hamish requests允许您以规范形式和小写形式访问标头。参见docs.python-requests.org/en/master/user/quickstart/…–
Marian

1
从2019年开始,在Python 3中,这似乎不再适用于我。(我收到一个关键的dict错误。)
Max von Hippel,

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请求库将为您节省很多麻烦。
2014年

指向“ 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进行单元测试,并处理了登录方法,该方法将重定向到我不在乎的页面,但不会将所需的会话cookie与重定向响应一起发送。这正是我所需要的。
蒂姆·怀尔德2014年

9

request方法中的redirections关键字httplib2是红色鲱鱼。RedirectLimit如果收到重定向状态代码,它将引发异常,而不是返回第一个请求。要返回初始响应,您需要在对象上设置follow_redirects为:FalseHttp

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请求),然后引发异常
CarlesBarrobés11

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())where debugHandler=urllib.request.HTTPHandler()and” 这样的开瓶器设置时可以设置倍数处理程序debugHandler.set_http_debuglevel (1)。最后:urllib.request.install_opener(opener)
StashOfCode
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.