http.cookiejar
— 用于 HTTP 客户端的 Cookie 处理¶
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-age
和 port
Cookie 属性。
注意
Set-Cookie 和 Set-Cookie2 标头中找到的各种命名参数(例如 domain
和 expires
)通常被称为 属性。为了将它们与 Python 属性区分开来,本文档使用术语 Cookie 属性 来代替。
该模块定义了以下异常
- 异常 http.cookiejar.LoadError¶
FileCookieJar
的实例在无法从文件加载 Cookie 时引发此异常。LoadError
是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。默认情况下,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
实例会通过将Cookie
实例的version
属性设置为 0,将 RFC 2109 Cookie“降级”为 Netscape Cookie。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。未被广泛使用。
- http://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
实例)必须支持urllib.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 中提取 Cookie,并在策略允许的情况下将其存储在
CookieJar
中。CookieJar
将在 response 参数中查找允许的 Set-Cookie 和 Set-Cookie2 标头,并根据需要存储 Cookie(需经CookiePolicy.set_ok()
方法的批准)。response 对象(通常是调用
urllib.request.urlopen()
或类似方法的结果)应支持info()
方法,该方法返回一个email.message.Message
实例。request 对象(通常是
urllib.request.Request
实例)必须支持urllib.request
文档中所述的get_full_url()
方法以及host
、unverifiable
和origin_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
对象序列。有关 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
属性为真的 Cookie(通常是因为它们没有max-age
或expires
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.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
,可以使用 Mozillacookies.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
类的最有用的方法是从 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
实例通过将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_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.DomainLiberal¶
等效于 0(即,所有上述 Netscape 域严格性标志都已关闭)。
- DefaultCookiePolicy.DomainStrict¶
等效于
DomainStrictNoDots|DomainStrictNonDomain
。
Cookie 对象¶
Cookie
实例具有大致对应于各种 Cookie 标准中指定的标准 Cookie 属性的 Python 属性。这种对应关系不是一对一的,因为分配默认值有复杂的规则,因为 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¶
自纪元以来的整数到期日期(以秒为单位),或
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/")