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