【问题标题】:How does Python's Requests treat multiple cookies in a headerPython 的请求如何处理标头中的多个 cookie
【发布时间】:2019-11-29 05:27:54
【问题描述】:

我使用 Python Rquests 来提取完整​​的响应标头。

我想准确计算响应中有多少 cookie(即 nam/variable)对。有两个问题:

1) 如果服务器响应多个 Set-Cookie 标头。 Requests 是如何表示这一点的?它是否将两个 Set-Cookie 值合二为一?还是保持原样?

这是我打印标题的脚本(完整标题):

import requests
requests.packages.urllib3.disable_warnings() # to disable certificate warnings

response = requests.get("https://example.com",verify=False,timeout=3)
print(str(response.headers))
response_headers = response.headers.get('Set-Cookie')

但是当我查看一些 Set-Cookie 响应标头时,我发现一些名称/值对用逗号分隔,如下所示:

dnn_IsMobile=False; path=/; secure; HttpOnly, Analytics_VisitorId=aa; expires=Mon 19-Aug-2019 14:20:02 GMT; path=/; secure; HttpOnly, Analytics=SessionId=vv&ContentItemId=-1; expires=Sat 20-Jul-2019 15:20:02 GMT; path=/; secure

2) 这是否意味着服务器发送了多个Set-Cookie 并且请求将它们组合在一起?

如果 requests 在 cookie 的名称/值对之间添加逗号,它是否总是用逗号和空格分隔它们?即cookie1=value, cookie2=value 而不仅仅是像cookie1=value,cookie2=value 这样的逗号。

了解这种差异对于我能够计算收到的正确 cookie 数量非常重要。

【问题讨论】:

    标签: python cookies python-requests http-headers httpresponse


    【解决方案1】:

    如何计算 cookie 的数量并获取它们

    您可以使用更高级别的.cookies 来获取它们,而不是使用.headers

    例如:

    >>> url="https://github.com"
    >>> r = requests.get(url)
    >>> r.cookies
    <RequestsCookieJar[Cookie(version=0, name='_octo', value='GH1.1.1081626831.1563694143', port=None, port_specified=False, domain='.github.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires=1626852543, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False), Cookie(version=0, name='logged_in', value='no', port=None, port_specified=False, domain='.github.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=True, expires=2194846143, discard=False, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='_gh_sess', value='N0NVdFd3dTMzcm9GSkh1U21ZQkVaYWUvWnBnRmVic0VFWm9kSVZKVVhMV0hVdUw4cDh5cGpmTmIrQ0xJYU9tNHE0ZHQxVkZlUU9JRGJHUkJtc21yVGM0Mk9hQjBUYnhDVXJYSFVWSjNzT2ZpNjdEVzF0emZydkJmQmgvZmVRRFhEaE1CRTlnd0ZPY0RRY0Z4L1ByaFFpbWhVTGtPZTZmUHhONzBxclIrWWZSdFlZK09NN1QzS1dlL3cwWmVSdG5wTHFROTh1Zmh6Y3JkMjFDQmtxb2FHQT09LS1DUEd6UHFtWS9ubTdpOEdwYndzU3l3PT0%3D--2f3ae9c74cba34f2e8de6dfe55c3616e8a35ab20', port=None, port_specified=False, domain='github.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=True, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='has_recent_activity', value='1', port=None, port_specified=False, domain='github.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1563697743, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False)]>
    >>> len(r.cookies)
    4
    >>> r.cookies.keys()
    ['_octo', 'logged_in', '_gh_sess', 'has_recent_activity']
    >>> for key in r.cookies.iterkeys(): print("{}: {}".format(key, r.cookies[key]))
    ... 
    _octo: GH1.1.1081626831.1563694143
    logged_in: no
    _gh_sess: N0NVdFd3dTMzcm9GSkh1U21ZQkVaYWUvWnBnRmVic0VFWm9kSVZKVVhMV0hVdUw4cDh5cGpmTmIrQ0xJYU9tNHE0ZHQxVkZlUU9JRGJHUkJtc21yVGM0Mk9hQjBUYnhDVXJYSFVWSjNzT2ZpNjdEVzF0emZydkJmQmgvZmVRRFhEaE1CRTlnd0ZPY0RRY0Z4L1ByaFFpbWhVTGtPZTZmUHhONzBxclIrWWZSdFlZK09NN1QzS1dlL3cwWmVSdG5wTHFROTh1Zmh6Y3JkMjFDQmtxb2FHQT09LS1DUEd6UHFtWS9ubTdpOEdwYndzU3l3PT0%3D--2f3ae9c74cba34f2e8de6dfe55c3616e8a35ab20
    has_recent_activity: 1
    

    附:有时阅读源代码更容易,我通过阅读cookies.py 发现:)


    编辑r.headers.get("Set-Cookie")中的分隔符(无论是", "还是","):

    1. Requests 在底层使用了urllib3,你会发现r.rawurllib3.response.HTTPResponse 的一个对象。
    2. 在urllib3中,标头由_collections.py中定义的HTTPHeaderDict表示,多个值由", "连接。

      def __getitem__(self, key):
          val = self._container[key.lower()]
          return ", ".join(val[1:])
      
    3. 另外,在 urllib3 中有一个关于这个的 issue,还有一个 test case 代表它。

    所以,您可以使用", " 来统计cookie 的数量。

    请求是否将多个Set-Cookies 合并为一个headers

    恐怕答案是肯定的,因为通过检查它的价值(为了更好地阅读,一些不相关的标题被删除):

    >>> r.headers
    {
        'Date': 'Sun, 21 Jul 2019 07:29:03 GMT',
        'Content-Type': 'text/html; charset=utf-8',
        'Transfer-Encoding': 'chunked',
        'Server': 'GitHub.com',
        'Status': '200 OK',
        'Set-Cookie': 'has_recent_activity=1; path=/; expires=Sun, 21 Jul 2019 08:29:03 -0000, _octo=GH1.1.1081626831.1563694143; domain=.github.com; path=/; expires=Wed, 21 Jul 2021 07:29:03 -0000, logged_in=no; domain=.github.com; path=/; expires=Thu, 21 Jul 2039 07:29:03 -0000; secure; HttpOnly, _gh_sess=N0NVdFd3dTMzcm9GSkh1U21ZQkVaYWUvWnBnRmVic0VFWm9kSVZKVVhMV0hVdUw4cDh5cGpmTmIrQ0xJYU9tNHE0ZHQxVkZlUU9JRGJHUkJtc21yVGM0Mk9hQjBUYnhDVXJYSFVWSjNzT2ZpNjdEVzF0emZydkJmQmgvZmVRRFhEaE1CRTlnd0ZPY0RRY0Z4L1ByaFFpbWhVTGtPZTZmUHhONzBxclIrWWZSdFlZK09NN1QzS1dlL3cwWmVSdG5wTHFROTh1Zmh6Y3JkMjFDQmtxb2FHQT09LS1DUEd6UHFtWS9ubTdpOEdwYndzU3l3PT0%3D--2f3ae9c74cba34f2e8de6dfe55c3616e8a35ab20; path=/; secure; HttpOnly',
        'Content-Encoding': 'gzip',
        'X-GitHub-Request-Id': 'A947:3711:E0377A:13B4CEA:5D34143E'
    }
    

    【讨论】:

    • 我已经使用.headers 收集的数据,我不能重复收集数据。所以我不得不手动解析和计算它们。目前还不清楚,cookies是否总是用空格隔开,然后用逗号cookie1=value, cookie2=value?或者只是逗号cookie1=value,cookie2=value?
    • @qbq 使用", ",我已经更新了我的答案。
    • @qbq 和@whatcold - 从r.cookies 的上述输出中,您可以看到各个cookie 包含在“Cookie()”中。所以这四个cookie是“Cookie(), Cookie(), Cookie(), Cookie()”。在 cookie 中使用“key=value”。
    猜你喜欢
    • 2013-08-29
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-20
    • 2020-06-04
    • 1970-01-01
    相关资源
    最近更新 更多