# 架构说明(v1.2.0) 本文档梳理项目中的主要模块、职责划分以及核心流程,帮助维护者快速了解整体结构。当前版本包含短信验证码登录、Cookie 持久化以及 AI 驱动的滑块验证码自动破解功能。 ## 模块概览 ```mermaid graph TD root((项目根目录)) root --> readme[README.md
使用说明与运行指引] root --> arch[ARCHITECTURE.md
架构概览与流程说明] root --> impl[IMPLEMENTATION.md
实现细节记录] root --> quick[QUICKSTART.md
快速开始指南] root --> changelog[CHANGELOG.md
更新日志] root --> release[release.md
发布说明] root --> login_doc[login.md
早期需求与操作步骤] root --> pkg[package.json
项目配置] root --> src_dir[src/] root --> noflag[noflag/
原始验证码截图] root --> output_dir[output/
标注结果] root --> ts_spec[typescript-spec.md
编码规范] src_dir --> login_ts[login.ts
登录脚本入口] src_dir --> sms_dir[sms/] src_dir --> slider_dir[slider/] sms_dir --> sms_code[douban-code.ts
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()
• 启动 Chromium
• 复用或创建上下文
• 调用 loginWithSms()
• 保存 Cookies] --> login[loginWithSms()
• 输入手机号
• 触发短信验证码
• 自动处理滑块验证
• 自动读取 macOS 短信验证码
• 提交并校验登录结果] login --> slider[SliderController
• 等待滑块出现
• 截图并调用检测器
• 计算距离与拖动
• 失败自动重试] login --> logged[isLoggedIn()
• 检查 Cookie(dbcl2)
• 确认登录表单状态] slider --> detector[SliderDetector
• 图像缩放(800px)
• 多策略检测
• 候选框评分
• 绘制标注] detector --> candidate[CandidateSearch
• 暗区域检测
• Canny 边缘
• 颜色量化
• LAB 色彩
• IoU 去重] login --> sms[waitForDoubanCode()
• 连接 chat.db
• 跟踪最新消息
• 解析验证码
• 超时降级手动输入] sms --> autofill[自动填入验证码
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[原始验证码
(340x191)] --> img_capture[截图保存
noflag/captcha-*.png] img_capture --> img_scale[缩放至 800px
内存处理图像] img_scale --> img_detect[多策略检测] img_detect --> img_boxes[候选框数组
{x,y,w,h,score}] img_boxes --> img_filter[评分排序 + IoU 去重] img_filter --> img_best[最佳滑块位置
[b1, b2]] img_best --> img_draw[绘制标注
output/captcha-*-detected.png] img_draw --> img_distance[计算距离
(b2.x - b1.x) / scaleX] ``` 5. **短信数据流(macOS)** ```mermaid flowchart TD sms_db[~/Library/Messages/chat.db] --> sms_query[better-sqlite3 查询] sms_query --> sms_record[最新短信记录
(handle/text/date)] sms_record --> sms_parse[parseDoubanSms()
解析验证码] 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. 确保两个滑块在合理的水平距离范围内