10
21
2010
6

Python HTTP 请求时对重定向中的 cookie 的处理

本文来自依云's Blog,转载请注明。

首先说明一下,我使用的是 Python3 的 urllib,但 Python2.x 同理(使用 urllib2)。

想用脚本去登录一个网站。和很多网站一样,该网站使用 cookie 来保存会话信息。这个我以前是自己提取 response 中的 Set-Cookie 头来处理的。这次本想如法炮制,却发现没保存需要的 cookie,所以登录失败。

很郁闷地想了半天,最后出去 wireshark 抓包,终于发现原来重要的 cookie 在登录后的应答中,但这个应答是个 302 重定向,所以 urllib 默认的 opener (urllib.request.urlopen)直接就跟从这个重定向了,没有对 cookie 进行任何处理。

我首先想到的是,不要跟从重定向。我看到有个 HTTPRedirectHandler,但文档里没写它怎么用。郁闷……自己找到 request.py 文件看源代码,折腾了好久无果,遂想到 Google (早该想到了。。。)于是找到了 StackOverflow 上。有两个解决办法:要么不跟从重定向,要么弄个 HTTPCookieProcessor 保存 cookie 信息。看我自己的需求,当然选后者了。而且,那个回答问题的人也没有给出如何不让它跟从重定向(所给代码只是在重定向前对 cookie 进行处理而已)。

于是,我再一次地打开了 http.cookiejar 的文档,尝试弄明白这东西到底怎么用。当初折腾 cookie 的时候,没弄明白这个,所以才自己处理的。

看 request.py 里的代码,这个 CookieJar 用起来相当不错:

class HTTPCookieProcessor(BaseHandler):
    def __init__(self, cookiejar=None):
        import http.cookiejar
        if cookiejar is None:
            cookiejar = http.cookiejar.CookieJar()
        self.cookiejar = cookiejar

    def http_request(self, request):
        self.cookiejar.add_cookie_header(request)
        return request

    def http_response(self, request, response):
        self.cookiejar.extract_cookies(response, request)
        return response

    https_request = http_request
    https_response = http_response

不过我需要将 cookie 信息保存到文件。从文档上看到有个 FileCookieJar。我尝试了下,出错了,没有 _really_load 方法,我晕。。。之后才注意到其源代码开头有个ASCII图:

						CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

原来具体实现还在子类啊。好吧,我就用 MozillaCookieJar 好了。

用法很简单,初始化时把文件名传给它,载入用 load(),保存用 save()。不过要注意的是,文件不存在时不能载入,touch 个空文件出来也不行的。

另外,那个 StackOverflow 的页面还提到了 mechanize 这个模块,有时间去尝试下 :-)

最后,如果我不要它重定向该怎么做呢?难道非要我去用更底层的 http.client?

Category: python | Tags: python 网络 | Read Count: 20636
fory 说:
Feb 24, 2011 03:13:19 AM

我在用urllib2处理重定向时好像也碰到过类似的问题,这个你可以参考下不知道跟你说的是否同一件事

redirect_handler = urllib2.HTTPRedirectHandler()
#disable redirection request
def no_redirect(req, fp, code, msg, hdrs, newurl): return None
redirect_handler.redirect_request=no_redirect
opener = urllib2.build_opener(redirect_handler)
urllib2.install_opener(opener)
req=urllib2.Request('http://xxx.url/download.php?fileid=%s'%(fid),"")
req.add_header('Referer',dlurl)
try:
f=urllib2.urlopen(req)
except urllib2.HTTPError,e:
if e.code==302:
print "get file location(%s)"%fn
return e.hdrs['Location']
print "opps~HTTPError(%d)"%(e.code)
except Exception as ec:
print "*_* can't locate file %s[%s]"%(fn,str(ec))
else:
print "*_* can't locate file %s[http no redirection]"%fn

Avatar_small
依云 说:
Feb 24, 2011 06:12:37 AM

是同一回事,参见本文第一行 ;-)

pretty975 说:
Mar 18, 2011 06:40:13 PM

你好,请教你一个问题。。不知道跟你写的有没有关系。
觉得你应该会。。
我的目的是想要python写一个程序登陆网个网站(m.renren.com--手机人人网),想在自己的程序里写上自己的账号密码,再通过账号密码登陆人人网。现在不知道怎么下手,而我身边的人,我知道他能用 python处理登陆(www.renren.com--人人网)的cookie,你能给点方向性的意见吗?谢谢。

Avatar_small
依云 说:
Mar 18, 2011 07:06:21 PM

首先用火狐访问,使用 Firebug 或者 HttpFox 之类的工具把请求的细节弄清楚,然后使用 Python 的 urllib2/urllib 标准库访问和发送数据,同时维护 cookie。你需要了解下HTML表单提交的过程。

mrluanma 说:
Jul 19, 2011 02:45:25 PM

何必跟 urllib2 绕来绕去呢, 直接换 httplib2 吧.

自动重定向, 还是不重定向, 设置一个属性就可以了:

from httplib2 import Http
h = Http()
h.follow_redirects = False

这里有个登录 人人网 的完整的例子.

https://gist.github.com/964785

Avatar_small
依云 说:
Jul 19, 2011 03:18:51 PM

貌似不错,以后有机会我试用下。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

部分静态文件存储由又拍云存储提供。 | Theme: Aeros 2.0 by TheBuckmaker.com