Files
douban-login/ARCHITECTURE.md
2025-10-25 23:39:25 +08:00

9.0 KiB
Raw Blame History

架构说明v1.1.0

本文档梳理项目中的主要模块、职责划分以及核心流程帮助维护者快速了解整体结构。当前版本包含短信验证码登录、Cookie 持久化以及 AI 驱动的滑块验证码自动破解功能。

模块概览

├── README.md              // 使用说明与运行指引
├── ARCHITECTURE.md        // 架构概览与流程说明(本文档)
├── IMPLEMENTATION.md      // 关键实现细节记录
├── QUICKSTART.md          // 快速开始指南
├── CHANGELOG.md           // 版本更新日志
├── release.md             // 发布说明
├── login.md               // 早期需求与操作步骤
├── package.json           // 项目配置v1.1.0
├── src/
│   ├── login.ts           // 豆瓣登录脚本入口(集成滑块验证)
│   └── slider/            // 滑块验证模块v1.1.0 新增)
│       ├── index.ts       // 模块导出
│       ├── types.ts       // 类型定义
│       ├── detector.ts    // 主滑块检测器
│       ├── detector-self-learning.ts  // 第二滑块检测
│       ├── slider-controller.ts       // 滑块控制器
│       ├── cli.ts         // CLI 批量工具
│       ├── validator.ts   // 结果验证工具
│       ├── detection/
│       │   └── candidate-search.ts    // 多策略检测
│       └── utils/
│           ├── geometry.ts            // 几何计算
│           └── image.ts               // 图像处理
├── noflag/                // 原始验证码截图输出目录
├── output/                // 标注结果输出目录
└── typescript-spec.md     // 团队 TypeScript 编码规范

登录流程分层v1.1.0

┌─────────────────────────────────────────┐
│ main()                                  │
│  - 启动 Chromium                        │
│  - 复用或创建上下文                     │
│  - 调用 loginWithSms()                  │
│  - 保存 Cookies                         │
└─────────────────────────────────────────┘
                   │
┌──────────────────▼────────────────────┐
│ loginWithSms()                        │
│  - 输入手机号                         │
│  - 触发短信验证码                     │
│  - [v1.1.0] 自动处理滑块验证          │
│  - 等待并提交短信验证码               │
│  - 校验是否登录成功                   │
└───────────────────────────────────────┘
                   │
      ┌────────────┴──────────────┐
      │                           │
┌─────▼──────────────┐  ┌─────────▼──────────────┐
│ SliderController   │  │ isLoggedIn()           │
│  - 等待滑块出现    │  │  - 检查 Cookiedbcl2 │
│  - 截图到 noflag/  │  │  - 确认登录表单状态     │
│  - 调用 detector   │  └────────────────────────┘
│  - 计算距离        │
│  - 拖动滑块        │
│  - 验证成功标识    │
│  - 失败重试(10次)  │
└────────────────────┘
         │
┌────────▼───────────────┐
│ SliderDetector         │
│  - 图像缩放(800px)     │
│  - 多策略检测          │
│  - 候选框评分          │
│  - 绘制标注到 output/  │
└────────────────────────┘
         │
┌────────▼───────────────┐
│ CandidateSearch        │
│  - 暗区域检测          │
│  - Canny 边缘检测      │
│  - 颜色量化            │
│  - LAB 色彩空间        │
│  - IoU 去重            │
└────────────────────────┘

关键模块职责

  • prepareContext():负责加载已有 Cookie、创建新上下文以及兜底跳转登录页
  • loginWithSms():串联短信登录流程,涵盖用户输入与滑块自动化
  • SliderControllerPlaywright 集成,控制滑块验证的完整流程
  • SliderDetector:图像处理和滑块位置检测的核心算法
  • CandidateSearch:多种图像识别策略的并行执行
  • isLoggedIn():封装判定逻辑,避免各处重复编写 Cookie/页面检查

依赖与交互

  • Playwright:启动浏览器、操作页面元素、持久化 storageState、控制滑块拖动
  • Sharp:图像处理(缩放、边缘检测、颜色量化、模板匹配)
  • Node.js:文件读写、路径与环境变量处理
  • readline:在控制台等待用户输入短信验证码
  • 环境变量
    • DOUBAN_PHONE:登录手机号(必填)
    • DOUBAN_AUTO_SLIDER:启用自动滑块验证(可选,值为 1 时启用)
  • ~/douban-cookie.json:保存登录态的 storageState 文件,下次运行直接复用
  • noflag/:原始验证码截图存储目录
  • output/:标注结果(红框)存储目录

数据流v1.1.0

  1. 初始化阶段

    • 读取 DOUBAN_PHONE,未配置则终止
    • 检查 DOUBAN_AUTO_SLIDER 环境变量
    • 若存在本地 Cookie 文件,加载后访问登录页以确认是否仍然有效
  2. 登录流程

    • 无有效登录态时执行短信登录:
      • Playwright 填写手机号并请求验证码
      • [v1.1.0] 自动检测并处理滑块验证码:
        1. 等待验证码 iframe 加载
        2. 截图验证码区域到 noflag/ 目录
        3. 使用 Sharp 将图像缩放到 800px 宽度
        4. 并行运行四种检测策略
        5. 计算距离:(缺口X - 滑块X) / scaleX
        6. 绘制红框标注保存到 output/ 目录
        7. 拖动滑块到计算位置
        8. 检测成功标识(.tc-success
        9. 失败则刷新重试(最多 10 次)
      • 控制台输入短信验证码并提交
  3. 状态持久化

    • 登录成功后调用 context.storageState() 写入 ~/douban-cookie.json
    • 浏览器关闭,后续脚本可直接复用该文件
  4. 图像数据流

    原始验证码(340x191)
          │
          ▼ 截图
    noflag/captcha-timestamp.png
          │
          ▼ 缩放到 800px
    内存中的处理图像(800x449)
          │
          ▼ 多策略检测
    候选框数组 [{x,y,w,h,score}]
          │
          ▼ 评分排序 + IoU去重
    最佳滑块位置 [b1, b2]
          │
          ▼ 绘制红框
    output/captcha-timestamp-detected.png
          │
          ▼ 计算距离
    移动距离 = (b2.x - b1.x) / scaleX
    

日志与错误处理

  • 关键步骤均在控制台打印提示,便于追踪流程
  • [v1.1.0] 滑块检测过程的详细日志:
    • 图像缩放信息(原始尺寸 → 检测尺寸)
    • 检测到的滑块数量和位置
    • 每个滑块的评分和尺寸
    • 距离计算公式和结果
    • 成功/失败状态和重试次数
  • 验证码相关操作采用提示 + prompt 方式等待人工输入
  • 登录失败或异常会设置 process.exitCode 并输出详细错误信息
  • 视觉调试:output/ 目录中的红框标注图便于人工验证检测准确性

v1.1.0 核心创新

简化的距离计算算法

核心原理"两只小鸟嘴尖距离"

// 双滑块模式(推荐)
const distance = (box2.x - box1.x) / scaleX;

// 单滑块模式(兜底)
const distance = box.x / scaleX;

为什么这样简单?

  1. 检测在 800px 宽度图像上进行scaleX ≈ 2.35
  2. 两个滑块的左边界水平距离就是移动距离(缩放坐标系)
  3. 除以 scaleX 转换回实际显示坐标系340px
  4. 避免复杂的 iframe 偏移、页面坐标转换等计算

v1.0.0 vs v1.1.0

  • v1.0.0:需要人工完成滑块验证
  • v1.1.0:自动检测、计算、拖动,成功率约 50%

多策略并行检测

并行运行四种算法,提高鲁棒性:

  1. 暗区域检测:基于亮度阈值查找暗色滑块
  2. Canny 边缘检测:查找边缘密集区域
  3. 颜色量化K-means 聚类找独特色块
  4. LAB 色彩空间:在感知均匀的色彩空间中检测

候选框通过 IoU 去重,避免重复检测同一个滑块。

自学习模板匹配

使用第一个检测到的滑块作为模板,在图像中查找第二个滑块:

  1. 提取第一个滑块的边缘特征
  2. 在剩余区域进行模板匹配
  3. 验证 y 坐标一致性(偏差 < 25px
  4. 确保两个滑块在合理的水平距离范围内