http.cookiejar
--- HTTP 用戶端的 Cookie 處理¶
http.cookiejar
模組定義了自動處理 HTTP cookie 的類別。當需要存取小量資料 ——cookies —— 的網站時會非常有用。這些資料會依據網頁伺服器的 HTTP 回應來設置於用戶端機器,並在之後的請求中被回傳到伺服器。
一般的 Netscape cookie 協定和RFC 2965 定義的 cookie 協定都會被處理。RFC 2965 的處理預設是關閉的。RFC 2109 cookie 會被剖析為 Netscape cookie,然後根據有生效的「策略」來被看作為 Netscape 或 RFC 2965 cookie。http.cookiejar
會嘗試遵循實際上的 Netscape cookie 協定(與原始的 Netscape 規格中的協定有很大的不同),包括 RFC 2965 所引進的max-age
和port
cookie 屬性。
備註
在Set-Cookie 和Set-Cookie2 標頭中出現的各種命名參數(例如domain
和expires
)通常被稱為attributes。為了與 Python 的屬性分別開,這個模組的說明檔案改用cookie-attribute 來稱呼。
模組定義了以下例外:
- exceptionhttp.cookiejar.LoadError¶
當從檔案載入 cookies 失敗時,
FileCookieJar
的實例會引發這個例外。LoadError
是OSError
的子類別。
這個模組提供了以下類別:
- classhttp.cookiejar.CookieJar(policy=None)¶
policy 是實作了
CookiePolicy
介面的一個物件。CookieJar
類別會儲存 HTTP cookies。它會從 HTTP 請求中抽取出 cookies,並在 HTTP 回應中將它們回傳。CookieJar
實例會在必要時自動使包含的 cookies 過期。它的子類別也負責從檔案或資料庫中儲存和擷取 cookies。
- classhttp.cookiejar.FileCookieJar(filename=None,delayload=None,policy=None)¶
policy 是實作了
CookiePolicy
介面的一個物件。至於其他引數,請參閱對應屬性的說明文件。一個可以從磁碟上的檔案載入 Cookie,也可以儲存 Cookie 到磁碟上檔案的
CookieJar
。在load()
或revert()
方法被呼叫之前,Cookie 並不會從指定的檔案載入。這個類別的子類別有記載於FileCookieJar 子類別及與網頁瀏覽器的合作 章節。這個類別不應該直接初始化 - 請使用下面的子類別代替。
在 3.8 版的變更:filename 參數支援傳入一個path-like object。
- classhttp.cookiejar.CookiePolicy¶
此類別負責決定是否應從伺服器接受 / 回傳每個 cookie。
- classhttp.cookiejar.DefaultCookiePolicy(blocked_domains=None,allowed_domains=None,netscape=True,rfc2965=False,rfc2109_as_netscape=None,hide_cookie2=False,strict_domain=False,strict_rfc2965_unverifiable=True,strict_ns_unverifiable=False,strict_ns_domain=DefaultCookiePolicy.DomainLiberal,strict_ns_set_initial_dollar=False,strict_ns_set_path=False,secure_protocols=('https','wss'))¶
建構函式引數只能以關鍵字引數的形式傳送。blocked_domains 是我們從不接受 cookies 或回傳 cookies 的網域名稱序列。allowed_domains 如果不是
None
,這是我們接受並回傳 cookies 的唯一網域名稱序列。secure_protocols 是可以加入安全 cookies 的通訊協定序列。預設情況下,https 和wss(安全 websocket)會被視為安全通訊協定。所有其他引數請參閱CookiePolicy
及DefaultCookiePolicy
物件的說明文件。DefaultCookiePolicy
實作了 Netscape 和RFC 2965 cookies 的標準接受/拒絕規則。預設情況下,RFC 2109 cookies(即在Set-Cookie 標頭中接收到的版本 cookie-attribute 為 1 的 cookies)會根據 RFC 2965 規則處理。 但是,如果 RFC 2965 處理被關閉,或者rfc2109_as_netscape
是True
,RFC 2109 cookie 會被CookieJar
實例「降級 」為 Netscape cookie,方法是將Cookie
實例的version
屬性設為 0。DefaultCookiePolicy
也提供了一些參數來允許對策略進行一些微調。
- classhttp.cookiejar.Cookie¶
這個類別代表 Netscape、RFC 2109 和RFC 2965 cookies。 我們不希望
http.cookiejar
的使用者建立自己的Cookie
實例。 如有必要,請在CookieJar
實例上呼叫make_cookies()
。
也參考
urllib.request
模組URL 打開時會自動處理 cookie。
http.cookies
模組HTTP cookie 類別,主要用於伺服器端程式碼。
http.cookiejar
和http.cookies
模組不互相依賴。- https://curl.se/rfc/cookie_spec.html
原始 Netscape cookie 協定的規範。雖然這仍是主流協定,但所有主要瀏覽器(以及
http.cookiejar
)實作的「Netscape cookie 協定」與cookie_spec.html
中實作的協定只有一點相似之處。- RFC 2109 - HTTP 狀態管理機制
被RFC 2965 所取代,會使用Set-Cookie 設定 version=1。
- RFC 2965 - HTTP 狀態管理機制
有錯誤修正的 Netscape 通訊協定。使用Set-Cookie2 取代Set-Cookie。未被廣泛使用。
- https://kristol.org/cookie/errata.html
未完成的RFC 2965 勘誤表。
RFC 2964 - HTTP 狀態管理使用方法
CookieJar 與 FileCookieJar 物件¶
CookieJar
物件支援iterator 協定來遍歷包含的Cookie
物件。
CookieJar
擁有以下方法:
- CookieJar.add_cookie_header(request)¶
將正確的Cookie 標頭加入request。
如果策略允許(即
CookieJar
的CookiePolicy
實例的rfc2965
和hide_cookie2
屬性分別為 true 和 false),Cookie2 標頭也會在適當的時候加入。如
urllib.request
文件所述,request 物件(通常是urllib.request.Request
的實例)必須支援get_full_url()
、has_header()
、get_header()
、header_items()
、add_unredirected_header()
方法與host
、type
、unverifiable
、origin_req_host
屬性。在 3.3 版的變更:request 物件需要
origin_req_host
屬性。已移除對已廢棄方法get_origin_req_host()
的依賴。
- CookieJar.extract_cookies(response,request)¶
在策略允許的情況下,從 HTTPresponse 抽取出 cookies 並儲存到
CookieJar
中。CookieJar
會在response 引數中尋找允許的Set-Cookie 和Set-Cookie2 標頭,並視情況儲存 cookies(需經CookiePolicy.set_ok()
方法的檢測)。response 物件(通常是呼叫
urllib.request.urlopen()
的結果或類似的東西)應該支援info()
方法,它會回傳一個email.message.Message
的實例。如
urllib.request
的檔案所說,request 物件(通常是urllib.request.Request
的實例)必須支援get_full_url()
方法以及host
、unverifiable
和origin_req_host
等屬性,該請求被用於設置 cookie-attributes 的預設值並檢查 cookie 是否允許被設置。在 3.3 版的變更:request 物件需要
origin_req_host
屬性。已移除對已廢棄方法get_origin_req_host()
的依賴。
- CookieJar.set_policy(policy)¶
設定要使用的
CookiePolicy
實例。
- CookieJar.make_cookies(response,request)¶
回傳從response 物件抽取出的
Cookie
物件序列。有關response 和request 引數所需的介面,請參閱
extract_cookies()
的說明檔案。
- CookieJar.clear([domain[,path[,name]]])¶
清除一些 cookies。
如果不帶引數地叫用,則清除所有 cookies。如果給定單一引數,則只移除屬於該domain 的 cookies。如果給定兩個引數,則會移除屬於指定domain 和 URLpath 的 cookie。 如果給定三個引數,則會移除指定domain、path 和name 的 cookie。
如果沒有符合的 cookie 存在,則引發
KeyError
。
- CookieJar.clear_session_cookies()¶
刪除所有 session cookies。
刪除所有包含有 true
discard
屬性的 cookie (通常是因為它們沒有max-age 或expires cookie 屬性,或有明確的discard cookie 屬性)。 對於互動式瀏覽器,工作階段的結束通常對應於關閉瀏覽器視窗。請注意
save()
方法無論如何都不會儲存 session cookies,除非你透過傳入 trueignore_discard 引數來要求。
FileCookieJar
實例有下列附加方法:
- FileCookieJar.save(filename=None,ignore_discard=False,ignore_expires=False)¶
將 cookies 儲存到檔案中。
這個基底類別會產生
NotImplementedError
。子類別可以不實作此方法。filename 是儲存 cookies 的檔案名稱。 如果filename 未指定,則會使用
self.filename
(其預設值是傳給建構函式的值(如果有));如果self.filename
是None
,則會產生ValueError
。ignore_discard: 即使設定為捨棄的 cookies 也會儲存。ignore_expires: 保存過期的 cookie
如果檔案已經存在,則會被覆寫,因此會抹除其中包含的所有 cookies。 儲存的 cookies 可以稍後使用
load()
或revert()
方法還原。
- FileCookieJar.load(filename=None,ignore_discard=False,ignore_expires=False)¶
從檔案中載入 cookies。
舊的 cookies 會被保留,除非被新載入的 cookies 覆蓋。
引數與
save()
相同。被命名的檔案必須是類別所能正確剖析的格式,否則會產生
LoadError
。此外,OSError
可能會被引發,例如檔案不存在時。
- FileCookieJar.revert(filename=None,ignore_discard=False,ignore_expires=False)¶
清除所有 cookies, 並從儲存的檔案重新載入 cookies。
FileCookieJar
實例擁有以下公開屬性:
- FileCookieJar.filename¶
保存 cookie 的預設檔案的檔案名稱。 此屬性可以被指定。
- FileCookieJar.delayload¶
若為 true,則從硬盤惰性地載入 cookies。 此屬性不應被指定。 這只是一個提示,因為這只會影響效能,不會影響行為 (除非磁碟上的 cookies 正在改變)。一個
CookieJar
物件可以忽略它。 沒有一個包含在標準函式庫中的FileCookieJar
類別會惰性地載入 cookies。
FileCookieJar 子類別及與網頁瀏覽器的合作¶
以下CookieJar
子類別提供用於讀取和寫入。
- classhttp.cookiejar.MozillaCookieJar(filename=None,delayload=None,policy=None)¶
一個能夠以 Mozilla
cookies.txt
檔案格式(該格式也被 curl 和 Lynx 以及 Netscape 瀏覽器所使用)從磁碟載入和儲存 cookie 的FileCookieJar
。備註
這會遺失關於RFC 2965 cookie 的訊息,以及較新或非標準 cookie 屬性(例如
port
)的訊息。警告
如果 Cookie 遺失或損壞會造成不便,請在儲存之前先備份 Cookie(有些微妙的情況可能會導致檔案在載入/儲存往返過程中發生輕微變化)。
另外請注意,在 Mozilla 執行時儲存的 cookies 會被 Mozilla 刪除。
- classhttp.cookiejar.LWPCookieJar(filename=None,delayload=None,policy=None)¶
一個
FileCookieJar
可以從 libwww-perl 函式庫的Set-Cookie3 檔案格式載入 cookies 並儲存 cookies 到磁碟。如果你想要將 cookie 儲存在人類可讀的檔案中,這是很方便的。在 3.8 版的變更:filename 參數支援傳入一個path-like object。
CookiePolicy 物件¶
實作CookiePolicy
介面的物件有以下方法:
- CookiePolicy.set_ok(cookie,request)¶
回傳值表示的是否接受伺服器 cookie 的布林值。
cookie 是一個
Cookie
實例。request 是一個實作了CookieJar.extract_cookies()
文件所定義的介面的物件。
- CookiePolicy.return_ok(cookie,request)¶
回傳布林值,表示 cookie 是否應回傳伺服器。
cookie 是一個
Cookie
實例。request 是一個實作了CookieJar.add_cookie_header()
文件所定義的介面的物件。
- CookiePolicy.domain_return_ok(domain,request)¶
在給定 cookie 網域如果不應回傳 cookie,則回傳
False
。此方法為一種最佳化。它消除了檢查每個具有特定網域的 cookie 的需要(這可能需要讀取許多檔案)。從
domain_return_ok()
和path_return_ok()
回傳 true 會把所有的工作留給return_ok()
。如果
domain_return_ok()
對 cookie 網域回傳 true,path_return_ok()
就會被用來呼叫 cookie 路徑。否則path_return_ok()
和return_ok()
永遠不會被呼叫。如果path_return_ok()
回傳 true,則會呼叫return_ok()
附帶的Cookie
物件本身以進行全面檢查。否則,return_ok()
將永遠不會被呼叫。請注意,
domain_return_ok()
是針對每個cookie 網域來呼叫的,而不只是針對request 網域。 例如,如果請求網域是"www.example.com"
,這個函式可能會同時被".example.com"
和"www.example.com"
呼叫。 同樣的道理也適用於path_return_ok()
。request 引數與
return_ok()
的說明文件相同。
- CookiePolicy.path_return_ok(path,request)¶
給定 cookie 路徑如不應該回傳 cookie,則回傳
False
。關於
domain_return_ok()
請見文件。
除了實作上述方法外,CookiePolicy
介面的實作也必須提供下列屬性,指出應該使用哪些通訊協定,以及如何使用。所有這些屬性都可以被指定。
- CookiePolicy.netscape¶
實作 Netscape 協定。
以DefaultCookiePolicy
為子類別定義CookiePolicy
類別,並覆寫其中的一些或全部方法是最有用的。CookiePolicy
本身可以用做 '無策略',允許設定和接收任何和所有的 cookies (這不太可能有用)。
DefaultCookiePolicy 物件¶
執行接受和回傳 cookie 的標準規則。
同時支援RFC 2965 和 Netscape cookies。 RFC 2965 的處理預設為關閉。
提供你自己的策略的最簡單方法是覆寫此類別,並在你覆寫的實作中呼叫其方法,然後再加入你自己的額外檢查:
importhttp.cookiejarclassMyCookiePolicy(http.cookiejar.DefaultCookiePolicy):defset_ok(self,cookie,request):ifnothttp.cookiejar.DefaultCookiePolicy.set_ok(self,cookie,request):returnFalseifi_dont_want_to_store_this_cookie(cookie):returnFalsereturnTrue
除了實作CookiePolicy
介面所需的功能外,這個類別還允許你阻止或允許網域名稱設定和接收 cookies。 還有調整嚴格度的控制選項,可讓你稍微收緊相對寬鬆的 Netscape 通訊協定(代價是阻擋一些良性 cookies)。
提供網域阻止清單和允許清單(預設都關閉)。只有不在阻止清單中和在允許清單中(如果允許清單是有效的)的網域才參與 cookie 設定和回傳。使用blocked_domains 構造函式引數,以及blocked_domains()
和set_blocked_domains()
方法(以及allowed_domains 的相應引數和方法)。如果你設定了允許清單,你可以透過設定為None
來再次關閉它。
封鎖或允許清單中不以點開頭的網域必須與 cookie 網域相等才能匹配。 例如,"example.com"
會與封鎖清單項目"example.com"
匹配,但"www.example.com"
則不會。 以點開頭的網域也會與更特定的網域相匹配。例如,"www.example.com"
和"www.coyote.example.com"
都匹配".example.com"
(但"example.com"
本身不匹配)。 IP 位址是例外,它們必須完全匹配。例如,如果 blocked_domains 包含"192.168.1.2"
和".168.1.2"
,則 192.168.1.2 會被封鎖,但 193.168.1.2 則不會。
DefaultCookiePolicy
實作了下列附加方法:
- DefaultCookiePolicy.blocked_domains()¶
回傳被阻止網域的序列(以元組形式)。
- DefaultCookiePolicy.set_blocked_domains(blocked_domains)¶
設定阻止網域的順序。
- DefaultCookiePolicy.is_blocked(domain)¶
如果domain 在設定或接收 cookies 的阻止列表上,則回傳
True
。
- DefaultCookiePolicy.is_not_allowed(domain)¶
如果domain 不在設定或接收 cookies 的允許清單上,則回傳
True
。
DefaultCookiePolicy
實例有以下屬性,這些屬性都是由同名的建構函式引數初始化,而且都可以被指定。
- DefaultCookiePolicy.rfc2109_as_netscape¶
如果為 true,請求
CookieJar
實例透過設定Cookie
實例的版本屬性為 0,將RFC 2109 cookies (即在Set-Cookie 標頭中收到的、版本 cookie 屬性為 1 的 cookies) 降級為 Netscape cookies。 預設值是None
,在這種情況下,如果且僅如果RFC 2965 處理被關閉,RFC 2109 cookies 才會被降級。 因此,RFC 2109 cookie 在預設情況下被降級。
一般的調整嚴格度的控制選項:
- DefaultCookiePolicy.strict_domain¶
不允許網站設定具有國家代碼頂層域名的兩層域名,如
.co.uk
、.gov.uk
、.co.nz
等。 這遠遠不夠完美,也不能保證一定有效!
RFC 2965 通訊協定調整嚴格度的控制選項:
- DefaultCookiePolicy.strict_rfc2965_unverifiable¶
遵循針對不可驗證事務(transaction)的RFC 2965 規則(不可驗證事務通常是由重定向或請求發佈在其它網站的圖片導致的)。 如果該屬性為假值,則永遠不會基於可驗證性而阻止 cookie
Netscape 通訊協定調整嚴格度的控制選項:
- DefaultCookiePolicy.strict_ns_domain¶
指明針對 Netscape cookie 的網域匹配規則的嚴格程度。 可接受的值見下文。
- DefaultCookiePolicy.strict_ns_set_initial_dollar¶
忽略 Set-Cookie: 標頭中名稱以
'$'
開頭的 cookies。
- DefaultCookiePolicy.strict_ns_set_path¶
不允許設置路徑與請求 URL 路徑不匹配的 cookie。
strict_ns_domain
是一系列旗標。它的值由將旗標按位元或組成(例如,DomainStrictNoDots|DomainStrictNonDomain
表示兩個旗標都被設定)。
- DefaultCookiePolicy.DomainStrictNoDots¶
設定 cookie 時,「host 前綴」不得包含點(例如,
www.foo.bar.com
不能為.bar.com
設定 cookie,因為www.foo
包含一個點)。
- DefaultCookiePolicy.DomainStrictNonDomain¶
未明確指定
domain
cookie-attribute 的 Cookie 只能回傳給與設定 Cookie 的網域相同的網域(例如,spam.example.com
將不會回傳來自example.com
但沒有domain
cookie-attribute 的 Cookie)。
為了方便起見,以下屬性是上述旗標最有用的組合:
- DefaultCookiePolicy.DomainLiberal¶
等於 0(即關閉上述所有 Netscape 網域嚴格度旗標)。
- DefaultCookiePolicy.DomainStrict¶
等價於
DomainStrictNoDots|DomainStrictNonDomain
。
Cookie 物件¶
Cookie
實例的 Python 屬性大致對應於各種 cookie 標準中指定的標準 cookie 屬性。 這個對應關係不是一一對應的,因為有複雜的規則來指定預設值,因為max-age
和expires
cookie 屬性包含相等的訊息,也因為RFC 2109 cookie 可能會被http.cookiejar
從版本 1「降級」到版本 0 (Netscape) cookie。
除了在CookiePolicy
方法中的罕見情況外,不應該對這些屬性進行指定。 這個類別不會強制執行內部一致性,所以如果你這麼做,你應該要知道你在做什麼。
- Cookie.version¶
整數或
None
。 Netscape cookie 的version
為 0。RFC 2965 和RFC 2109 cookie 的version
cookie 屬性為 1。但是,請注意http.cookiejar
可能會將 RFC 2109 cookie 「降級」 為 Netscape cookie,在這種情況下version
為 0。
- Cookie.name¶
Cookie 名稱(字串)。
- Cookie.domain¶
Cookie 網域(字串)。
- Cookie.path¶
Cookie 路徑(字串,例如
'/acme/rocket_launchers'
)。
- Cookie.secure¶
如果 cookie 只能透過安全連線回傳,則為
True
。
- Cookie.expires¶
自 epoch 起計算的整數到期時間,以秒為單位,或
None
。另請參閱is_expired()
方法。
- Cookie.discard¶
如果這是 session cookie,即為
True
。
- Cookie.rfc2109¶
True
如果這個 cookie 是以RFC 2109 cookie 的形式收到的 (即這個 cookie 是在Set-Cookie 標頭中收到的,而且在那個標頭中的 Version cookie-attribute 的值是 1)。 提供這個屬性的原因是http.cookiejar
可能會將 RFC 2109 cookie 「降級」 為 Netscape cookie,在這種情況下version
的值是 0。
- Cookie.port_specified¶
如果伺服器顯式地指定了一個連接埠或一組連接埠(在Set-Cookie /Set-Cookie2 標頭中)。
- Cookie.domain_specified¶
如果伺服器明確指定網域,則為
True
。
- Cookie.domain_initial_dot¶
如果伺服器明確指定的網域以點 (
'.'
) 開頭,則為True
。
Cookies 可能具有額外的非標準 cookie 屬性。你可以使用下列方法存取這些屬性:
- Cookie.has_nonstandard_attr(name)¶
如果 cookie 具有指定的 cookie 屬性,則回傳
True
。
- Cookie.get_nonstandard_attr(name,default=None)¶
如果 cookie 具有指定的 cookie 屬性,則回傳其值。否則,回傳default。
- Cookie.set_nonstandard_attr(name,value)¶
設定指定 cookie 屬性的值。
Cookie
類別也定義了以下方法:
- Cookie.is_expired(now=None)¶
如果 cookie 已經超過伺服器要求的過期時間,則回傳
True
。 如果給定了now (以自紀元起的秒數為單位),則會回傳 cookie 是否已在指定時間過期。
範例¶
第一個範例展示了http.cookiejar
: 最常見的用法:
importhttp.cookiejar,urllib.requestcj=http.cookiejar.CookieJar()opener=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))r=opener.open("http://example.com/")
本範例說明如何使用你的 Netscape、Mozilla 或 Lynx cookies 打開 URL (假設 Unix/Netscape 會慣用 cookies 檔案的位置):
importos,http.cookiejar,urllib.requestcj=http.cookiejar.MozillaCookieJar()cj.load(os.path.join(os.path.expanduser("~"),".netscape","cookies.txt"))opener=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))r=opener.open("http://example.com/")
下一個範例說明DefaultCookiePolicy
的使用。開啟RFC 2965 cookies,在設定和回傳 Netscape cookies 時對網域更嚴格,並阻止某些網域設定 cookies 或讓其回傳:
importurllib.requestfromhttp.cookiejarimportCookieJar,DefaultCookiePolicypolicy=DefaultCookiePolicy(rfc2965=True,strict_ns_domain=Policy.DomainStrict,blocked_domains=["ads.net",".ads.net"])cj=CookieJar(policy)opener=urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))r=opener.open("http://example.com/")