http.cookiejar — 用于 HTTP 客户端的 Cookie 处理

源代码: Lib/http/cookiejar.py


http.cookiejar 模块定义了用于自动处理 HTTP Cookie 的类。它对于访问需要在客户端机器上设置小块数据(即 Cookie)的网站非常有用,这些数据由 Web 服务器的 HTTP 响应设置,并在以后的 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 属性 来代替。

该模块定义了以下异常

异常 http.cookiejar.LoadError

FileCookieJar 的实例在无法从文件加载 Cookie 时引发此异常。LoadErrorOSError 的子类。

在 3.3 版更改: LoadError 曾经是 IOError 的子类型,现在是 OSError 的别名。

提供了以下类

http.cookiejar.CookieJar(policy=None)

policy 是一个实现 CookiePolicy 接口的对象。

CookieJar 类存储 HTTP Cookie。它从 HTTP 请求中提取 Cookie,并在 HTTP 响应中返回它们。CookieJar 实例会在必要时自动使包含的 Cookie 过期。子类还负责从文件或数据库中存储和检索 Cookie。

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

policy 是一个实现 CookiePolicy 接口的对象。有关其他参数,请参阅相应属性的文档。

一个 CookieJar,它可以从磁盘上的文件加载 Cookie,并且可以将 Cookie 保存到磁盘上的文件。在调用 load()revert() 方法之前,不会 从指定的文件加载 Cookie。此类的子类记录在 FileCookieJar 子类以及与 Web 浏览器的协作 部分中。

不应直接初始化此类,而应使用其下面的子类。

在 3.8 版更改: filename 参数支持 类路径对象

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_netscapeTrue,则 CookieJar 实例会通过将 Cookie 实例的 version 属性设置为 0,将 RFC 2109 Cookie“降级”为 Netscape Cookie。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。未被广泛使用。

http://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 实例)必须支持 urllib.request 文档中所述的 get_full_url()has_header()get_header()header_items()add_unredirected_header() 方法以及 hosttypeunverifiableorigin_req_host 属性。

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 实例)必须支持 urllib.request 文档中所述的 get_full_url() 方法以及 hostunverifiableorigin_req_host 属性。该请求用于设置 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 属性为真的 Cookie(通常是因为它们没有 max-ageexpires Cookie 属性,或者具有显式的 discard Cookie 属性)。对于交互式浏览器,会话结束通常对应于关闭浏览器窗口。

请注意,除非您通过传递值为真的 ignore_discard 参数来请求,否则 save() 方法不会保存会话 Cookie。

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() 相同的异常。如果出现故障,则对象的 state 将不会更改。

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,可以使用 Mozilla cookies.txt 文件格式(curl 以及 Lynx 和 Netscape 浏览器也使用此格式)从磁盘加载 Cookie 并将 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 保存到磁盘。如果您想将 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 实例通过将 Cookie 实例的版本属性设置为 0,将 RFC 2109 Cookie(即在版本 Cookie 属性为 1 的 Set-Cookie 标头中接收到的 Cookie)降级为 Netscape Cookie。默认值为 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 不会收到来自没有 domain Cookie 属性的 example.com 的 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/")