# 21.24. `http.cookiejar` - HTTP客户端的Cookie处理

源代码： Lib / http / cookiejar.py

`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规范中的协议大不相同），包括注意`max-age`和使用RFC 2965引入的`port` cookie属性。

注意

在Set-Cookie和Set-Cookie2标头中找到的各种命名参数（例如。`domain`和`expires`）通常被称为属性。为了将它们与Python属性区分开来，本模块的文档使用术语cookie-attribute。

模块定义了以下异常：

exception `http.cookiejar.``LoadError`

  `FileCookieJar`的实例在从文件加载Cookie失败时引发此异常。`LoadError`是`OSError`的子类。

  在版本3.3中已更改： LoadError已成为`OSError`的子类，而不是`IOError`。

提供以下类：

class `http.cookiejar.``CookieJar`(policy=None)

  policy是实现`CookiePolicy`接口的对象。

  `CookieJar`类存储HTTP Cookie。它从HTTP请求中提取Cookie，并在HTTP响应中返回。`CookieJar`实例会在必要时自动过期包含的Cookie。The CookieJar class stores HTTP cookies. It extracts cookies from HTTP requests, and returns them in HTTP responses. CookieJar instances automatically expire contained cookies when necessary. Subclasses are also responsible for storing and retrieving cookies from a file or database.

class `http.cookiejar.``FileCookieJar`(filename, delayload=None, policy=None)

  policy是实现`CookiePolicy`接口的对象。有关其他参数，请参阅相应属性的文档。

  `CookieJar`可以从磁盘上的文件加载Cookie，或者保存Cookie到文件。在`load()`或`revert()`方法被调用之前，从指定文件加载NOT 此类的子类在FileCookieJar subclasses and co-operation with web browsers部分中进行了说明。

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)

  构造函数参数只应作为关键字参数传递。blocked_domains是一系列域名，我们从不接受Cookie，也不会将Cookie传回。allowed_domains如果不是`None`，这是我们接受并返回Cookie的唯一域的序列。对于所有其他参数，请参阅`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处理的网址打开。
模块`http.cookies`
  HTTP cookie类，主要用于服务器端代码。`http.cookiejar`和`http.cookies`模块不依赖于彼此。
https://curl.haxx.se/rfc/cookie_spec.html T0>
  原始Netscape Cookie协议的规范。尽管这仍然是主要的协议，但是所有主要浏览器（和`http.cookiejar`）实现的“Netscape cookie协议”只是与在`cookie_spec.html`。
RFC 2109 - HTTP状态管理机制
  由RFC 2965已过时。使用版本= 1的Set-Cookie。
RFC 2965 - HTTP状态管理机制
  Netscape协议修复了错误。使用Set-Cookie2代替Set-Cookie。不广泛使用。
http://kristol.org/cookie/errata.html T0>
  RFC 2965的未完成勘误表。

RFC 2964 - 使用HTTP状态管理

## 21.24.1. CookieJar和FileCookieJar对象

`CookieJar`对象支持iterator协议，用于对包含的`Cookie`对象进行迭代。

`CookieJar`有以下方法：

`CookieJar.``add_cookie_header`(request)

  将Cookie标头添加到请求。

  如果政策允许（即。`CookieJar`的`CookiePolicy`实例的`rfc2965`和`hide_cookie2`属性分别为true和false）， Cookie2标题也会在适当时添加。

  The request object (usually a `urllib.request..Request` instance) must support the methods `get_full_url()`, `get_host()`, `get_type()`, `unverifiable()`, `has_header()`, `get_header()`, `header_items()`, `add_unredirected_header()` and `origin_req_host` attribute as documented by `urllib.request`.

  在版本3.3： 请求对象需要`origin_req_host`属性中更改。依赖于已弃用的方法`get_origin_req_host()`已被移除。

`CookieJar.``extract_cookies`(response, request)

  从HTTP 响应中提取Cookie，并将其存储在策略允许的`CookieJar`中。

  `CookieJar`将在响应参数中查找允许的Set-Cookie和Set-Cookie2 （根据`CookiePolicy.set_ok()`方法的批准）。

  响应对象（通常调用`urllib.request.urlopen()`或类似的结果）应支持`info()`方法，它返回`email.message.Message`实例。

  The request object (usually a `urllib.request.Request` instance) must support the methods `get_full_url()`, `get_host()`, `unverifiable()`, and `origin_req_host` attribute, as documented by `urllib.request`. 请求用于设置cookie属性的默认值以及检查是否允许设置cookie。

  在版本3.3： 请求对象需要`origin_req_host`属性中更改。依赖于已弃用的方法`get_origin_req_host()`已被移除。

`CookieJar.``set_policy`(policy)

  设置要使用的`CookiePolicy`实例。

`CookieJar.``make_cookies`(response, request)

  从响应对象提取的`Cookie`对象的返回序列。

  有关响应和请求参数所需的接口，请参阅`extract_cookies()`的文档。

`CookieJar.``set_cookie_if_ok`(cookie, request)

  如果政策声明可以这么做，请设置`Cookie`。

`CookieJar.``set_cookie`(cookie)

  设置`Cookie`，而不检查政策是否应该设置。

`CookieJar.``clear`([domain[, path[, name]]])

  清除一些cookie。

  如果没有参数调用，请清除所有Cookie。如果给定单个参数，则只会删除属于域的Cookie。如果给定两个参数，将删除属于指定的域和URL 路径的Cookie。如果给出三个参数，则会删除指定的域，路径和名称的Cookie。

  如果没有匹配的Cookie，则引发`KeyError`。

`CookieJar.``clear_session_cookies`()

  舍弃所有会话Cookie。

  丢弃所有包含具有真实`discard`属性的Cookie（通常是因为它们没有`max-age`或`expires` cookie属性， `discard` cookie-attribute）。对于交互式浏览器，会话的结束通常对应于关闭浏览器窗口。

  注意，除非你通过传递一个真实的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。保存的Cookie可以稍后使用`load()`或`revert()`方法恢复。

`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。

## 21.24.2. FileCookieJar子类和与web浏览器的合作

提供以下`CookieJar`子类用于读取和写入。

class `http.cookiejar.``MozillaCookieJar`(filename, delayload=None, policy=None)

  可以使用Mozilla `cookies.txt`文件格式（也由Lynx和Netscape浏览器使用）加载并将Cookie保存到磁盘的`FileCookieJar`。

  注意

  这会丢失有关RFC 2965 cookie以及有关较新或非标准cookie属性（如`port`）的信息。

  警告

  如果您的Cookie具有丢失/损坏的不便，请在保存前备份您的Cookie，（有一些细微之处可能导致加载/保存往返程序中的文件略有更改）。

  还要注意，Mozilla运行时保存的Cookie会被Mozilla破坏。

class `http.cookiejar.``LWPCookieJar`(filename, delayload=None, policy=None)

  可以以与libwww-perl库的`Set-Cookie3`文件格式兼容的格式加载并将Cookie保存到磁盘的`FileCookieJar` 如果要将cookie存储在人工可读的文件中，这很方便。

## 21.24.3. CookiePolicy对象

实现`CookiePolicy`接口的对象有以下方法：

`CookiePolicy.``set_ok`(cookie, request)

  返回布尔值，指示是否应从服务器接受cookie。

  cookie t>是`Cookie`实例。请求是实现由`CookieJar.extract_cookies()`文档定义的接口的对象。

`CookiePolicy.``return_ok`(cookie, request)

  返回布尔值，指示是否应将cookie返回到服务器。

  cookie t>是`Cookie`实例。请求是实现由`CookieJar.add_cookie_header()`文档定义的接口的对象。

`CookiePolicy.``domain_return_ok`(domain, request)

  给定Cookie域时，返回false，如果不应返回Cookie。

  这个方法是一个优化。它不需要检查每个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()`。

  请注意，每个Cookie域都会调用`domain_return_ok()`，而不仅仅是请求域。For example, the function might be called with both `".example.com"` and `"www.example.com"` if the request domain is `"www.example.com"`. 对于`path_return_ok()`也是如此。

  请求参数与`return_ok()`中的文档相同。

`CookiePolicy.``path_return_ok`(path, request)

  如果cookie不应该返回，返回false，给定cookie路径。

  请参阅`domain_return_ok()`的文档。

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

`CookiePolicy.``netscape`

  实现Netscape协议。

`CookiePolicy.``rfc2965`

  实现RFC 2965协议。

`CookiePolicy.``hide_cookie2`

  不要向请求添加Cookie2头（此头的存在表示服务器，我们了解RFC 2965 cookie）。

定义`CookiePolicy`类的最有用的方法是通过从`DefaultCookiePolicy`子类化并覆盖上述部分或全部方法。`CookiePolicy`本身可以用作“空策略”，允许设置和接收任何和所有Cookie（这不太可能有用）。

## 21.24.4. 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)

  返回域是否位于设置或接收Cookie的黑名单上。

`DefaultCookiePolicy.``allowed_domains`()

  返回`None`或允许的域序列（作为元组）。

`DefaultCookiePolicy.``set_allowed_domains`(allowed_domains)

  设置允许的域的顺序，或`None`。

`DefaultCookiePolicy.``is_not_allowed`(domain)

  返回域是否不在白名单中，用于设置或接收Cookie。

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

`DefaultCookiePolicy.``rfc2109_as_netscape`

  如果为true，则请求`CookieJar`实例降级RFC 2109 Cookie（即。通过将`Cookie`实例的版本属性设置为0，在Netscape Cookie中接收到Cookie（Cookie版本为Set-Cookie 默认值为`None`，在这种情况下，RFC 2109 cookie会降级，当且仅当RFC 2965处理被关闭。因此，RFC 2109 cookie默认降级。

一般严格开关：

`DefaultCookiePolicy.``strict_domain`

  不允许网站设置具有国家/地区代码顶级域（如`.co.uk`，`.gov.uk`，`.co.nz` .etc。这是远非完美，不能保证工作！

RFC 2965协议严格开关：

`DefaultCookiePolicy.``strict_rfc2965_unverifiable`

  遵循关于不可验证事务的RFC 2965规则（通常，不可验证的事务是由重定向或对托管在另一个站点上的图像的请求引起的）。如果这是假的，基于可验证性，cookies 从不被阻止

Netscape协议严格开关：

`DefaultCookiePolicy.``strict_ns_unverifiable`

  对不可验证的事务应用RFC 2965规则，甚至对Netscape cookie。

`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.``DomainRFC2965Match`

  设置Cookie时，需要完整的RFC 2965域匹配。

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

`DefaultCookiePolicy.``DomainLiberal`

  等于0（即。所有上述Netscape域严格标志关闭）。

`DefaultCookiePolicy.``DomainStrict`

  等效于`DomainStrictNoDots|DomainStrictNonDomain`。

## 21.24.5. 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.``value`

  Cookie值（字符串），或`None`。

`Cookie.``port`

  表示端口或一组端口的字符串（例如，'80'或'80,8080'）或`None`。

`Cookie.``path`

  Cookie路径（字符串，例如。`'/acme/rocket_launchers'`）。

`Cookie.``secure`

  `True`如果Cookie只应通过安全连接返回。

`Cookie.``expires`

  从纪元开始的整数到期日期（以秒为单位），或`None`。另请参见`is_expired()`方法。

`Cookie.``discard`

  `True`如果这是会话Cookie。

`Cookie.``comment`

  来自服务器的字符串注释解释此Cookie的功能，或`None`。

`Cookie.``comment_url`

  URL链接到来自服务器的解释此Cookie功能的注释，或`None`。

`Cookie.``rfc2109`

  `True`如果此Cookie是作为RFC 2109 Cookie接收的（即。Cookie到达Set-Cookie头，并且该头中的版本cookie属性的值为1）。提供此属性是因为`http.cookiejar`可能会将RFC 2109 Cookie降级为Netscape Cookie，在这种情况下`version`为0。

`Cookie.``port_specified`

  `True`如果服务器（在Set-Cookie / Set-Cookie2头中）明确指定了一个端口或一组端口。

`Cookie.``domain_specified`

  `True`如果服务器显式指定了域。

`Cookie.``domain_initial_dot`

  `True`如果服务器显式指定的域以点（`'.'`）开头。

Cookie可能具有其他非标准Cookie属性。这些可以使用以下方法访问：

`Cookie.``has_nonstandard_attr`(name)

`Cookie.``get_nonstandard_attr`(name, default=None)

  如果cookie具有命名的cookie属性，则返回其值。否则，返回默认值。

`Cookie.``set_nonstandard_attr`(name, value)

  设置命名的cookie属性的值。

`Cookie`类还定义了以下方法：

`Cookie.``is_expired`(now=None)

  `True`如果Cookie已经过了服务器请求的时间，则应该到期。如果给定现在（自纪元以来的秒数），则返回Cookie是否在指定时间到期。

## 21.24.6. 实例

第一个示例显示了`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（假定对于Cookie文件的位置使用Unix / Netscape惯例）：

    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或返回：

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