http.cookiejar
— HTTP 客戶端的 Cookie 處理¶
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-age
和 port
Cookie 屬性。
備註
在 Set-Cookie 和 Set-Cookie2 頭中找到的各種命名引數(例如 domain
和 expires
)通常被稱為 attributes (屬性)。為了與 Python 的屬性 (attribute) 區分開來,本模組的文件使用術語 cookie-attribute (Cookie 屬性)。
該模組定義了以下異常:
- exception http.cookiejar.LoadError¶
FileCookieJar
的例項在從檔案載入 Cookie 失敗時會引發此異常。LoadError
是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。預設情況下,https 和 wss (安全 WebSocket) 被視為安全協議。對於所有其他引數,請參閱CookiePolicy
和DefaultCookiePolicy
物件的文件。DefaultCookiePolicy
實現了針對 Netscape 和 RFC 2965 Cookie 的標準接受/拒絕規則。預設情況下,RFC 2109 Cookie(即在 Set-Cookie 頭部中收到的,版本 Cookie 屬性為 1 的 Cookie)會根據 RFC 2965 規則處理。然而,如果 RFC 2965 處理被關閉,或者rfc2109_as_netscape
為True
,CookieJar
例項會將 RFC 2109 Cookie“降級”為 Netscape Cookie,方法是將Cookie
例項的version
屬性設定為 0。DefaultCookiePolicy
還提供了一些引數以允許對策略進行一些微調。
- class http.cookiejar.Cookie¶
這個類代表 Netscape、RFC 2109 和 RFC 2965 Cookie。不希望
http.cookiejar
的使用者自己構造Cookie
例項。如有必要,應在CookieJar
例項上呼叫make_cookies()
。
參見
- 模組
urllib.request
使用自動 Cookie 處理開啟 URL。
- 模組
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 廢棄。使用帶有 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
具有以下方法:
- CookieJar.add_cookie_header(request)¶
向 request 新增正確的 Cookie 標頭。
如果策略允許(即,
CookieJar
的CookiePolicy
例項的rfc2965
和hide_cookie2
屬性分別為 true 和 false),則在適當時也會新增 Cookie2 標頭。request 物件(通常是
urllib.request.Request
的例項)必須支援get_full_url()
,has_header()
,get_header()
,header_items()
,add_unredirected_header()
方法,以及host
,type
,unverifiable
和origin_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-Cookie 和 Set-Cookie2 標頭,並根據情況儲存 Cookie(需經CookiePolicy.set_ok()
方法批准)。response 物件(通常是呼叫
urllib.request.urlopen()
或類似函式的結果)應支援一個info()
方法,該方法返回一個email.message.Message
例項。request 物件(通常是
urllib.request.Request
的例項)必須支援get_full_url()
方法,以及host
、unverifiable
和origin_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
物件序列。關於 response 和 request 引數所需的介面,請參閱
extract_cookies()
的文件。
- CookieJar.clear([domain[, path[, name]]])¶
清除一些 Cookie。
如果不帶引數呼叫,則清除所有 Cookie。如果給定一個引數,則只刪除屬於該 domain 的 Cookie。如果給定兩個引數,則刪除屬於指定 domain 和 URL path 的 Cookie。如果給定三個引數,則刪除具有指定 domain、path 和 name 的 Cookie。
如果不存在匹配的 Cookie,則引發
KeyError
。
- CookieJar.clear_session_cookies()¶
丟棄所有會話 Cookie。
丟棄所有
discard
屬性為 true 的 Cookie(通常是因為它們沒有max-age
或expires
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.filename
是None
,則引發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
,例如,如果檔案不存在。
- FileCookieJar.revert(filename=None, ignore_discard=False, ignore_expires=False)¶
清除所有 Cookie 並從已儲存的檔案中重新載入 Cookie。
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
類的最有用方法是繼承自 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.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_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.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-attribute 為 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¶
如果這是一個會話 cookie,則為
True
。
- Cookie.rfc2109¶
如果此 cookie 是作為 RFC 2109 cookie 接收的(即 cookie 是在 Set-Cookie 標頭中到達的,並且該標頭中 Version cookie-attribute 的值為 1),則為
True
。提供此屬性是因為http.cookiejar
可能會將 RFC 2109 cookie“降級”為 Netscape cookie,在這種情況下version
為 0。
- Cookie.port_specified¶
如果伺服器明確指定了一個或一組埠(在 Set-Cookie / Set-Cookie2 標頭中),則為
True
。
- Cookie.domain_specified¶
如果伺服器明確指定了域,則為
True
。
- Cookie.domain_initial_dot¶
如果伺服器明確指定的域以點(
'.'
)開頭,則為True
。
Cookie 可能具有其他非標準的 cookie-attribute。可以使用以下方法訪問它們
- Cookie.has_nonstandard_attr(name)¶
如果 cookie 具有指定的 cookie-attribute,則返回
True
。
- Cookie.get_nonstandard_attr(name, default=None)¶
如果 cookie 具有指定的 cookie-attribute,則返回其值。否則,返回 default。
- Cookie.set_nonstandard_attr(name, value)¶
設定指定的 cookie-attribute 的值。
Cookie
類還定義了以下方法
- Cookie.is_expired(now=None)¶
如果 cookie 已超過伺服器請求其應過期的時刻,則為
True
。如果給定了 now(以 epoch 以來的秒數),則返回 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 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/")