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 *代替。

该模块定义以下异常:

  • exception cookielib. LoadError
    • FileCookieJar实例在无法从文件加载 cookie 时引发此异常。

Note

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

提供了以下类:

    • class * cookielib. CookieJar(* policy = None *)

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

    • class * cookielib. FileCookieJar(* filename delayload = None policy = None *)
      • policy *是实现CookiePolicy接口的对象。有关其他参数,请参见相应属性的文档。

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

  • 类别 cookielib. CookiePolicy

    • 此类负责确定是否应从服务器接受每个 cookie 或将其返回给服务器。
  • 类别 cookielib. DefaultCookiePolicy((* blocked_domains = None allowed_domains = None netscape = True rfc2965 = False rfc2109_as_netscape = None hide_cookie2 = False strict_domain = False strict_rfc2965_unverifi = True strict_ns_unverifiable = False strict_ns_domain = DefaultCookiePolicy.DomainLiberal strict_ns_set_initial_dollar = False strict_ns_set_path = False *)

    • 构造函数参数只能作为关键字参数传递。 * blocked_domains *是一连串的域名,我们从不接受 Cookie,也不向其返回 Cookie。 * allowed_domains *(如果不是None),这是我们接受并返回 Cookie 的唯一域的序列。有关其他所有参数,请参见CookiePolicyDefaultCookiePolicy对象的文档。

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 调整。

  • 类别 cookielib. Cookie
    • 此类表示 Netscape,RFC 2109 和 RFC 2965 cookie。不应期望cookielib的用户构造自己的Cookie实例。相反,如有必要,请在CookieJar实例上调用make_cookies()

20.21.1. CookieJar 和 FileCookieJar 对象

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

CookieJar具有以下方法:

  • CookieJar. add_cookie_header(* request *)
    • 将正确的* Cookie Headers 添加到 request *。

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

  • request *对象(通常是urllib2.Request实例)必须支持方法get_full_url()get_host()get_type()unverifiable()get_origin_req_host()has_header()get_header()header_items()add_unredirected_header(),如urllib2所述。
  • CookieJar. extract_cookies(响应请求)
    • 从 HTTP“响应”中提取 Cookie,并将其存储在CookieJar中(在策略允许的范围内)。

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

  • response *对象(通常是对urllib2.urlopen()的调用或类似结果)应支持info()方法,该方法返回带有getallmatchingheaders()方法的对象(通常是mimetools.Message实例)。

  • request *对象(通常是urllib2.Request实例)必须支持方法get_full_url()get_host()unverifiable()get_origin_req_host(),如urllib2所述。该请求用于设置 cookie 属性的默认值,以及检查是否允许设置 cookie。

  • CookieJar. set_policy(* policy *)

  • CookieJar. make_cookies(响应请求)

    • 从* response *对象中提取的Cookie个对象的返回序列。

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

  • CookieJar. set_cookie_if_ok(* cookie request *)

    • 如果 Policy 认为可以的话,请设置Cookie
  • CookieJar. set_cookie(* cookie *)

    • 设置Cookie,而无需检查策略是否设置。
  • CookieJar. clear([ [,路径 [,名称]]])

    • 清除一些 cookie。

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

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

  • CookieJar. clear_session_cookies ( )
    • 丢弃所有会话 cookie。

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

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

FileCookieJar实现了以下其他方法:

  • FileCookieJar. save(* filename = None ignore_discard = False ignore_expires = False *)
    • 将 Cookie 保存到文件中。

该 Base Class 引发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。另外,例如,如果文件不存在,则可以引发IOError

Note

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

  • FileCookieJar. revert(* filename = None ignore_discard = False ignore_expires = False *)
    • 清除所有 cookie 并从已保存的文件中重新加载 cookie。

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

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

  • FileCookieJar. filename

    • 保留 cookie 的默认文件的文件名。该属性可以被分配给。
  • FileCookieJar. delayload

    • 如果为 true,则从磁盘延迟加载 cookie。此属性不应分配给它。这只是一个提示,因为这只会影响性能,而不会影响行为(除非磁盘上的 cookie 发生变化)。 CookieJar对象可能会忽略它。标准库中包含的FileCookieJar类都没有延迟加载 cookie。

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

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

    • class * cookielib. MozillaCookieJar(* filename delayload = None policy = None *)
    • 一个FileCookieJar可以以 Mozilla cookies.txt文件格式(Lynx 和 Netscape 浏览器也使用)将 cookie 加载并保存到磁盘上。

Note

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

Note

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

Warning

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

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

    • class * cookielib. LWPCookieJar(* filename delayload = None policy = None *)
    • FileCookieJar可以以与 libwww-perl 库的Set-Cookie3文件格式兼容的格式从 cookie 加载并将 cookie 保存到磁盘。如果要将 cookie 存储在人类可读的文件中,这很方便。

20.21.3. CookiePolicy 对象

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

  • CookiePolicy. set_ok(* cookie request *)
    • 返回指示是否应从服务器接受 cookie 的布尔值。
  • CookiePolicy. return_ok(* cookie request *)
    • 返回布尔值,指示是否应将 cookie 返回给服务器。
  • CookiePolicy. domain_return_ok(* domain request *)
    • 给定 cookie 域,如果不应该返回 cookie,则返回 false。

此方法是一种优化。它消除了检查带有特定域的每个 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()也是如此。

  • CookiePolicy. path_return_ok(* path request *)
    • 给定 cookie 路径,如果不应该返回 cookie,则返回 false。

请参阅domain_return_ok()的文档。

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

  • CookiePolicy. netscape

    • 实现 Netscape 协议。
  • CookiePolicy. rfc2965

    • 实施 RFC 2965 协议。
  • CookiePolicy. hide_cookie2

    • 不要在请求中添加* Cookie2 *Headers(此 Headers 的存在向服务器表明我们了解 RFC 2965 cookie)。

定义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. blocked_domains ( )

    • 返回被阻止的域的序列(作为 Tuples)。
  • DefaultCookiePolicy. set_blocked_domains(* blocked_domains *)

    • 设置阻止域的 Sequences。
  • DefaultCookiePolicy. is_blocked(* domain *)

    • 返回* domain *是否在黑名单上以设置或接收 cookie。
  • DefaultCookiePolicy. allowed_domains ( )

    • 返回None或允许的域序列(以 Tuples 的形式)。
  • DefaultCookiePolicy. set_allowed_domains(* allowed_domains *)

    • 设置允许域的 Sequences,或None
  • DefaultCookiePolicy. is_not_allowed(* domain *)

    • 返回* domain *是否不在白名单上以设置或接收 Cookie。

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

  • DefaultCookiePolicy. rfc2109_as_netscape
    • 如果为 true,则pass将Cookie实例的 version 属性设置为 0,请求CookieJar实例将 RFC 2109 cookie(即,在* Set-Cookie *Headers 中接收的 cookie 的版本 cookie 属性为 1)降级为 Netscape cookie。默认值为None,在这种情况下,并且仅当关闭 RFC 2965 处理时,RFC 2109 cookie 才会降级。因此,默认情况下会降级 RFC 2109 cookie。

2.5 版的新Function。

一般严格性开关:

  • DefaultCookiePolicy. strict_domain
    • 不允许网站使用国家代码顶级域名(例如.co.uk.gov.uk.co.nz等)来设置两部分域名。这远非完美,不能保证能正常工作!

RFC 2965 协议严格性开关:

  • DefaultCookiePolicy. strict_rfc2965_unverifiable
    • 遵循 RFC 2965 规则对不可验证的 Transaction(通常,不可验证的 Transaction 是重定向或请求托管在另一个站点上的映像所导致的 Transaction)。如果这是错误的,则基于可验证性,绝不会阻止 Cookie

Netscape 协议严格性开关:

  • DefaultCookiePolicy. strict_ns_unverifiable

    • 将 RFC 2965 规则应用于不可验证的事务,甚至应用于 Netscape cookie。
  • DefaultCookiePolicy. strict_ns_domain

    • 指示 Netscape cookie 的域匹配规则的严格程度的标志。请参阅下面的可接受值。
  • DefaultCookiePolicy. strict_ns_set_initial_dollar

    • 忽略 Set-Cookie 中的 cookie:标题以'$'开头的 Headers。
  • DefaultCookiePolicy. strict_ns_set_path

    • 不允许设置其路径与请求 URI 不匹配的 cookie。

strict_ns_domain是标志的集合。它的值是pass“或”运算得到的(例如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

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

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

  • Cookie. version

    • 整数或None。 Netscape cookie 的值为version0.RFC2965 和 RFC 2109 cookie 的version cookie 属性为 1.但是,请注意,cookielib可能会将 RFC 2109 cookie 降级为 Netscape cookie,在这种情况下version为 0.
  • Cookie. name

    • Cookie 名称(字符串)。
  • Cookie. value

    • Cookie 值(字符串)或None
  • Cookie. port

    • 代表端口或一组端口(例如'80'或'80,8080')或None的字符串。
  • Cookie. path

    • Cookie 路径(字符串,例如'/acme/rocket_launchers')。
  • Cookie. secure

    • True,如果仅应pass安全连接返回 cookie。
  • Cookie. expires

    • 从纪元以来的整数有效日期(以秒为单位)或None。另请参见is_expired()方法。
  • Cookie. discard

    • True(如果这是会话 cookie)。
  • Cookie. comment

    • 来自服务器的字符串 Comments,用于解释此 cookie 的Function,或None
  • Cookie. comment_url

    • 链接到服务器上解释此 cookie 的Function的 Comments 的 URL 或None
  • Cookie. rfc2109

    • True(如果此 cookie 作为 RFC 2109 cookie 被接收到(即该 cookie 到达* Set-Cookie *Headers,并且该 Headers 中的 Version cookie 属性的值为 1))。提供此属性是因为cookielib可能将 RFC 2109 cookie 降级为 Netscape cookie,在这种情况下version为 0.

2.5 版的新Function。

  • Cookie. port_specified

    • True如果服务器明确指定了一个端口或一组端口(在* Set-Cookie / Set-Cookie2 *Headers 中)。
  • Cookie. domain_specified

    • True如果服务器明确指定了域。
  • Cookie. domain_initial_dot

    • 如果服务器明确指定的域以点('.')开头,则为True

Cookies 可能还有其他非标准的 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类还定义了以下方法:

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