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

原始碼: Lib/http/cookiejar.py


http.cookiejar 模組定義了用於自動處理 HTTP Cookie 的類。它對於訪問需要由 Web 伺服器的 HTTP 響應在客戶端機器上設定少量資料(cookies)的網站非常有用,然後在以後的 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)通常稱為屬性。為了將它們與 Python 屬性區分開來,此模組的文件使用了術語Cookie 屬性

該模組定義了以下異常

exception http.cookiejar.LoadError

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

在 3.3 版本中更改: LoadError 曾經是 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 引數支援 類路徑物件

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(即在帶有版本 cookie 屬性為 1 的 Set-Cookie 標頭中收到的 cookie)根據 RFC 2965 規則處理。但是,如果關閉了 RFC 2965 處理,或者 rfc2109_as_netscapeTrue,則 RFC 2109 cookie 將被 CookieJar 例項“降級”為 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 廢棄。使用 Set-Cookie,版本為 1。

RFC 2965 - HTTP 狀態管理機制

修復了錯誤的 Netscape 協議。使用 Set-Cookie2 代替 Set-Cookie。不常用。

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

RFC 2965 的未完成的勘誤。

RFC 2964 - HTTP 狀態管理的使用

CookieJar 和 FileCookieJar 物件

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

CookieJar 具有以下方法

將正確的 Cookie 標頭新增到 request

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

request 物件(通常是 urllib.request.Request 例項)必須支援方法 get_full_url()has_header()get_header()header_items()add_unredirected_header() 和屬性 hosttypeunverifiableorigin_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() 方法以及 host, unverifiableorigin_req_host 屬性,如 urllib.request 文件所述。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。

丟棄所有具有 true discard 屬性的包含的 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。可以使用 load()revert() 方法在以後還原已儲存的 cookie。

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

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

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

提供了以下 CookieJar 子類,用於讀取和寫入。

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

一個 FileCookieJar,可以從磁碟載入 Cookie 並以 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,可以從磁碟載入 Cookie 並以與 libwww-perl 庫的 Set-Cookie3 檔案格式相容的格式儲存 Cookie 到磁碟。如果你想將 Cookie 儲存在人類可讀的檔案中,這將非常方便。

在 3.8 版本中更改: filename 引數支援 類路徑物件

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(即,在帶有版本 Cookie 屬性為 1 的 Set-Cookie 標頭中接收的 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(假設 Unix/Netscape 關於 cookie 檔案位置的約定)

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 或返回 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/")