爬虫模拟登录实战——Session、Cookie与验证码处理

很多网站的内容需要登录才能看到,比如知乎的关注动态、微博的关注列表、电商平台的订单信息。这一篇就讲怎么用 Python 搞定模拟登录。

一、Cookie 与 Session 基本原理

HTTP 为什么需要它们?

HTTP 是无状态的------服务器记不住你之前来过。Cookie 和 Session 就是为了解决"记住我是谁"这个问题。

复制代码
第一次请求:POST /login → 用户名+密码
  服务器验证通过,返回 Set-Cookie: session_id=abc123

第二次请求:GET /profile → 浏览器自动带上 Cookie: session_id=abc123
  服务器一看 Session ID 就知道你是谁

核心流程:

  1. 登录成功后,服务器返回 Cookie
  2. 后续请求带着 Cookie,服务器就能识别身份
  3. Cookie 过期或被清除,就需要重新登录

requests.Session 会自动保存和发送 Cookie,比手动处理省事很多。

python 复制代码
import requests

# 创建 Session 对象(自动管理 Cookie)
session = requests.Session()

# 登录参数
login_url = "https://example.com/login"
login_data = {
    "username": "your_account",
    "password": "your_password"
}

# 发送登录请求,Session 自动保存返回的 Cookie
resp = session.post(login_url, data=login_data)
print("登录状态码:", resp.status_code)

# 后续请求自动携带 Cookie
profile_url = "https://example.com/profile"
resp2 = session.get(profile_url)
print(resp2.text)  # 已登录后的页面内容

对比普通 requests.get: 用 Session 后,鉴权信息自动带上,不用手动操作 Cookie。

三、实战:模拟登录 GitHub

GitHub 的登录流程比较典型,包含表单提交和 Token 校验。

python 复制代码
import requests
from bs4 import BeautifulSoup

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

def login_github(username, password):
    """模拟登录 GitHub"""
    login_url = "https://github.com/login"
    
    # 第一步:访问登录页,获取 authenticity_token
    resp = session.get(login_url)
    soup = BeautifulSoup(resp.text, "html.parser")
    
    # GitHub 登录表单需要 token 防 CSRF 攻击
    token = soup.find("input", {"name": "authenticity_token"}).get("value")
    
    # 第二步:提交登录表单
    data = {
        "login": username,
        "password": password,
        "authenticity_token": token,
        "commit": "Sign in"
    }
    
    session.post(login_url, data=data)
    
    # 验证登录是否成功
    profile = session.get("https://github.com/" + username)
    if username in profile.text:
        print("登录成功!")
        return True
    else:
        print("登录失败")
        return False

要点: 很多网站的登录流程不是一步的------先 GET 拿 Token,再 POST 提交。直接用账号密码去 POST 大概率失败。

四、处理验证码

1. 图形验证码------保存到本地手动识别

python 复制代码
import requests

session = requests.Session()

# 先获取验证码图片
captcha_url = "https://example.com/captcha"
resp = session.get(captcha_url)

# 保存到本地,手动查看
with open("captcha.png", "wb") as f:
    f.write(resp.content)

# 手动输入验证码
code = input("请输入验证码: ")

# 提交登录
login_data = {
    "username": "your_account",
    "password": "your_password",
    "captcha": code
}
resp = session.post("https://example.com/login", data=login_data)

2. 使用打码平台(推荐)

对于大规模采集,手动输入不现实,可以用打码平台自动识别。

python 复制代码
import requests
import base64
# 假设使用某打码平台的 API

def recognize_captcha(image_url):
    """自动识别验证码"""
    # 下载验证码
    img_data = session.get(image_url).content
    
    # 调用打码平台 API
    api_url = "http://api.damaplatform.com/recognize"
    files = {"image": ("captcha.png", img_data)}
    data = {"token": "your_api_key"}
    
    resp = requests.post(api_url, files=files, data=data)
    return resp.json().get("result")  # 返回识别的文本

# 使用
code = recognize_captcha("https://example.com/captcha")
login_data = {
    "username": "your_account",
    "password": "your_password",
    "captcha": code
}

国内常用的打码平台:超级鹰、打码兔、图鉴等,识别准确率一般在 80%-95%。

有些验证码太难识别,那就保存登录后的 Cookie 到文件,下次直接用。

python 复制代码
import json

# 登录成功后,保存 Cookie
def save_cookies(session, filepath="cookies.json"):
    cookies = session.cookies.get_dict()
    with open(filepath, "w") as f:
        json.dump(cookies, f)
    print("Cookie 已保存")

# 下次登录时,加载 Cookie
def load_cookies(session, filepath="cookies.json"):
    with open(filepath, "r") as f:
        cookies = json.load(f)
    session.cookies.update(cookies)
    print("Cookie 已加载")

# 使用
# 第一次:手动登录,保存 Cookie
session = requests.Session()
# ... 执行登录流程 ...
save_cookies(session)

# 之后:直接加载 Cookie,无需登录
session2 = requests.Session()
load_cookies(session2)
resp = session2.get("https://example.com/profile")
print(resp.text)

Cookie 有效期: 有的网站 Cookie 几天过期,有的几个月。如果发现返回登录页,说明需要重新登录。

五、实战:模拟登录知乎

python 复制代码
import requests
import re
import time

class ZhihuLogin:
    def __init__(self):
        self.session = requests.Session()
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0",
            "Referer": "https://www.zhihu.com/signin"
        })

    def login(self, phone, password):
        """知乎手机号登录"""
        login_api = "https://www.zhihu.com/api/v3/oauth/sign_in"

        # 获取登录页面的 xsrf token
        resp = self.session.get("https://www.zhihu.com/signin")
        xsrf = re.search(r'name="xsrf" value="([^"]+)"', resp.text)
        xsrf = xsrf.group(1) if xsrf else ""

        # 登录参数
        timestamp = int(time.time() * 1000)
        data = {
            "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
            "grant_type": "password",
            "source": "com.zhihu.web",
            "username": phone,
            "password": password,
            "captcha": "",  # 验证码(可为空,触发滑块时再填)
            "lang": "cn",
            "ref_source": "homepage",
            "utm_source": "",
            "timestamp": timestamp,
            "signature": ""  # 实际需要计算签名,简化示例
        }

        resp = self.session.post(login_api, json=data)
        if resp.status_code == 200 and "access_token" in resp.text:
            print("知乎登录成功!")
            return True
        else:
            print("登录失败:", resp.text)
            return False

    def get_following(self):
        """获取关注列表(登录后)"""
        url = "https://www.zhihu.com/api/v4/me/followees"
        resp = self.session.get(url)
        return resp.json()

# 使用
zhihu = ZhihuLogin()
if zhihu.login("your_phone", "your_password"):
    following = zhihu.get_following()
    print("关注人数:", len(following.get("data", [])))

注意: 知乎的登录接口有签名校验,实际开发中可能需要更复杂的方式(如用 Selenium 模拟真实浏览器登录)。

六、Selenium 模拟登录------最通用方案

遇到接口加密、签名验证等复杂情况时,用 Selenium 控制真实浏览器登录是最省心的方案。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import pickle  # Python 序列化工具

# 启动浏览器
driver = webdriver.Chrome()
driver.get("https://weibo.com/login")

# 等待用户手动登录(给足够时间扫码或输密码)
print("请在浏览器中手动登录...")
time.sleep(30)  # 留 30 秒手动操作

# 保存 Cookie 到文件
with open("weibo_cookies.pkl", "wb") as f:
    pickle.dump(driver.get_cookies(), f)
print("Cookie 已保存")

driver.quit()

下次直接用 Cookie 登录,不用再手动扫码:

python 复制代码
from selenium import webdriver
import pickle

driver = webdriver.Chrome()
driver.get("https://weibo.com")

# 加载 Cookie
with open("weibo_cookies.pkl", "rb") as f:
    cookies = pickle.load(f)
    for cookie in cookies:
        # 注意要设置正确的 domain
        driver.add_cookie(cookie)

# 刷新页面,已登录状态
driver.get("https://weibo.com")
time.sleep(5)
print("登录成功后的页面:", driver.title)

Selenium 模拟登录的核心策略: 让用户手动登录一次 → 保存 Cookie → 后续自动使用。

七、常见问题与排查思路

问题 原因 解决
登录成功但请求报 403 缺少 Referer 或 User-Agent 加上常见的请求头
Cookie 频繁过期 网站有主动踢下线机制 缩短 Cookie 复用间隔
无法获取 Token 表单字段名动态变化 用正则或解析器动态提取
验证码无法识别 图形干扰太强 转第三方打码平台
接口加密复杂 有签名算法 用 Selenium 替代 requests

排查方法论:

  1. 浏览器 F12 → Network → 勾选 Preserve log
  2. 手动登录一次,看浏览器发了什么请求和数据
  3. 用 Python 一模一样地复现
  4. 如果某个参数找不到来源 → 可能是前端 JS 生成的 → 用 Selenium

八、总结

模拟登录的本质就是:用代码模拟浏览器和服务器之间的认证交互。

复制代码
简单场景 → requests.Session(自动管理 Cookie)
一般场景 → 加验证码识别或 Token 提取
复杂场景 → Selenium 控制浏览器 + 保存 Cookie 复用

建议掌握的顺序:requests.Session 入门 → 加验证码处理 → 最后上 Selenium。不要一上来就用 Selenium,太重了。


💡 觉得有用的话,点赞 + 关注【张老师技术栈】吧!每周更新 Java/Python/爬虫 实战干货,不让你白来。