下面我将从基础到高级,分步讲解如何自定义 Cookie。
核心概念
http.cookiejar.CookieJar: 这是http.cookiejar模块的核心类,它像一个容器,用来存储和管理所有的 Cookie。http.cookiejar.MozillaCookieJar/http.cookiejar.LWPCookieJar: 这两个是CookieJar的子类,它们可以将 Cookie 持久化保存到文件中,就像浏览器一样。MozillaCookieJar兼容 Mozilla/Netscape 格式,LWPCookieJar兼容 libwww-perl (LWP) 格式,我们通常使用MozillaCookieJar。urllib.request.build_opener: 我们需要用它来创建一个可以自动处理 Cookie 的“opener”(打开器)。urllib.request.HTTPHandler/HTTPSHandler: 用于处理 HTTP 和 HTTPS 请求。urllib.request.HTTPCookieProcessor: 这是关键,它将CookieJar与opener关联起来,使得opener在发送请求时能自动带上 Cookie,并在收到响应时自动保存新的 Cookie。
基础用法:创建并使用 CookieJar
这个例子演示了如何创建一个 CookieJar,并用它来发送一个请求,服务器返回的 Cookie 会被自动保存到 CookieJar 中。
import urllib.request
import urllib.parse
import http.cookiejar
# 1. 创建一个 CookieJar 实例
cookie_jar = http.cookiejar.CookieJar()
# 2. 创建一个 HTTPCookieProcessor,并将 CookieJar 传给它
cookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)
# 3. 创建一个 opener,将 cookie_handler 添加进去
opener = urllib.request.build_opener(cookie_handler)
# 4. 使用 opener 发送请求
# 注意:这里用一个需要登录的网站作为示例,你需要替换成你自己的目标 URL
# 访问一个需要登录才能访问的页面
# url = "https://example.com/protected-page"
# 为了演示,我们用一个能设置 Cookie 的简单网站
url = "http://httpbin.org/cookies/set?test_cookie=12345"
try:
response = opener.open(url)
# 5. 读取并打印响应内容
html = response.read().decode('utf-8')
print("--- Response Content ---")
print(html)
print("------------------------\n")
# 6. 查看保存到 CookieJar 中的 Cookie
print("--- Cookies in CookieJar ---")
for cookie in cookie_jar:
print(f"Name: {cookie.name}")
print(f"Value: {cookie.value}")
print(f"Domain: {cookie.domain}")
print(f"Path: {cookie.path}")
print(f"Expires: {cookie.expires}")
print("------------------------")
except urllib.error.URLError as e:
print(f"Error opening URL: {e.reason}")
代码解释:
http.cookiejar.CookieJar(): 创建一个空的“饼干罐”。HTTPCookieProcessor(cookie_jar): 创建一个处理器,告诉 urllib:“请使用这个cookie_jar来管理所有 Cookie”。build_opener(cookie_handler): 创建一个“开门器”,这个开门器包含了我们刚刚配置好的 Cookie 处理能力。opener.open(url): 当我们用这个开门器去打开 URL 时,它会自动完成以下事情:- 检查
cookie_jar中是否有匹配该 URL 的 Cookie,如果有,就自动添加到请求头中。 - 发送请求。
- 接收服务器响应,如果响应头中有
Set-Cookie,就解析它并存入cookie_jar。
- 检查
- 遍历
cookie_jar,我们可以看到从httpbin.org收到的test_cookie。
高级用法:手动创建和添加 Cookie
服务器可能不会通过 Set-Cookie 来给你 Cookie,或者你需要手动设置一个特定的 Cookie 来访问某个接口,这时,我们可以手动创建 Cookie 对象并添加到 CookieJar 中。
http.cookiejar.Cookie 对象的构造函数签名如下:
Cookie(version, name, value, port, port_specified, domain, domain_specified, domain_initial_dot, path, path_specified, secure, expires, discard, comment, comment_url, rest, rfc2109=False)
这看起来很复杂,但我们可以使用 http.cookiejar.CookieJar 的 set_cookie 方法,它会更方便地处理这些细节。
import http.cookiejar
from urllib.parse import urlparse
# 1. 创建一个 CookieJar
cookie_jar = http.cookiejar.CookieJar()
# 2. 手动创建一个 Cookie 对象
# 假设我们要为 'example.com' 设置一个名为 'user_id' 的 Cookie,值为 'abc123'
# 注意:domain 必须包含点,'example.com' 而不是 'example'
new_cookie = http.cookiejar.Cookie(
version=0,
name='user_id',
value='abc123',
port=None,
port_specified=False,
domain='httpbin.org', # 目标域名
domain_specified=True,
domain_initial_dot=False,
path='/cookies', # Cookie 有效的路径
path_specified=True,
secure=False, # 是否仅 HTTPS 传输
expires=None, # 会话 Cookie,浏览器关闭后失效
discard=True, # 是否在会话结束后丢弃
comment=None,
comment_url=None,
rest={'HttpOnly': None} # 可以添加额外的属性,如 HttpOnly, SameSite
)
# 3. 将手动创建的 Cookie 添加到 CookieJar
cookie_jar.set_cookie(new_cookie)
# 4. 创建 opener (和之前一样)
cookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)
opener = urllib.request.build_opener(cookie_handler)
# 5. 发送请求,验证 Cookie 是否被带上
# httpbin.org/cookies 会返回请求中携带的所有 Cookie
url = "http://httpbin.org/cookies"
try:
response = opener.open(url)
html = response.read().decode('utf-8')
print("--- Response Content (should show our manual cookie) ---")
print(html)
print("--------------------------------------------------------\n")
# 6. 再次查看 CookieJar
print("--- Cookies in CookieJar (after manual addition) ---")
for cookie in cookie_jar:
print(cookie)
print("----------------------------------------------------")
except urllib.error.URLError as e:
print(f"Error opening URL: {e.reason}")
代码解释:
- 我们创建了一个
Cookie对象,并详细指定了它的name,value,domain,path等属性。 cookie_jar.set_cookie(new_cookie): 将我们“捏”出来的这个 Cookie 放进了饼干罐。- 后续步骤和基础用法一样,当我们用这个
opener访问httpbin.org/cookies时,请求中就会包含我们手动设置的user_id=abc123。
持久化存储:将 Cookie 保存到文件并读取
模拟真实浏览器,我们需要把 Cookie 保存下来,下次程序运行时直接加载,而不需要重新登录。
import http.cookiejar
import urllib.request
# --- 1. 第一次运行:保存 Cookie 到文件 ---
# 创建一个 MozillaCookieJar 实例,并指定文件名
cookie_file = 'my_cookies.txt'
cookie_jar = http.cookiejar.MozillaCookieJar(cookie_file)
# 创建 opener
cookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)
opener = urllib.request.build_opener(cookie_handler)
# 模拟登录或获取 Cookie 的请求
# httpbin.org/cookies/set 会设置一个 Cookie
print("--- First Run: Fetching and saving cookies... ---")
opener.open("http://httpbin.org/cookies/set/session_id=98765")
# 保存 Cookie 到文件
# ignore_discard=True: 保存那些被标记为会话结束就丢弃的 Cookie
# ignore_expires=True: 保存那些已经过期的 Cookie (通常为了调试)
cookie_jar.save(ignore_discard=True, ignore_expires=True)
print(f"Cookies saved to {cookie_file}\n")
# --- 2. 第二次运行:从文件加载 Cookie ---
# 创建一个新的 MozillaCookieJar 实例
cookie_jar_loaded = http.cookiejar.MozillaCookieJar(cookie_file)
try:
# 尝试从文件加载 Cookie
cookie_jar_loaded.load(ignore_discard=True, ignore_expires=True)
print(f"--- Second Run: Cookies loaded from {cookie_file} ---")
# 创建新的 opener
cookie_handler_loaded = urllib.request.HTTPCookieProcessor(cookie_jar_loaded)
opener_loaded = urllib.request.build_opener(cookie_handler_loaded)
# 发送请求,验证加载的 Cookie 是否生效
response = opener_loaded.open("http://httpbin.org/cookies")
html = response.read().decode('utf-8')
print("--- Response Content (should show loaded cookie) ---")
print(html)
print("-----------------------------------------------------")
except FileNotFoundError:
print(f"Cookie file {cookie_file} not found. This is expected on the first run.")
except http.cookiejar.LoadError as e:
print(f"Error loading cookies: {e}. The file might be corrupted.")
代码解释:
http.cookiejar.MozillaCookieJar(cookie_file): 创建一个支持文件存储的CookieJar。cookie_jar.save(...): 将当前CookieJar中的所有 Cookie 保存到指定文件。cookie_jar.load(...): 从文件中读取 Cookie 并加载到CookieJar实例中。- 通过
ignore_discard=True和ignore_expires=True,我们可以确保即使是一些临时或过期的 Cookie 也能被保存和加载,这对于某些场景很有用。
| 场景 | 核心步骤 | 关键代码/类 |
|---|---|---|
| 基础使用 | 创建 CookieJar -> 创建 HTTPCookieProcessor -> 创建 opener -> 发送请求 |
CookieJar, HTTPCookieProcessor, build_opener |
| 手动创建 Cookie | 创建 Cookie 对象 -> 用 set_cookie 添加到 CookieJar -> 后续步骤同上 |
Cookie, CookieJar.set_cookie() |
| 持久化存储 | 使用 MozillaCookieJar -> save() 保存到文件 -> load() 从文件加载 |
MozillaCookieJar, .save(), .load() |
掌握了这些方法,你就可以在 Python 中灵活地处理各种与 Cookie 相关的任务了。
