如何使用Python requests库禁用cookie处理?

20

当我使用requests访问一个URL时,cookies会自动发送回服务器(在下面的例子中,请求的URL设置了一些cookie值,然后重定向到另一个显示存储的cookie的URL)

>>> import requests
>>> response = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")
>>> response.content
'{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'

是否有可能像设置 Chrome 或 Firefox 不接受 cookie 一样临时禁用 cookie 处理?

例如,如果我使用已禁用 cookie 处理的 Chrome 访问上述 URL,则会得到预期结果:

{
  "cookies": {}
}

1
从文档中可以看到关于“Requests - Cookies”(http://docs.python-requests.org/en/latest/user/quickstart/#cookies)的内容,但是并没有提及如何禁用cookies。不过,你可以查看https://github.com/kennethreitz/requests/blob/master/requests/cookies.py和https://github.com/kennethreitz/requests/blob/master/requests/sessions.py来了解它是如何处理cookiejars的。 - bnlucas
5个回答

32

您可以通过定义一个拒绝所有 cookie 的 cookie 政策来实现此操作:

from http import cookiejar  # Python 2: import cookielib as cookiejar
class BlockAll(cookiejar.CookiePolicy):
    return_ok = set_ok = domain_return_ok = path_return_ok = lambda self, *args, **kwargs: False
    netscape = True
    rfc2965 = hide_cookie2 = False

(请注意,http.cookiejar 的 API 要求您定义一堆属性和方法,如所示。)

然后,在您的 Requests 会话中设置 cookie 策略:

import requests
s = requests.Session()
s.cookies.set_policy(BlockAll())

现在它将不会存储或发送cookie:

s.get("https://httpbin.org/cookies/set?foo=bar")
assert not s.cookies

顺便提一下,如果您查看代码,requests包中的方便方法(而不是requests.Session对象上的方法)每次都会构造一个新的Session。因此,在对requests.get进行分开的调用时,cookie不会被保留。但是,如果第一个页面设置了cookie并发出HTTP重定向,则目标页面将会看到cookie。(这就是HTTPBin /cookies/set调用的情况,它重定向到/cookies。)

因此,取决于您想要的重定向行为,您可能不需要采取任何特殊措施。请参考:

>>> print(requests.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {'foo': 'bar'}}
>>> print(requests.get("https://httpbin.org/cookies").json())
{'cookies': {}}

>>> s = requests.Session()
>>> print(s.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {'foo': 'bar'}}
>>> print(s.get("https://httpbin.org/cookies").json())
{'cookies': {'foo': 'bar'}}

>>> s = requests.Session()
>>> s.cookies.set_policy(BlockAll())
>>> print(s.get("https://httpbin.org/cookies/set?foo=bar").json())
{'cookies': {}}
>>> print(requests.get("https://httpbin.org/cookies").json())
{'cookies': {}}

非常感谢您提供的全面、清晰和详细的回答,特别是关于 httpbin 重定向解释的部分。 - raben

1
创建新类的更简单的替代方法是使用 http.cookiejar.DefaultCookiePolicy 并提供一个空的允许域名列表:
from requests import Session
from http.cookiejar import DefaultCookiePolicy

s = Session()
s.cookies.set_policy(DefaultCookiePolicy(allowed_domains=[]))

来自文档

allowed_domains:如果不是None,则这是我们接受和返回cookie的唯一域名序列。


allowed_domains的默认值为None,这意味着它接受任何网站的cookie。 - undefined
@thetaprime 是的,这就是为什么我们传递 [] - undefined

0

你得到了"k2": "v2", "k1": "v1",因为它们是通过GET参数发送的。如果你跟进第二个请求,你会发现你没有发送任何cookies。除非你使用requests.Session,否则客户端不会自动处理cookies,你必须在每个请求中显式地传递一个字典或CookieJar。

In [17]: r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")

In [18]: r.content
Out[18]: '{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'

In [20]: r.cookies.get_dict()
Out[20]: {}

In [21]: r = requests.get("http://httpbin.org/cookies")

In [22]: r.content
Out[22]: '{\n  "cookies": {}\n}'

2
当您向该URL发出请求时,服务器的第一个响应会在客户端中设置一个cookie。然后,您将被重定向到一个新的URL,该URL显示由第一个响应设置的cookie的内容。这是httpbin.org专门用于测试cookie持久性的方式。尝试使用已禁用cookie的浏览器获取相同的URL,您将获得一个空答案。 - raben

0
>>> import mock
>>> import requests
>>> with mock.patch.object(requests.cookies.RequestsCookieJar, 'update', lambda *args, **kwargs: 0):
...     r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")#, cookies=cj)
...     r.content
... 
'{\n  "cookies": {}\n}'
>>> r = requests.get("http://httpbin.org/cookies/set?k1=v1&k2=v2")
>>> r.content
'{\n  "cookies": {\n    "k2": "v2",\n    "k1": "v1"\n  }\n}'

我看到它能够工作,但我并不完全理解正在发生的事情。你介意解释一下吗? - raben
1
这段代码补丁请求 cookies.RequestsCookieJar.update 方法不更新 cookie。在 with 块之外,该补丁将被撤销。 - falsetru

-1
class BlockAll(CookiePolicy):
    def set_ok(self, cookie, request):
        return False
session.cookies.policy = BlockAll()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接