{T}

Cookie 管理与模拟登录

1.1 问题的起点

在爬虫开发中,大量有价值的数据隐藏在登录墙之后:用户个人信息、订单记录、好友动态、会员专属内容……要获取这些数据,爬虫必须具备"证明自己身份"的能力。这就是 Cookie 管理与模拟登录 要解决的核心问题。

HTTP 协议本身是无状态的——服务器不会记住"上一个请求是谁发的"。Cookie 和 Session 正是为了解决这个问题而生的:Cookie 在客户端存储身份标识,Session 在服务器端维护会话状态,两者配合,让无状态的 HTTP 能够承载有状态的登录流程。

1.2 本章覆盖范围

本章从原理到实战,系统讲解以下几个层面的内容:

  • 原理层:Cookie 与 Session 的完整工作机制
  • 工具层requests.Session 的自动 Cookie 管理、持久化与恢复
  • 策略层:表单登录、Cookie 注入、OAuth/JWT 令牌三种主流模拟登录策略
  • 工程层:Cookie 池的设计与实现(含 Redis 存储方案)
  • 安全层:常见陷阱排查与安全提醒

1.3 技术栈与版本要求

本章所有代码示例均基于 Python 3.10+,依赖库如下:

版本要求用途
requests>= 2.31HTTP 请求与 Session 管理
lxml>= 5.0HTML 解析提取 CSRF Token
redis>= 5.0Cookie 池存储后端
flask>= 3.0Cookie 池 API 接口
selenium>= 4.15浏览器自动化备选方案
bash
pip install requests>=2.31 lxml>=5.0 redis>=5.0 flask>=3.0

二、Cookie 与 Session 机制原理

2.1 一张图理解完整流程

在深入代码之前,先通过一张时序图建立全局认知。下图展示了从用户首次访问到登录成功,再到后续请求携带 Cookie 验证身份的完整链路:

图表渲染中…

理解 Cookie 的每个属性,对于正确模拟 Cookie 和排查问题至关重要:

属性说明典型值爬虫注意事项
Name/ValueCookie 的键值对session_id=abc123核心关注点,Value 是身份凭证
Domain作用域名.github.com子域名 Cookie 可能不共享
Path作用路径//admin 路径的 Cookie 不会发到 /api
Max-Age有效期(秒)1209600(2周)正值=持久 Cookie,负值=会话 Cookie
Expires过期绝对时间Wed, 21 Oct 2026 07:28:00 GMT与 Max-Age 同时存在时 Max-Age 优先
HttpOnly禁止 JS 读取true爬虫不受影响——此限制仅针对浏览器 JS,HTTP 请求头仍可携带
Secure仅 HTTPS 传输true爬虫需使用 HTTPS 请求
SameSite跨站发送策略Strict / Lax / None跨站请求时需关注

2.3 Session 与 Token 的对比

认证机制的选型决定了爬虫的登录策略。以下是三种主流机制的核心区别:

特性Cookie + SessionJWT TokenOAuth 2.0
存储位置Session 在服务端,Session ID 在 CookieToken 在客户端Token 在客户端
服务器状态有状态(需存储 Session)无状态无状态(资源服务器)
爬虫策略模拟登录获取 Cookie获取 Token 放入 Authorization 头模拟授权流程获取 Token
典型场景传统 Web 网站(如 GitHub)API 服务、SPA 应用第三方登录

3.1 为什么使用 Session

requests.Sessionrequests 库中最强大的特性之一,它解决了 Cookie 管理的核心痛点:

  • 自动保存:每次请求后,响应中的 Set-Cookie 自动存入 Session
  • 自动携带:后续请求自动带上所有已保存的 Cookie
  • 连接复用:底层 TCP 连接复用,减少握手开销
  • 全局配置:统一的 headers、proxies、auth 等配置,无需每次传入
python
# Python 3.10+
import requests

# 不使用 Session —— 每次请求独立,Cookie 不会保留
r1 = requests.get("https://httpbin.org/cookies/set/foo/bar")
r2 = requests.get("https://httpbin.org/cookies")
print(r2.json())  # {"cookies": {}}  —— Cookie 丢失!

# 使用 Session —— 自动管理 Cookie
session = requests.Session()
r1 = session.get("https://httpbin.org/cookies/set/foo/bar")
r2 = session.get("https://httpbin.org/cookies")
print(r2.json())  # {"cookies": {"foo": "bar"}}  —— Cookie 保留!

长时间运行的爬虫需要将 Cookie 持久化,避免每次启动都重新登录。以下是生产环境可用的方案:

python
# Python 3.10+
import json
import os
from pathlib import Path
import requests
import logging

logger = logging.getLogger(__name__)


class CookiePersistence:
    """Cookie 持久化管理 —— 支持保存到文件、从文件恢复、自动校验"""

    def __init__(self, session: requests.Session, cookie_file: str = "cookies.json"):
        self.session = session
        self.cookie_file = Path(cookie_file)

    def save(self) -> None:
        """将 Session 中的 Cookie 保存为 JSON 文件"""
        cookies: list[dict[str, str]] = []
        for cookie in self.session.cookies:
            cookies.append({
                "name": cookie.name,
                "value": cookie.value,
                "domain": cookie.domain,
                "path": cookie.path,
            })
        self.cookie_file.write_text(json.dumps(cookies, indent=2, ensure_ascii=False))
        logger.info(f"Cookie 已保存到 {self.cookie_file}({len(cookies)} 条)")

    def load(self) -> bool:
        """从 JSON 文件恢复 Cookie 到 Session"""
        if not self.cookie_file.exists():
            logger.warning(f"Cookie 文件不存在: {self.cookie_file}")
            return False

        cookies: list[dict] = json.loads(self.cookie_file.read_text())
        for cookie in cookies:
            self.session.cookies.set(
                cookie["name"],
                cookie["value"],
                domain=cookie.get("domain"),
                path=cookie.get("path"),
            )
        logger.info(f"已从 {self.cookie_file} 恢复 {len(cookies)} 条 Cookie")
        return True

    def is_valid(self, check_url: str) -> bool:
        """向 check_url 发送请求,通过响应判断 Cookie 是否有效"""
        try:
            resp = self.session.get(check_url, allow_redirects=False, timeout=10)
            # 有效的 Cookie 不应被重定向到登录页
            return resp.status_code == 200 and "login" not in resp.url.lower()
        except requests.RequestException:
            return False
安全提醒

Cookie 文件包含登录凭证,应妥善保管:不要提交到 Git 仓库(添加到 .gitignore),不要分享给他人,生产环境建议加密存储。

四、模拟登录策略

4.1 策略一:表单登录(分析 + 构造 POST)

这是最经典、最通用的模拟登录方式。核心思路是分析登录接口,构造请求参数,使用 Session 提交

版本要求

以下代码基于 Python 3.10+ 语法(类型注解、dict 泛型等),请确保运行环境满足要求。

通用表单登录流程

python
# Python 3.10+
import requests
from lxml import etree
import logging

logger = logging.getLogger(__name__)


class FormLoginClient:
    """通用表单登录客户端"""

    def __init__(self, login_page_url: str, login_action_url: str):
        self.session = requests.Session()
        self.login_page_url = login_page_url
        self.login_action_url = login_action_url
        self._setup_headers()

    def _setup_headers(self) -> None:
        self.session.headers.update({
            "User-Agent": (
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                "AppleWebKit/537.36 (KHTML, like Gecko) "
                "Chrome/120.0.0.0 Safari/537.36"
            ),
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
        })

    def _extract_csrf_token(self, html: str, token_field_name: str = "authenticity_token") -> str | None:
        """
        从登录页面 HTML 中提取 CSRF Token。
        使用 XPath 为主,正则表达式为备选方案。
        """
        # 策略1:XPath 解析
        selector = etree.HTML(html)
        tokens = selector.xpath(f'//input[@name="{token_field_name}"]/@value')
        if tokens:
            return str(tokens[0])

        # 策略2:正则表达式兜底
        import re
        pattern = rf'name="{token_field_name}"\s+value="([^"]+)"'
        match = re.search(pattern, html)
        if match:
            return match.group(1)

        return None

    def login(self, username: str, password: str,
              extra_fields: dict[str, str] | None = None) -> bool:
        """
        执行表单登录。

        Args:
            username: 用户名/邮箱
            password: 密码
            extra_fields: 额外的表单字段(如 commit、utf8 等固定值)

        Returns:
            bool: 登录是否成功
        """
        # 步骤1:访问登录页面,获取初始 Cookie 和 CSRF Token
        logger.info("正在访问登录页面...")
        response = self.session.get(self.login_page_url)
        csrf_token = self._extract_csrf_token(response.text)

        if csrf_token is None:
            logger.error("无法提取 CSRF Token,请检查页面结构")
            return False
        logger.info(f"CSRF Token 获取成功: {csrf_token[:20]}...")

        # 步骤2:构造登录表单
        form_data: dict[str, str] = {
            "login": username,
            "password": password,
            "authenticity_token": csrf_token,
        }
        if extra_fields:
            form_data.update(extra_fields)

        # 步骤3:提交登录请求
        logger.info("正在提交登录表单...")
        response = self.session.post(
            self.login_action_url,
            data=form_data,
            allow_redirects=True,
        )

        # 步骤4:验证登录结果
        return self._verify_login(response)

    def _verify_login(self, response: requests.Response) -> bool:
        """通过多种方式验证登录是否成功"""
        # 方式1:检查特定 Cookie 是否出现
        if "logged_in" in self.session.cookies:
            return True
        # 方式2:检查页面内容中的登录标识
        if "Sign out" in response.text or "logout" in response.text.lower():
            return True
        return False

    def fetch_protected(self, url: str) -> str | None:
        """获取需要登录才能访问的页面"""
        resp = self.session.get(url)
        return resp.text if resp.status_code == 200 else None

以 GitHub 为例的实战调用

python
# Python 3.10+
client = FormLoginClient(
    login_page_url="https://github.com/login",
    login_action_url="https://github.com/session",
)

success = client.login(
    username="your_email@example.com",
    password="your_password",
    extra_fields={"commit": "Sign in", "utf8": "✓"},
)

if success:
    print("登录成功!")
    # 爬取登录后才能访问的个人设置页
    profile_html = client.fetch_protected("https://github.com/settings/profile")
else:
    print("登录失败,请检查用户名/密码或分析登录接口变化")

4.2 策略二:Cookie 注入(从浏览器复制)

当目标网站的反爬机制较强(如 JS 加密参数、复杂验证码),或者登录次数很少时,直接从浏览器复制已登录的 Cookie 是最快的方式。

操作步骤

  1. 在浏览器中手动登录目标网站
  2. 打开开发者工具(F12),进入 Application > Storage > Cookies
  3. 复制所需的 Cookie 键值对
  4. 注入到爬虫的 Session 中
python
# Python 3.10+
import requests

def parse_cookie_string(cookie_str: str) -> dict[str, str]:
    """
    将浏览器复制的 Cookie 字符串解析为字典。
    输入示例: "name1=value1; name2=value2; name3=value3"
    """
    cookies: dict[str, str] = {}
    for item in cookie_str.split(";"):
        item = item.strip()
        if "=" in item:
            key, _, value = item.partition("=")
            cookies[key.strip()] = value.strip()
    return cookies


# 从浏览器复制的 Cookie 字符串
cookie_string = "logged_in=yes; dotcom_user=zhang; user_session=xyz789"

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})

# 方式1:通过 cookies 参数传递
cookies_dict = parse_cookie_string(cookie_string)
resp = session.get("https://github.com/settings/profile", cookies=cookies_dict)

# 方式2:直接注入到 Session(推荐,后续请求自动携带)
session.cookies.update(cookies_dict)
resp = session.get("https://github.com/settings/profile")
print(f"状态码: {resp.status_code},页面长度: {len(resp.text)}")
注意事项
  • 浏览器复制的 Cookie 会过期,需要定期更新
  • 某些 Cookie 可能绑定 IP 或 User-Agent,复制时需一并模拟
  • 不适用于大规模、长时间运行的采集任务

4.3 策略三:OAuth / JWT 令牌方式

越来越多的现代网站采用 Token 认证(尤其是 API 服务)。相比 Cookie,Token 方式通常更稳定、更易维护。

python
# Python 3.10+
import requests

# === JWT Token 认证 ===
session = requests.Session()
session.headers.update({
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "User-Agent": "Mozilla/5.0 ...",
})

# 直接请求 API,无需 Cookie
resp = session.get("https://api.example.com/user/profile")
print(resp.json())

# === GitHub Personal Access Token 认证 ===
# 在 GitHub Settings > Developer settings > Personal access tokens 创建
session = requests.Session()
session.headers.update({
    "Authorization": "token ghp_xxxxxxxxxxxxxxxxxxxx",
    "Accept": "application/vnd.github+json",
})
resp = session.get("https://api.github.com/user")
print(resp.json())

三种策略的适用场景对比

策略难度稳定性自动化程度适用场景
表单登录常规网站,需分析接口
Cookie 注入临时采集、反爬较强的网站
Token 认证API 服务、有 Token 获取渠道

五、验证码 + 登录组合处理

验证码是模拟登录中最常见的障碍。根据验证码类型,选择不同的处理策略:

验证码类型难度推荐方案工具
简单图形验证码OCR 识别ddddocrpytesseract
复杂图形验证码打码平台超级鹰、云打码
滑动/点选验证码浏览器自动化Selenium / Playwright
短信验证码接码平台各接码平台

使用 Selenium 处理验证码的混合方案

python
# Python 3.10+
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import requests


def login_with_selenium_and_export_cookies(
    login_url: str, username: str, password: str
) -> dict[str, str]:
    """
    使用 Selenium 完成登录(包括验证码处理),然后导出 Cookie 供 requests 使用。
    典型应用场景:requests 无法处理的验证码,由 Selenium 人工或半自动处理。
    """
    options = webdriver.ChromeOptions()
    options.add_argument("--disable-blink-features=AutomationControlled")
    driver = webdriver.Chrome(options=options)
    wait = WebDriverWait(driver, 15)

    try:
        driver.get(login_url)

        # 填写表单
        username_input = wait.until(EC.presence_of_element_located((By.NAME, "username")))
        username_input.send_keys(username)
        driver.find_element(By.NAME, "password").send_keys(password)
        driver.find_element(By.CSS_SELECTOR, "button[type='submit']").click()

        # 如果有验证码,手动处理
        input("请在浏览器中完成验证码,然后按 Enter 继续...")

        # 导出 Cookie
        return {c["name"]: c["value"] for c in driver.get_cookies()}
    finally:
        driver.quit()


# 使用 Selenium 登录,导出 Cookie 后切换到 requests
cookies = login_with_selenium_and_export_cookies(
    "https://example.com/login", "username", "password"
)

session = requests.Session()
session.cookies.update(cookies)
# 后续全部使用 requests 高效爬取
resp = session.get("https://example.com/dashboard")

六、Cookie 池的设计与实现

单账号 Cookie 存在三个致命弱点:有效期短(过期后爬虫中断)、频率限制(单账号请求量有上限)、封禁风险(一经封禁全盘皆输)。Cookie 池通过多账号轮换,将这三个风险分散到多个账号上,是规模化爬虫的基础设施。

6.2 架构设计

Cookie 池由五大核心模块组成,各模块职责清晰、松耦合:

图表渲染中…

各模块职责

模块职责关键设计
存储模块Cookie 持久化Redis Hash,Key=cookies:{website},Field=账号名,Value=JSON
获取模块模拟登录获取 Cookie可扩展的登录器架构,新增网站只需实现 BaseLoginer 子类
检测模块验证 Cookie 有效性请求验证 URL,根据响应码/内容判断
接口模块对外提供 REST APIGET /get/<website> 随机返回一个有效 Cookie
调度模块协调定时任务获取间隔 1 小时,检测间隔 10 分钟

6.3 Redis 存储方案

选择 Redis 的理由:Hash 结构天然适合"网站-账号"的二级映射;支持 TTL 过期自动清理;高并发下性能优异。

python
# Python 3.10+
import redis
import json
import random
import time
import logging

logger = logging.getLogger(__name__)


class CookieStore:
    """
    Cookie 存储管理 —— 基于 Redis Hash。

    数据结构:
        Key:    cookies:{website}
        Field:  {username}
        Value:  {"cookies": {...}, "status": "valid/invalid", "updated": 1700000000}
    """

    def __init__(self, host: str = "localhost", port: int = 6379,
                 db: int = 0, password: str | None = None):
        self.redis = redis.StrictRedis(
            host=host, port=port, db=db, password=password,
            decode_responses=True,
        )
        logger.info(f"Redis 连接成功: {host}:{port}")

    def _key(self, website: str) -> str:
        return f"cookies:{website}"

    def set(self, website: str, username: str, cookies: dict, status: str = "valid") -> None:
        """存储 Cookie"""
        value = json.dumps({
            "cookies": cookies,
            "status": status,
            "updated": int(time.time()),
        }, ensure_ascii=False)
        self.redis.hset(self._key(website), username, value)
        logger.info(f"Cookie 已存储: {website}:{username} ({status})")

    def get_random(self, website: str) -> dict | None:
        """随机获取一个有效 Cookie"""
        all_data = self.redis.hgetall(self._key(website))
        valid_accounts = [
            (username, json.loads(data))
            for username, data in all_data.items()
            if json.loads(data).get("status") == "valid"
        ]
        if not valid_accounts:
            logger.warning(f"{website} 无可用 Cookie")
            return None
        username, data = random.choice(valid_accounts)
        logger.info(f"随机获取: {website}:{username}")
        return data.get("cookies")

    def set_status(self, website: str, username: str, status: str) -> None:
        """更新 Cookie 状态"""
        data = self.get(website, username)
        if data:
            self.set(website, username, data["cookies"], status)

    def get(self, website: str, username: str) -> dict | None:
        """获取指定账号的 Cookie"""
        value = self.redis.hget(self._key(website), username)
        return json.loads(value) if value else None

    def delete(self, website: str, username: str) -> None:
        """删除指定账号的 Cookie"""
        self.redis.hdel(self._key(website), username)

    def count(self, website: str, status: str | None = None) -> int:
        """统计 Cookie 数量"""
        all_data = self.redis.hgetall(self._key(website))
        if status is None:
            return len(all_data)
        return sum(1 for v in all_data.values() if json.loads(v).get("status") == status)

    def get_all(self, website: str, status: str | None = None) -> dict[str, dict]:
        """获取指定网站的所有 Cookie"""
        all_data = self.redis.hgetall(self._key(website))
        result = {u: json.loads(v) for u, v in all_data.items()}
        if status:
            return {u: d for u, d in result.items() if d.get("status") == status}
        return result

6.4 定时检测与自动刷新

Cookie 的有效期是有限的(通常数小时到数周不等),必须定时检测并自动刷新。检测器通过请求一个"验证 URL"(如个人设置页面)来判断 Cookie 是否仍然有效:

python
# Python 3.10+
import requests
from abc import ABC, abstractmethod


class BaseChecker(ABC):
    """Cookie 检测器基类"""

    def __init__(self, website: str):
        self.website = website

    @abstractmethod
    def check(self, cookies: dict) -> bool:
        """检测 Cookie 是否有效,返回 True/False"""
        ...


class GithubChecker(BaseChecker):
    """GitHub Cookie 检测器 —— 请求个人设置页验证"""

    def __init__(self):
        super().__init__("github")
        self.check_url = "https://github.com/settings/profile"

    def check(self, cookies: dict) -> bool:
        try:
            resp = requests.get(
                self.check_url,
                cookies=cookies,
                allow_redirects=False,  # 不跟随重定向,通过状态码判断
                headers={"User-Agent": "Mozilla/5.0 ..."},
                timeout=10,
            )
            # 200 = 有效,302 = 被重定向到登录页 = 失效
            return resp.status_code == 200
        except requests.RequestException:
            return False


# 检测器注册表(可扩展更多网站)
CHECKER_MAP: dict[str, type[BaseChecker]] = {
    "github": GithubChecker,
}

调度器将 Cookie 获取和检测串联为定时任务,形成闭环:获取 -> 存储 -> 检测 -> 失效 -> 重新获取。

七、常见陷阱与解决方案

以下表格汇总了 Cookie 管理与模拟登录开发中最常见的陷阱:

陷阱典型现象根因分析解决方案
Cookie 过期运行一段时间后突然返回 401/302Cookie 有效期结束实现定时检测 + 自动刷新机制
CSRF Token 缺失登录接口返回 403 Forbidden未携带 CSRF 防护令牌先 GET 登录页面,从 HTML 中提取 Token
多步登录流程登录后仍无法访问目标页面有重定向链或中间验证步骤跟踪完整请求链,设置 allow_redirects=True
验证码失效识别出的验证码提交后提示错误验证码与 Session 绑定,每次刷新页面后旧验证码失效确保验证码图片和登录请求使用同一个 Session
请求头异常返回 403/404,但浏览器可以User-Agent、Referer 等被识别为爬虫完整复制浏览器请求头,特别注意 Referer 和 Origin
IP 频率限制请求返回 429 Too Many Requests单 IP 短时间内请求过多使用代理 IP 池 + 随机延时
JS 动态加密抓包参数与实际提交参数不一致密码等字段在提交前被 JS 加密分析加密逻辑(逆向 JS)或使用 Selenium 绕过
SameSite 限制跨站请求不携带 CookieSameSite=Strict 禁止跨站发送使用同站请求或设置 SameSite=None(需配合 Secure)

八、最佳实践

8.1 代码规范

实践推荐做法不推荐做法原因
Cookie 管理使用 requests.Session手动拼接 Cookie 字符串自动管理,减少遗漏和错误
登录验证检查关键元素 + Cookie + URL仅检查 HTTP 状态码某些网站登录失败也返回 200
CSRF Token每次登录前动态获取硬编码 Token 值Token 会动态变化
Cookie 存储加密存储到文件或 Redis明文存储防止凭证泄露
异常处理捕获异常并实现重试逻辑直接崩溃提高程序健壮性
请求间隔随机延时 1-3 秒无间隔连续请求模拟人类行为,降低封禁风险
日志记录记录关键步骤和异常无日志便于排查问题

8.2 安全提醒

安全警告
  1. 绝对不要将登录凭证(用户名/密码/Cookie/Token)分享给他人或提交到公开仓库
  2. .gitignore 中添加 cookies.jsonaccounts.json*.pem 等敏感文件
  3. 遵守目标网站的**服务条款(ToS)**和 robots.txt 协议
  4. 控制请求频率,避免对目标网站造成不必要的负担
  5. 仅爬取你有权访问的数据,尊重数据所有权和隐私
  6. 生产环境使用环境变量或密钥管理服务(如 Vault)存储敏感配置

九、术语表

术语英文解释
CookieHTTP Cookie服务器发送到客户端的小型数据片段,用于状态管理
SessionSession服务器端存储的用户会话信息
Session IDSession Identifier唯一标识用户会话的字符串
CSRFCross-Site Request Forgery跨站请求伪造,一种 Web 攻击方式
CSRF TokenCSRF Token防御 CSRF 攻击的随机令牌,嵌入在表单中
JWTJSON Web Token一种无状态的身份认证令牌格式,由 Header、Payload、Signature 三部分组成
OAuth 2.0Open Authorization 2.0开放授权协议,用于第三方应用授权
HttpOnlyHttpOnlyCookie 属性,禁止 JavaScript 访问,但 HTTP 请求头仍可携带
SecureSecureCookie 属性,仅通过 HTTPS 传输
SameSiteSameSiteCookie 属性,控制跨站请求时是否发送
Cookie 池Cookie Pool预先获取并集中管理的多个 Cookie 集合,通过 API 分发
调度器Scheduler定时执行 Cookie 获取和检测任务的协调模块
登录器Loginer负责模拟登录并获取 Cookie 的模块
检测器Checker负责验证 Cookie 有效性的模块
持久 CookiePersistent Cookie设置了 Max-Age 或 Expires 的 Cookie,关闭浏览器后仍存在
会话 CookieSession Cookie未设置过期时间的 Cookie,关闭浏览器后消失
PATPersonal Access TokenGitHub 等平台的个人访问令牌,用于 API 认证
2FATwo-Factor Authentication双因素认证,额外的安全验证层

十、延伸阅读

站内链接

  • Requests 模块完全指南 -- requests 库完整教程,含 Session 详解
  • Selenium 自动化深度指南 -- 浏览器自动化方案,处理复杂验证码
  • HTTP 基本原理 -- HTTP 协议深入理解

外部链接

十一、小结

本章从原理到工程实践,系统讲解了 Cookie 管理与模拟登录的完整知识体系:

  1. 理解原理:Cookie 在客户端存储身份标识,Session 在服务器端维护会话状态,两者配合让无状态的 HTTP 承载有状态的登录流程
  2. 掌握工具requests.Session 自动管理 Cookie 的保存、携带和持久化,是模拟登录的核心工具
  3. 选择策略:表单登录(通用)、Cookie 注入(临时)、Token 认证(API 服务)三种策略各有适用场景
  4. 应对验证码:根据验证码类型选择 OCR、打码平台或浏览器自动化方案
  5. 构建基础设施:Cookie 池通过"获取-存储-检测-分发-淘汰"的闭环,实现多账号 Cookie 的自动化管理,是规模化爬虫的基石

核心思想:分析思路比代码实现更重要。只要正确理解了目标网站的认证机制,获取并维护好登录状态,模拟登录就能稳定运行。

版本差异(爬虫技术栈 → 当前版本)

本文编写时当前稳定版
requests2.28/2.312.32.x
Scrapy1.x/2.02.11.x(API 稳定)
httpx0.240.28.x
Playwright1.3x1.6x(Python 版)
lxml/BeautifulSoup旧版保持稳定
Python3.8-3.123.14(推荐)

本文讲解的爬虫原理(HTTP、解析、反爬、存储)与核心 API 在最新版本中成立;注意 Python 3.9 及以下已 EOL,新项目使用 3.13/3.14。