http.cookiejar
— HTTP 客户端的 Cookie 处理¶
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-age
和 port
Cookie 属性。
注解
在 Set-Cookie 和 Set-Cookie2 标头中找到的各种命名参数(例如 domain
和 expires
)通常称为属性。为了将它们与 Python 属性区分开来,此模块的文档使用了术语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 参数支持 类路径对象。
- 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(即在带有版本 cookie 属性为 1 的 Set-Cookie 标头中收到的 cookie)根据 RFC 2965 规则处理。但是,如果关闭了 RFC 2965 处理,或者rfc2109_as_netscape
为True
,则 RFC 2109 cookie 将被CookieJar
实例“降级”为 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 废弃。使用 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
具有以下方法
- CookieJar.add_cookie_header(request)¶
将正确的 Cookie 标头添加到 request。
如果策略允许(即
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
文档所述。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。
丢弃所有具有 true
discard
属性的包含的 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。可以使用
load()
或revert()
方法在以后还原已保存的 cookie。
- 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¶
如果为 true,则从磁盘延迟加载 Cookie。此属性不应被赋值。这只是一个提示,因为它只会影响性能,而不会影响行为(除非磁盘上的 Cookie 正在更改)。
CookieJar
对象可能会忽略它。标准库中包含的FileCookieJar
类都不会延迟加载 Cookie。
FileCookieJar 子类以及与 Web 浏览器的协作¶
提供了以下 CookieJar
子类,用于读取和写入。
- class http.cookiejar.MozillaCookieJar(filename=None, delayload=None, policy=None)¶
一个
FileCookieJar
,可以从磁盘加载 Cookie 并以 Mozillacookies.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
类最有用的方法是通过从 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(即,在带有版本 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_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 属性为 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 属性的值为 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 属性。可以使用以下方法访问它们
- 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 在指定时间是否已过期。
示例¶
第一个示例展示了 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/")