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.
Both the regular Netscape cookie protocol and the protocol defined by
RFC 2965 are handled. RFC 2965 handling is switched off by default.
RFC 2109 cookies are parsed as Netscape cookies and subsequently treated
either as Netscape or RFC 2965 cookies according to the 'policy' in effect.
Note that the great majority of cookies on the internet are Netscape cookies.
http.cookiejar attempts to follow the de-facto Netscape cookie protocol (which
differs substantially from that set out in the original Netscape specification),
including taking note of the max-age and port cookie-attributes
introduced with RFC 2965.
備註
在 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¶
This class represents Netscape, RFC 2109 and RFC 2965 cookies. It is not expected that users of
http.cookiejarconstruct their ownCookieinstances. Instead, if necessary, callmake_cookies()on aCookieJarinstance.
也參考
urllib.request模組URL 打開時會自動處理 cookie。
http.cookies模組HTTP cookie classes, principally useful for server-side code. The
http.cookiejarandhttp.cookiesmodules do not depend on each other.- https://curl.se/rfc/cookie_spec.html
The specification of the original Netscape cookie protocol. Though this is still the dominant protocol, the 'Netscape cookie protocol' implemented by all the major browsers (and
http.cookiejar) only bears a passing resemblance to the one sketched out incookie_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 instances have Python attributes roughly corresponding to the
standard cookie-attributes specified in the various cookie standards. The
correspondence is not one-to-one, because there are complicated rules for
assigning default values, because the max-age and expires
cookie-attributes contain equivalent information, and because RFC 2109 cookies
may be 'downgraded' by http.cookiejar from version 1 to version 0 (Netscape)
cookies.
除了在 CookiePolicy 方法中的罕見情況外,不應該對這些屬性進行指定。 這個類別不會強制執行內部一致性,所以如果你這麼做,你應該要知道你在做什麼。
- Cookie.version¶
Integer or
None. Netscape cookies haveversion0. RFC 2965 and RFC 2109 cookies have aversioncookie-attribute of 1. However, note thathttp.cookiejarmay 'downgrade' RFC 2109 cookies to Netscape cookies, in which caseversionis 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¶
Trueif this cookie was received as an RFC 2109 cookie (ie. the cookie arrived in a Set-Cookie header, and the value of the Version cookie-attribute in that header was 1). This attribute is provided becausehttp.cookiejarmay 'downgrade' RFC 2109 cookies to Netscape cookies, in which caseversionis 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 是否已在指定時間過期。
範例¶
The first example shows the most common usage of 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/")