Files
douban-login/ARCHITECTURE.md
2025-10-26 10:24:17 +08:00

208 lines
9.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 架构说明v1.2.0
本文档梳理项目中的主要模块、职责划分以及核心流程帮助维护者快速了解整体结构。当前版本包含短信验证码登录、Cookie 持久化以及 AI 驱动的滑块验证码自动破解功能。
## 模块概览
```mermaid
graph TD
root((项目根目录))
root --> readme[README.md<br/>使用说明与运行指引]
root --> arch[ARCHITECTURE.md<br/>架构概览与流程说明]
root --> impl[IMPLEMENTATION.md<br/>实现细节记录]
root --> quick[QUICKSTART.md<br/>快速开始指南]
root --> changelog[CHANGELOG.md<br/>更新日志]
root --> release[release.md<br/>发布说明]
root --> login_doc[login.md<br/>早期需求与操作步骤]
root --> pkg[package.json<br/>项目配置]
root --> src_dir[src/]
root --> noflag[noflag/<br/>原始验证码截图]
root --> output_dir[output/<br/>标注结果]
root --> ts_spec[typescript-spec.md<br/>编码规范]
src_dir --> login_ts[login.ts<br/>登录脚本入口]
src_dir --> sms_dir[sms/]
src_dir --> slider_dir[slider/]
sms_dir --> sms_code[douban-code.ts<br/>macOS 短信读取]
subgraph slider["slider/ 模块"]
direction TB
slider_index[index.ts]
slider_types[types.ts]
slider_detector[detector.ts]
slider_self[detector-self-learning.ts]
slider_controller[slider-controller.ts]
slider_cli[cli.ts]
slider_validator[validator.ts]
slider_detection_dir[detection/]
slider_utils_dir[utils/]
slider_detection_dir --> slider_candidate[candidate-search.ts]
slider_utils_dir --> slider_geometry[geometry.ts]
slider_utils_dir --> slider_image[image.ts]
end
slider_dir --> slider_index
slider_dir --> slider_types
slider_dir --> slider_detector
slider_dir --> slider_self
slider_dir --> slider_controller
slider_dir --> slider_cli
slider_dir --> slider_validator
slider_dir --> slider_detection_dir
slider_dir --> slider_utils_dir
```
## 登录流程分层v1.2.0
```mermaid
flowchart TD
main[main()<br/>• 启动 Chromium<br/>• 复用或创建上下文<br/>• 调用 loginWithSms()<br/>• 保存 Cookies] --> login[loginWithSms()<br/>• 输入手机号<br/>• 触发短信验证码<br/>• 自动处理滑块验证<br/>• 自动读取 macOS 短信验证码<br/>• 提交并校验登录结果]
login --> slider[SliderController<br/>• 等待滑块出现<br/>• 截图并调用检测器<br/>• 计算距离与拖动<br/>• 失败自动重试]
login --> logged[isLoggedIn()<br/>• 检查 Cookie(dbcl2)<br/>• 确认登录表单状态]
slider --> detector[SliderDetector<br/>• 图像缩放(800px)<br/>• 多策略检测<br/>• 候选框评分<br/>• 绘制标注]
detector --> candidate[CandidateSearch<br/>• 暗区域检测<br/>• Canny 边缘<br/>• 颜色量化<br/>• LAB 色彩<br/>• IoU 去重]
login --> sms[waitForDoubanCode()<br/>• 连接 chat.db<br/>• 跟踪最新消息<br/>• 解析验证码<br/>• 超时降级手动输入]
sms --> autofill[自动填入验证码<br/>input#code]
sms --> fallback[提示手动输入验证码]
```
**关键模块职责**
- `prepareContext()`:负责加载已有 Cookie、创建新上下文以及兜底跳转登录页
- `loginWithSms()`:串联短信登录流程,涵盖用户输入与滑块自动化
- `waitForDoubanCode()`:从 macOS 信息数据库读取最新验证码,失败时回退到手动输入
- `SliderController`Playwright 集成,控制滑块验证的完整流程
- `SliderDetector`:图像处理和滑块位置检测的核心算法
- `CandidateSearch`:多种图像识别策略的并行执行
- `isLoggedIn()`:封装判定逻辑,避免各处重复编写 Cookie/页面检查
## 依赖与交互
- **Playwright**:启动浏览器、操作页面元素、持久化 `storageState`、控制滑块拖动
- **Sharp**:图像处理(缩放、边缘检测、颜色量化、模板匹配)
- **Node.js**:文件读写、路径与环境变量处理
- **better-sqlite3**:只读访问 `~/Library/Messages/chat.db`解析最新短信验证码macOS
- **readline**:作为短信读取的降级方案,提示用户手动输入验证码
- **环境变量**
- `DOUBAN_PHONE`:登录手机号(必填)
- `DOUBAN_AUTO_SLIDER`:启用自动滑块验证(可选,值为 1 时启用)
- **`~/douban-cookie.json`**:保存登录态的 storageState 文件,下次运行直接复用
- **`noflag/`**:原始验证码截图存储目录
- **`output/`**:标注结果(红框)存储目录
## 数据流v1.2.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 次)
- **[v1.2.0]** 调用 `waitForDoubanCode()` 轮询 chat.db捕获最新验证码
- 若读取失败或超时,提示用户手动输入验证码
- 将验证码填入页面并提交
3. **状态持久化**
- 登录成功后调用 `context.storageState()` 写入 `~/douban-cookie.json`
- 浏览器关闭,后续脚本可直接复用该文件
4. **图像数据流**
```mermaid
flowchart TD
img_raw[原始验证码<br/>(340x191)] --> img_capture[截图保存<br/>noflag/captcha-*.png]
img_capture --> img_scale[缩放至 800px<br/>内存处理图像]
img_scale --> img_detect[多策略检测]
img_detect --> img_boxes[候选框数组<br/>{x,y,w,h,score}]
img_boxes --> img_filter[评分排序 + IoU 去重]
img_filter --> img_best[最佳滑块位置<br/>[b1, b2]]
img_best --> img_draw[绘制标注<br/>output/captcha-*-detected.png]
img_draw --> img_distance[计算距离<br/>(b2.x - b1.x) / scaleX]
```
5. **短信数据流macOS**
```mermaid
flowchart TD
sms_db[~/Library/Messages/chat.db] --> sms_query[better-sqlite3 查询]
sms_query --> sms_record[最新短信记录<br/>(handle/text/date)]
sms_record --> sms_parse[parseDoubanSms()<br/>解析验证码]
sms_parse --> sms_autofill[自动填入 input#code]
sms_parse --> sms_manual[失败时提示手动输入]
```
## 日志与错误处理
- 关键步骤均在控制台打印提示,便于追踪流程
- **[v1.2.0]** 短信读取阶段输出 `[短信读取]` 前缀日志,包含基线 ID、轮询状态与命中消息
- **[v1.1.0]** 滑块检测过程的详细日志:
- 图像缩放信息(原始尺寸 → 检测尺寸)
- 检测到的滑块数量和位置
- 每个滑块的评分和尺寸
- 距离计算公式和结果
- 成功/失败状态和重试次数
- 默认优先使用自动短信读取,`prompt` 只在超时或读取失败时触发
- 登录失败或异常会设置 `process.exitCode` 并输出详细错误信息
- 视觉调试:`output/` 目录中的红框标注图便于人工验证检测准确性
## v1.2.0 新增能力
- **macOS 短信自动读取**:通过 `better-sqlite3` 直接查询 `chat.db`,仅处理新消息并解析验证码。
- **自动回填验证码**:等待 `input#code` 可见后自动填充,减少人为介入。
- **降级与日志机制**:超时或权限不足时回退到控制台输入,并输出明确的失败原因与排查建议。
## v1.1.0 核心创新
### 简化的距离计算算法
**核心原理**"两只小鸟嘴尖距离"
```typescript
// 双滑块模式(推荐)
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. 确保两个滑块在合理的水平距离范围内