20.21. cookielib — HTTPClient 端的 Cookie 处理

Note

cookielib模块在 Python 3 中已重命名为http.cookiejar2to3工具在将源转换为 Python 3 时将自动适应导入。

2.4 版的新Function。

源代码: Lib/cookielib.py


cookielib模块定义用于自动处理 HTTP cookie 的类。对于访问需要少量数据(* cookies *)的网站很有用,这些数据由来自 Web 服务器的 HTTP 响应在 Client 端计算机上设置,然后在以后的 HTTP 请求中返回给服务器。

常规 Netscape cookie 协议和 RFC 2965定义的协议都可以处理。 RFC 2965 处理默认情况下处于关闭状态。 RFC 2109 cookie 被解析为 Netscape cookie,然后根据有效的“策略”被视为 Netscape 或 RFC 2965 cookie。请注意,Internet 上的大多数 cookie 是 Netscape cookie。 cookielibtry遵循事实上的 Netscape cookie 协议(与原始 Netscape 规范中的设置大不相同),包括记下 RFC 2965 引入的max-ageport cookie 属性。

Note

在* Set-Cookie Set-Cookie2 Headers(例如domainexpires)中找到的各种命名参数通常称为 attributes 。为了将它们与 Python 属性区分开来,此模块的文档使用术语 cookie-attribute *代替。

该模块定义以下异常:

Note

为了与 Python 2.4 向后兼容(引发了IOError),LoadErrorIOError的子类。

提供了以下类:

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

CookieJar可以从磁盘上的文件加载 cookie,也可以将 cookie 保存到磁盘上的文件。在调用load()revert()方法之前,不会从命名文件中加载 Cookie。此类的子类在FileCookieJar 子类并与 Web 浏览器合作部分中记录。

DefaultCookiePolicy实现了 Netscape 和 RFC 2965 cookie 的标准接受/拒绝规则。默认情况下,根据 RFC 2965 规则处理 RFC 2109 cookie(即,在* Set-Cookie *Headers 中接收的 cookie 版本为 1 的 cookie)。但是,如果 RFC 2965 处理被关闭或rfc2109_as_netscapeTrue,则pass将Cookie实例的version属性设置为 0,CookieJar实例将CookieJar实例“降级”为 Netscape cookie。DefaultCookiePolicy还提供了一些参数以允许一些罚款。Policy 调整。

20.21.1. CookieJar 和 FileCookieJar 对象

CookieJar个对象支持iterator协议,以迭代包含的Cookie个对象。

CookieJar具有以下方法:

如果策略允许(即CookieJarCookiePolicy实例的rfc2965hide_cookie2属性分别为 true 和 false),则还将在适当时添加* Cookie2 *Headers。

CookieJar将在* response 参数中查找允许的 Set-Cookie Set-Cookie2 *Headers,并适当存储 cookie(以CookiePolicy.set_ok()方法的批准为准)。

请参阅extract_cookies()的文档,以获取* response request *参数所需的接口。

如果在不带参数的情况下调用,请清除所有 cookie。如果给定单个参数,则仅删除属于该域的 cookie。如果提供了两个参数,则将删除属于指定* domain *和 URL * path 的 cookie。如果给定三个参数,则将删除具有指定 domain path name *的 cookie。

如果不存在匹配的 cookie,则引发KeyError

丢弃所有包含具有 truediscard属性的 cookie(通常是因为它们没有max-ageexpires cookie 属性,也没有显式的discard cookie 属性)。对于交互式浏览器,会话结束通常对应于关闭浏览器窗口。

请注意,除非您pass传递 true * ignore_discard *参数询问,否则save()方法将不会保存会话 cookie。

FileCookieJar实现了以下其他方法:

该 Base Class 引发NotImplementedError。子类可能使此方法未实现。

如果该文件已经存在,则会被覆盖,从而清除其中包含的所有 cookie。以后可以使用load()revert()方法还原保存的 cookie。

保留旧的 cookie,除非被新加载的 cookie 覆盖。

参数与save()相同。

命名文件必须采用该类可以理解的格式,否则将引发LoadError。另外,例如,如果文件不存在,则可以引发IOError

Note

为了与 Python 2.4 向后兼容(引发了IOError),LoadErrorIOError的子类。

revert()可以引发与load()相同的 exception。如果发生故障,则不会更改对象的状态。

FileCookieJar个实例具有以下公共属性:

20.21.2. FileCookieJar 子类并与 Web 浏览器合作

提供以下CookieJar个子类以进行读写。

Note

Firefox Web 浏览器的版本 3 不再以cookies.txt文件格式写入 cookie。

Note

这将丢失有关 RFC 2965 cookie 的信息,以及有关较新的或非标准 cookie 属性(例如port)的信息。

Warning

如果您的 cookie 丢失/损坏不方便(在存储/保存往返过程中有些细微之处可能导致文件中的细微变化),则在保存前先备份 cookie。

另请注意,Mozilla 运行时保存的 cookie 将被 Mozilla 破坏。

20.21.3. CookiePolicy 对象

实现CookiePolicy接口的对象具有以下方法:

此方法是一种优化。它消除了检查带有特定域的每个 cookie 的需要(这可能涉及读取许多文件)。从domain_return_ok()path_return_ok()返回 true 会将所有工作留给return_ok()

如果domain_return_ok()对于 cookie 域返回 true,则path_return_ok()将被称为 cookie 路径。否则,永远不会为该 Cookie 域调用path_return_ok()return_ok()。如果path_return_ok()返回 true,则使用Cookie对象本身调用return_ok()以进行全面检查。否则,永远不会为该 cookie 路径调用return_ok()

请注意,每个* cookie 域都将调用domain_return_ok(),而不仅仅是 request *域。例如,如果请求域是"www.example.com",则可以同时使用".example.com""www.example.com"调用该函数。 path_return_ok()也是如此。

请参阅domain_return_ok()的文档。

除了实现上述方法之外,CookiePolicy接口的实现还必须提供以下属性,指示应使用哪些协议以及如何使用。所有这些属性都可以分配给它。

定义CookiePolicy类的最有用方法是从DefaultCookiePolicy继承子类并覆盖上面的一些或所有方法。 CookiePolicy本身可用作“空策略”,以允许设置和接收任何和所有 cookie(这不太可能有用)。

20.21.4. DefaultCookiePolicy 对象

实现用于接受和返回 cookie 的标准规则。

RFC 2965 和 Netscape cookie 都包括在内。 RFC 2965 处理默认情况下处于关闭状态。

提供自己的策略的最简单方法是在添加自己的其他检查之前,重写此类并在重写的实现中调用其方法:

import cookielib
class MyCookiePolicy(cookielib.DefaultCookiePolicy):
    def set_ok(self, cookie, request):
        if not cookielib.DefaultCookiePolicy.set_ok(self, cookie, request):
            return False
        if i_dont_want_to_store_this_cookie(cookie):
            return False
        return True

除了实现CookiePolicy接口所需的Function之外,此类还允许您阻止和允许域设置和接收 Cookie。还有一些严格性开关,使您可以稍微加强一些比较宽松的 Netscape 协议规则(以阻止某些良性 cookie 为代价)。

提供了域黑名单和白名单(默认情况下都关闭)。只有不在黑名单中并且存在于白名单中的域(如果白名单处于活动状态)才参与 cookie 设置和返回。使用* blocked_domains 构造函数参数以及blocked_domains()set_blocked_domains()方法(以及 allowed_domains *的相应参数和方法)。如果您设置了白名单,则可以pass将其设置为None来再次将其关闭。

阻止列表或允许列表中不以点开头的域必须等于要匹配的 Cookie 域。例如,"example.com"与黑名单条目"example.com"匹配,但"www.example.com"不匹配。以点开头的域也会与更多特定域匹配。例如,"www.example.com""www.coyote.example.com"都匹配".example.com"(但"example.com"本身不匹配)。 IP 地址是一个 exception,必须完全匹配。例如,如果 blocked_domains 包含"192.168.1.2"".168.1.2",则阻止 192.168.1.2,但不阻止 193.168.1.2.

DefaultCookiePolicy实现了以下其他方法:

DefaultCookiePolicy实例具有以下属性,这些属性都是从同名的构造函数参数中初始化的,并且可以全部分配给它们。

2.5 版的新Function。

一般严格性开关:

RFC 2965 协议严格性开关:

Netscape 协议严格性开关:

strict_ns_domain是标志的集合。它的值是pass“或”运算得到的(例如DomainStrictNoDots|DomainStrictNonDomain表示两个标志都被设置)。

为了方便起见,提供了以下属性,它们是上述标志的最有用的组合:

Cookie实例的 Python 属性大致对应于各种 cookie 标准中指定的标准 cookie 属性。对应关系不是Pair一的,因为分配默认值有复杂的规则,因为max-ageexpires cookie 属性包含等效信息,并且 RFC 2109 cookie 可能被cookielib从版本 1 降级到版本 0. (Netscape)Cookie。

除非在CookiePolicy方法中的极少数情况下,否则不必分配这些属性。该类不强制内部一致性,因此您应该知道自己在做什么。

2.5 版的新Function。

Cookies 可能还有其他非标准的 Cookie 属性。可以使用以下方法访问这些文件:

Cookie类还定义了以下方法:

20.21.6. Examples

第一个示例显示了cookielib的最常见用法:

import cookielib, urllib2
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

此示例说明了如何使用 Netscape,Mozilla 或 Lynx cookie 打开 URL(假定 cookie 文件的位置采用 Unix/Netscape 约定):

import os, cookielib, urllib2
cj = cookielib.MozillaCookieJar()
cj.load(os.path.join(os.path.expanduser("~"), ".netscape", "cookies.txt"))
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

下一个示例说明了DefaultCookiePolicy的用法。打开 RFC 2965 cookie,在设置和返回 Netscape cookie 时更加严格地对待域,并阻止某些域设置 cookie 或返回它们:

import urllib2
from cookielib import CookieJar, DefaultCookiePolicy
policy = DefaultCookiePolicy(
    rfc2965=True, strict_ns_domain=DefaultCookiePolicy.DomainStrict,
    blocked_domains=["ads.net", ".ads.net"])
cj = CookieJar(policy)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")
首页