Python中Cookie的處理(二)cookielib庫

tycoon1988發表於2014-10-28

Python中cookielib庫(python3中為http.cookiejar)為儲存和管理cookie提供客戶端支援。

該模組主要功能是提供可儲存cookie的物件。使用此模組捕獲cookie並在後續連線請求時重新傳送,還可以用來處理包含cookie資料的檔案。

這個模組主要提供了這幾個物件,CookieJar,FileCookieJar,MozillaCookieJar,LWPCookieJar。

1. CookieJar

    CookieJar物件儲存在記憶體中。

1
2
3
4
5
6
>>> import urllib2
>>> import cookielib
>>> cookie=cookielib.CookieJar()
>>> handler=urllib2.HTTPCookieProcessor(cookie)
>>> opener=urllib2.build_opener(handler)
>>> opener.open('http://www.google.com.hk'

訪問google的cookie已經被捕捉了,來看下是怎樣的:

 
 
>>> print cookie
<cookielib.CookieJar[<Cookie NID=67=B6YQoEIEjcqDj-adada_WmNYl_JvADsDEDchFTMtAgERTgRjK452ko6gr9G0Q5p9h1vlmHpCR56XCrWwg1pv6iqhZnaVlnwoeM-Ln7kIUWi92l-X2fvUqgwDnN3qowDW for .google.com.hk/>, <Cookie PREF=ID=7ae0fa51234ce2b1:FF=0:NW=1:TM=1391219446:LM=1391219446:S=cFiZ5X8ts9NY3cmk for .google.com.hk/>]>

看來是Cookie例項的集合,Cookie例項有name,value,path,expires等屬性:

 
 
 
 
 
 
>>> for ck in cookie:
...     print ck.name,':',ck.value
...
NID : 67=B6YQoEIEjcqDj-adada_WmNYl_JvADsDEDchFTMtAgERTgRjK452ko6gr9G0Q5p9h1vlmHpCR56XCrWwg1pv6iqhZnaVlnwoeM-Ln7kIUWi92l-X2fvUqgwDnN3qowDW
PREF : ID=7ae0fa51234ce2b1:FF=0:NW=1:TM=1391219446:LM=1391219446:S=cFiZ5X8ts9NY3cmk
 
 
 
 

般,我們HTTP抓包得到的Cookie位於Request Header中,格式如下:

Cookie: key1=val1; key2=val2; key3=val3

要使用該字串發起HTTP請求,有幾種方法:

  1. 使用httplib新增到headers中
  2. 使用cookielib建立CookieJar物件在urllib2中使用
  3. 使用requests模組

它們各有不足:

  1. httplib不會自動管理cookie(不會在後續的請求中自動新增、更新、刪除過期)
  2. cookielib的處理過程稍複雜
  3. requests需要另安裝

使用httplib直接新增cookie到header

如果不需要程式自己管理cookie,這個方法是極簡單的。下面簡單示例處理GET請求:

 

 

import httplib
import urlparse

def request(url, cookie=''):
    ret = urlparse.urlparse(url)    # Parse input URL
    if ret.scheme == 'http':
        conn = httplib.HTTPConnection(ret.netloc)
    elif ret.scheme == 'https':
        conn = httplib.HTTPSConnection(ret.netloc)
       
    url = ret.path
    if ret.query: url += '?' + ret.query
    if ret.fragment: url += '#' + ret.fragment
    if not url: url = '/'
   
    conn.request(method='GET', url=url , headers={'Cookie': cookie})
    return conn.getresponse()

if __name__ == '__main__':
    cookie_str = 'tLargeScreenP=1; Authorization=Basic%20HereIsMySecret; subType=pcSub; TPLoginTimes=2'
    url = 'http://192.168.1.253'
    html_doc = request(url, cookie_str).read()
    import re
    print 'With Auth:', re.search('<title>(.*?)</title>', html_doc, re.IGNORECASE).group(1)

    html_doc = request(url).read()
    print 'Without Auth:', re.search('<title>(.*?)</title>', html_doc, re.IGNORECASE).group(1)

request函式就是全部的內容,測試IP 192.168.1.253是我房間的無線路由器。第一次HTTP請求帶Cookie,第二次不帶Cookie,返回的標題不一樣:

httplib-cookie

 

前篇介紹了直接使用httplib傳送Cookie,簡潔直觀。建立cookielib.CookieJar物件自動管理Cookie稍繁瑣一些,但是一旦建立,可供urllib2建立opener,後續的所有cookie更新和過期刪除都是自動處理的。

1. 解析Cookie Str,得到Cookie.SimpleCookie物件

我們得到的Request Header中,Cookie是這樣的格式:

Cookie: key1=val1; key2=val2; key3=val3

第一步是解析它,得到Cookie.SimpleCookie物件。通過字串構造即可: Cookie.SimpleCookie(cookie_str)

得到的是一個dict-like物件,它的每一個值都是一個Set-Cookie語句,上述例子解析後是:

2. 用SimpleCookie建立cooklib.Cookie物件

上述SimpleCookie不能直接使用,因為一個完整的Cookie,還必須包括額外的欄位,如:domain、path、expires等。第二步工作是建立cooklib.Cookie物件,直接將key, value傳入cooklib.Cookie類的建構函式即可。

得到一系列cookielib.Cookie物件,便可以依次用它們來更新CookieJar了。

3. 完整的示例程式碼

import cookielib
import Cookie
import urllib2

def build_opener_with_cookie_str(cookie_str, domain, path='/'):
    simple_cookie = Cookie.SimpleCookie(cookie_str)    # Parse Cookie from str
    cookiejar = cookielib.CookieJar()    # No cookies stored yet

    for c in simple_cookie:
        cookie_item = cookielib.Cookie(
            version=0, name=c, value=str(simple_cookie[c].value),
                     port=None, port_specified=None,
                     domain=domain, domain_specified=None, domain_initial_dot=None,
                     path=path, path_specified=None,
                     secure=None,
                     expires=None,
                     discard=None,
                     comment=None,
                     comment_url=None,
                     rest=None,
                     rfc2109=False,
            )
        cookiejar.set_cookie(cookie_item)    # Apply each cookie_item to cookiejar
    return urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))  

  # Return opener


if __name__ == '__main__':
    cookie_str = 'tLargeScreenP=1; Authorization=Basic%20HereIsMySecret; subType=pcSub; TPLoginTimes=2'
    opener = build_opener_with_cookie_str(cookie_str, domain='192.168.1.253')
  
    html_doc = opener.open('http://192.168.1.253').read()
    import re
    print 'Open With Cookie:', re.search('<title>(.*?)</title>', html_doc, re.IGNORECASE).group(1)

    html_doc = urllib2.urlopen('http://192.168.1.253').read()
    print 'Open Without Cookie:', re.search('<title>(.*?)</title>', html_doc, re.IGNORECASE).group(1)

 

相關文章