http.cookiejar --- HTTP 用戶端的 Cookie 處理¶
The http.cookiejar module defines classes for automatic handling of HTTP
cookies. It is useful for accessing websites that require small pieces of data
-- cookies -- to be set on the client machine by an HTTP response from a
web server, and then returned to the server in later HTTP requests.
一般的 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 來稱呼。
模組定義了以下例外:
- exception http.cookiejar.LoadError¶
當從檔案載入 cookies 失敗時,
FileCookieJar的實例會引發這個例外。LoadError是OSError的子類別。
這個模組提供了以下類別:
- class http.cookiejar.CookieJar(policy=None)¶
policy 是實作了
CookiePolicy介面的一個物件。CookieJar類別會儲存 HTTP cookies。它會從 HTTP 請求中抽取出 cookies,並在 HTTP 回應中將它們回傳。CookieJar實例會在必要時自動使包含的 cookies 過期。它的子類別也負責從檔案或資料庫中儲存和擷取 cookies。
- class http.cookiejar.FileCookieJar(filename=None, delayload=None, policy=None)¶
policy 是實作了
CookiePolicy介面的一個物件。至於其他引數,請參閱對應屬性的說明文件。一個可以從磁碟上的檔案載入 Cookie,也可以儲存 Cookie 到磁碟上檔案的
CookieJar。在load()或revert()方法被呼叫之前,Cookie 並不會從指定的檔案載入。這個類別的子類別有記載於 FileCookieJar 子類別及與網頁瀏覽器的合作 章節。這個類別不應該直接初始化 - 請使用下面的子類別代替。
在 3.8 版的變更: filename 參數支援傳入一個 path-like object。
- class http.cookiejar.CookiePolicy¶
此類別負責決定是否應從伺服器接受 / 回傳每個 cookie。
- class http.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也提供了一些參數來允許對策略進行一些微調。
- class http.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)¶
在策略允許的情況下,從 HTTP response 抽取出 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 和 URL path 的 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,除非你透過傳入 true ignore_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 子類別提供用於讀取和寫入。
- class http.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 刪除。
- class http.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 的處理預設為關閉。
提供你自己的策略的最簡單方法是覆寫此類別,並在你覆寫的實作中呼叫其方法,然後再加入你自己的額外檢查:
import http.cookiejar
class MyCookiePolicy(http.cookiejar.DefaultCookiePolicy):
def set_ok(self, cookie, request):
if not http.cookiejar.DefaultCookiePolicy.set_ok(self, cookie, request):
return False
if i_dont_want_to_store_this_cookie(cookie):
return False
return True
除了實作 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¶
未明確指定
domaincookie-attribute 的 Cookie 只能回傳給與設定 Cookie 的網域相同的網域(例如,spam.example.com將不會回傳來自example.com但沒有domaincookie-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 的versioncookie 屬性為 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: 最常見的用法:
import http.cookiejar, urllib.request
cj = 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 檔案的位置):
import os, http.cookiejar, urllib.request
cj = 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 或讓其回傳:
import urllib.request
from http.cookiejar import CookieJar, DefaultCookiePolicy
policy = 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/")