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


首先说明一下,我使用的是 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 用起来相当不错:

 
HTTPCookieProcessor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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图:

 
1
2
3
4
5
6
7
8
9
10
11
                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

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

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

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

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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM