http.cookiejar — HTTP 客戶端的 Cookie 處理

原始碼: Lib/http/cookiejar.py


http.cookiejar 模組定義了用於自動處理 HTTP Cookie 的類。它對於訪問那些需要Web伺服器透過HTTP響應在客戶端機器上設定一小段資料——即 Cookie,然後在後續的HTTP請求中將其返回給伺服器的網站非常有用。

該模組同時處理常規的 Netscape Cookie 協議和 RFC 2965 定義的協議。預設情況下,RFC 2965 的處理是關閉的。RFC 2109 Cookie 會被解析為 Netscape Cookie,然後根據生效的“策略”被當作 Netscape 或 RFC 2965 Cookie 處理。請注意,網際網路上絕大多數 Cookie 都是 Netscape Cookie。http.cookiejar 模組試圖遵循事實上的 Netscape Cookie 協議(這與最初 Netscape 規範中規定的有很大不同),包括注意 RFC 2965 引入的 max-ageport Cookie 屬性。

備註

Set-CookieSet-Cookie2 頭中找到的各種命名引數(例如 domainexpires)通常被稱為 attributes (屬性)。為了與 Python 的屬性 (attribute) 區分開來,本模組的文件使用術語 cookie-attribute (Cookie 屬性)。

該模組定義了以下異常:

exception http.cookiejar.LoadError

FileCookieJar 的例項在從檔案載入 Cookie 失敗時會引發此異常。LoadErrorOSError 的子類。

在 3.3 版本發生變更: LoadError 過去是 IOError 的子型別,現在 IOError 已成為 OSError 的別名。

提供了以下類:

class http.cookiejar.CookieJar(policy=None)

policy 是一個實現了 CookiePolicy 介面的物件。

CookieJar 類儲存 HTTP Cookie。它從 HTTP 請求中提取 Cookie,並在 HTTP 響應中返回它們。CookieJar 例項會在必要時自動使包含的 Cookie 過期。其子類還負責從檔案或資料庫中儲存和檢索 Cookie。

class http.cookiejar.FileCookieJar(filename=None, delayload=None, policy=None)

policy 是一個實現了 CookiePolicy 介面的物件。對於其他引數,請參閱相應屬性的文件。

一個 CookieJar,可以從磁碟上的檔案中載入 Cookie,也可能將 Cookie 儲存到檔案中。除非呼叫 load()revert() 方法,否則 Cookie 不會從指定的檔案中載入。這個類的子類在 FileCookieJar 的子類以及與 Web 瀏覽器的協作 一節中有文件說明。

不應直接初始化此類——應使用其下方的子類。

在 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 是一個域名序列,我們永遠不會接受來自這些域名的 Cookie,也不會向它們返回 Cookie。如果 allowed_domains 不為 None,則它是一個我們只接受和返回 Cookie 的域名序列。secure_protocols 是一個協議序列,可以為這些協議新增安全 Cookie。預設情況下,httpswss (安全 WebSocket) 被視為安全協議。對於所有其他引數,請參閱 CookiePolicyDefaultCookiePolicy 物件的文件。

DefaultCookiePolicy 實現了針對 Netscape 和 RFC 2965 Cookie 的標準接受/拒絕規則。預設情況下,RFC 2109 Cookie(即在 Set-Cookie 頭部中收到的,版本 Cookie 屬性為 1 的 Cookie)會根據 RFC 2965 規則處理。然而,如果 RFC 2965 處理被關閉,或者 rfc2109_as_netscapeTrueCookieJar 例項會將 RFC 2109 Cookie“降級”為 Netscape Cookie,方法是將 Cookie 例項的 version 屬性設定為 0。DefaultCookiePolicy 還提供了一些引數以允許對策略進行一些微調。

class http.cookiejar.Cookie

這個類代表 Netscape、RFC 2109RFC 2965 Cookie。不希望 http.cookiejar 的使用者自己構造 Cookie 例項。如有必要,應在 CookieJar 例項上呼叫 make_cookies()

參見

模組 urllib.request

使用自動 Cookie 處理開啟 URL。

模組 http.cookies

HTTP Cookie 類,主要用於伺服器端程式碼。http.cookiejarhttp.cookies 模組互不依賴。

https://curl.se/rfc/cookie_spec.html

最初的 Netscape Cookie 協議規範。儘管這仍然是主流協議,但所有主流瀏覽器(以及 http.cookiejar)實現的“Netscape Cookie 協議”與 cookie_spec.html 中描述的協議僅有微弱的相似之處。

RFC 2109 - HTTP 狀態管理機制

已被 RFC 2965 廢棄。使用帶有 version=1 的 Set-Cookie

RFC 2965 - HTTP 狀態管理機制

修復了 Netscape 協議錯誤的協議。使用 Set-Cookie2 替代 Set-Cookie。未被廣泛使用。

https://kristol.org/cookie/errata.html

RFC 2965 的未完成勘誤表。

RFC 2964 - HTTP 狀態管理的使用

CookieJar 和 FileCookieJar 物件

CookieJar 物件支援迭代器協議,用於遍歷其中包含的 Cookie 物件。

CookieJar 具有以下方法:

request 新增正確的 Cookie 標頭。

如果策略允許(即,CookieJarCookiePolicy 例項的 rfc2965hide_cookie2 屬性分別為 true 和 false),則在適當時也會新增 Cookie2 標頭。

request 物件(通常是 urllib.request.Request 的例項)必須支援 get_full_url(), has_header(), get_header(), header_items(), add_unredirected_header() 方法,以及 host, type, unverifiableorigin_req_host 屬性,具體如 urllib.request 所述。

在 3.3 版本發生變更: request 物件需要 origin_req_host 屬性。已移除對已棄用方法 get_origin_req_host() 的依賴。

CookieJar.extract_cookies(response, request)

從 HTTP response 中提取 Cookie,並在策略允許的情況下將它們儲存在 CookieJar 中。

CookieJar 會在 response 引數中查詢允許的 Set-CookieSet-Cookie2 標頭,並根據情況儲存 Cookie(需經 CookiePolicy.set_ok() 方法批准)。

response 物件(通常是呼叫 urllib.request.urlopen() 或類似函式的結果)應支援一個 info() 方法,該方法返回一個 email.message.Message 例項。

request 物件(通常是 urllib.request.Request 的例項)必須支援 get_full_url() 方法,以及 hostunverifiableorigin_req_host 屬性,具體如 urllib.request 所述。該請求用於為 Cookie 屬性設定預設值,以及檢查是否允許設定該 Cookie。

在 3.3 版本發生變更: request 物件需要 origin_req_host 屬性。已移除對已棄用方法 get_origin_req_host() 的依賴。

CookieJar.set_policy(policy)

設定要使用的 CookiePolicy 例項。

CookieJar.make_cookies(response, request)

返回從 response 物件中提取的 Cookie 物件序列。

關於 responserequest 引數所需的介面,請參閱 extract_cookies() 的文件。

如果策略允許,則設定一個 Cookie

設定一個 Cookie,不檢查策略是否允許設定。

CookieJar.clear([domain[, path[, name]]])

清除一些 Cookie。

如果不帶引數呼叫,則清除所有 Cookie。如果給定一個引數,則只刪除屬於該 domain 的 Cookie。如果給定兩個引數,則刪除屬於指定 domain 和 URL path 的 Cookie。如果給定三個引數,則刪除具有指定 domainpathname 的 Cookie。

如果不存在匹配的 Cookie,則引發 KeyError

CookieJar.clear_session_cookies()

丟棄所有會話 Cookie。

丟棄所有 discard 屬性為 true 的 Cookie(通常是因為它們沒有 max-ageexpires Cookie 屬性,或者有明確的 discard Cookie 屬性)。對於互動式瀏覽器,會話結束通常對應於關閉瀏覽器視窗。

注意,save() 方法不會儲存會話 Cookie,除非你透過傳遞一個 true 的 ignore_discard 引數來請求儲存。

FileCookieJar 實現了以下附加方法:

FileCookieJar.save(filename=None, ignore_discard=False, ignore_expires=False)

將 Cookie 儲存到檔案。

此基類會引發 NotImplementedError。子類可以不實現此方法。

filename 是儲存 Cookie 的檔名。如果未指定 filename,則使用 self.filename(其預設值是傳遞給建構函式的值,如果有的話);如果 self.filenameNone,則引發 ValueError

ignore_discard:即使是被設定為丟棄的 Cookie 也儲存。ignore_expires:即使是已過期的 Cookie 也儲存。

如果檔案已存在,則會覆蓋它,從而清除其中包含的所有 Cookie。儲存的 Cookie 之後可以使用 load()revert() 方法恢復。

FileCookieJar.load(filename=None, ignore_discard=False, ignore_expires=False)

從檔案中載入 Cookie。

舊的 Cookie 會被保留,除非被新載入的 Cookie 覆蓋。

引數與 save() 的引數相同。

指定的檔案必須是該類所理解的格式,否則將引發 LoadError。此外,也可能引發 OSError,例如,如果檔案不存在。

在 3.3 版本發生變更: 過去會引發 IOError,現在它是 OSError 的別名。

FileCookieJar.revert(filename=None, ignore_discard=False, ignore_expires=False)

清除所有 Cookie 並從已儲存的檔案中重新載入 Cookie。

revert() 可能引發與 load() 相同的異常。如果發生故障,物件的狀態將不會被改變。

FileCookieJar 例項具有以下公共屬性:

FileCookieJar.filename

用於儲存 Cookie 的預設檔案的檔名。該屬性可以被賦值。

FileCookieJar.delayload

如果為真,則從磁碟延遲載入 Cookie。不應給該屬性賦值。這只是一個提示,因為它隻影響效能,不影響行為(除非磁碟上的 Cookie 正在改變)。CookieJar 物件可能會忽略它。標準庫中包含的 FileCookieJar 類都不會延遲載入 Cookie。

FileCookieJar 的子類以及與 Web 瀏覽器的協作

提供了以下 CookieJar 子類用於讀寫操作。

class http.cookiejar.MozillaCookieJar(filename=None, delayload=None, policy=None)

一個 FileCookieJar,可以以 Mozilla 的 cookies.txt 檔案格式(curl、Lynx 和 Netscape 瀏覽器也使用此格式)從磁碟載入和儲存 Cookie。

備註

這會丟失關於 RFC 2965 Cookie 的資訊,以及較新的或非標準的 Cookie 屬性,如 port

警告

如果你的 Cookie 丟失或損壞會帶來不便,請在儲存前備份你的 Cookie(存在一些微妙之處,可能導致檔案在載入/儲存往返過程中發生輕微變化)。

另請注意,在 Mozilla 執行時儲存的 Cookie 會被 Mozilla 覆蓋。

class http.cookiejar.LWPCookieJar(filename=None, delayload=None, policy=None)

一個 FileCookieJar,可以以與 libwww-perl 庫的 Set-Cookie3 檔案格式相容的格式從磁碟載入和儲存 Cookie。如果你想將 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,則會為 Cookie 路徑呼叫 path_return_ok()。否則,對於該 Cookie 域,永遠不會呼叫 path_return_ok()return_ok()。如果 path_return_ok() 返回 true,則會使用 Cookie 物件本身呼叫 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 協議。

CookiePolicy.rfc2965

實現 RFC 2965 協議。

CookiePolicy.hide_cookie2

不要向請求新增 Cookie2 標頭(此標頭的存在向伺服器表明我們理解 RFC 2965 Cookie)。

定義 CookiePolicy 類的最有用方法是繼承自 DefaultCookiePolicy 並重寫上述部分或全部方法。CookiePolicy 本身可以用作“空策略”,以允許設定和接收任何和所有 Cookie(這可能不太有用)。

DefaultCookiePolicy 物件

實現了接受和返回 Cookie 的標準規則。

RFC 2965 和 Netscape Cookie 都被涵蓋。預設情況下,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 介面所需的功能外,此類還允許您阻止和允許域設定和接收 Cookie。還有一些嚴格性開關,可以讓您稍微收緊相當寬鬆的 Netscape 協議規則(代價是阻止一些良性的 Cookie)。

提供了一個域黑名單和白名單(預設都關閉)。只有不在黑名單中且存在於白名單中(如果白名單是啟用的)的域才會參與 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 在設定或接收 Cookie 的黑名單上,則返回 True

DefaultCookiePolicy.allowed_domains()

返回 None,或允許的域名序列(以元組形式)。

DefaultCookiePolicy.set_allowed_domains(allowed_domains)

設定允許的域名序列,或 None

DefaultCookiePolicy.is_not_allowed(domain)

如果 domain 不在設定或接收 Cookie 的白名單上,則返回 True

DefaultCookiePolicy 例項具有以下屬性,這些屬性都從同名的建構函式引數初始化,並且都可以被賦值。

DefaultCookiePolicy.rfc2109_as_netscape

如果為 true,則請求 CookieJar 例項將 RFC 2109 Cookie(即在 Set-Cookie 標頭中收到的,版本 Cookie 屬性為 1 的 Cookie)降級為 Netscape Cookie,方法是將 Cookie 例項的版本屬性設定為 0。預設值為 None,在這種情況下,當且僅當 RFC 2965 處理被關閉時,RFC 2109 Cookie 才會被降級。因此,預設情況下 RFC 2109 Cookie 會被降級。

通用嚴格性開關

DefaultCookiePolicy.strict_domain

不允許網站設定具有國家程式碼頂級域名(如 .co.uk.gov.uk.co.nz 等)的雙部分域名。這遠非完美,並不能保證一定有效!

RFC 2965 協議嚴格性開關

DefaultCookiePolicy.strict_rfc2965_unverifiable

遵循 RFC 2965 關於不可驗證事務的規則(通常,不可驗證事務是由重定向或對託管在其他站點上的影像的請求產生的)。如果此值為 false,則 Cookie 永遠不會因可驗證性而被阻止。

Netscape 協議嚴格性開關

DefaultCookiePolicy.strict_ns_unverifiable

即使對於 Netscape Cookie,也應用 RFC 2965 關於不可驗證事務的規則。

DefaultCookiePolicy.strict_ns_domain

指示對 Netscape Cookie 的域匹配規則的嚴格程度的標誌。可接受的值見下文。

DefaultCookiePolicy.strict_ns_set_initial_dollar

忽略 Set-Cookie: 標頭中名稱以 '$' 開頭的 Cookie。

DefaultCookiePolicy.strict_ns_set_path

不允許設定其路徑與請求 URI 不匹配的 Cookie。

strict_ns_domain 是一個標誌集合。它的值透過或運算構造(例如,DomainStrictNoDots|DomainStrictNonDomain 意味著兩個標誌都已設定)。

DefaultCookiePolicy.DomainStrictNoDots

設定 Cookie 時,“主機字首”不能包含點(例如,www.foo.bar.com 不能為 .bar.com 設定 Cookie,因為 www.foo 包含一個點)。

DefaultCookiePolicy.DomainStrictNonDomain

未明確指定 domain Cookie 屬性的 Cookie 只能返回給與設定該 Cookie 的域相等的域(例如,spam.example.com 不會收到來自 example.com 且沒有 domain Cookie 屬性的 Cookie)。

DefaultCookiePolicy.DomainRFC2965Match

設定 Cookie 時,需要完全的 RFC 2965 域匹配。

以下屬性為方便起見而提供,是上述標誌的最有用組合:

DefaultCookiePolicy.DomainLiberal

等同於 0(即,上述所有 Netscape 域嚴格性標誌都關閉)。

DefaultCookiePolicy.DomainStrict

等同於 DomainStrictNoDots|DomainStrictNonDomain

示例

第一個示例展示了 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 cookie 開啟 URL(假設 cookie 檔案的位置遵循 Unix/Netscape 約定)

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 cookie,在設定和返回 Netscape cookie 時對域進行更嚴格的檢查,並阻止某些域設定或返回 cookie

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/")