diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4520560..46db0fd 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,81 +1,71 @@ # 架构说明 -本文档描述项目中的主要模块、职责划分以及关键流程,帮助维护者快速理解整体结构。 +本文档梳理项目中的主要模块、职责划分以及核心流程,帮助维护者快速了解整体结构。当前版本仅关注短信验证码登录与 Cookie 持久化,滑块验证码需人工操作。 ## 模块概览 ``` -├── README.md // 使用说明与命令入口 -├── ARCHITECTURE.md // 架构与流程说明(本文档) -├── login.md // 需求与步骤原始描述 -├── block.md // 滑块破解背景与参考脚本 +├── README.md // 使用说明与运行指引 +├── ARCHITECTURE.md // 架构概览与流程说明(本文档) +├── IMPLEMENTATION.md // 关键实现细节记录 +├── login.md // 早期需求与操作步骤 ├── src/ -│ ├── login.ts // 豆瓣登录主流程(Cookie 复用、短信登录、滑块自动化) -│ └── slider.ts // 滑块模拟工具函数与命令行入口 -└── typescript-spec.md // TypeScript 编码规范与示例 +│ └── login.ts // 豆瓣登录脚本入口(Cookie 复用 + 短信登录) +└── typescript-spec.md // 团队 TypeScript 编码规范 ``` ## 登录流程分层 ``` -┌─────────────────────────────────────────────┐ -│ main() │ -│ - 创建浏览器 │ -│ - 复用或创建上下文 │ -│ - 调用 loginWithSms() │ -│ - 保存 Cookies │ -└─────────────────────────────────────────────┘ +┌────────────────────────────────────┐ +│ main() │ +│ - 启动 Chromium │ +│ - 复用或创建上下文 │ +│ - 调用 loginWithSms() │ +│ - 保存 Cookies │ +└────────────────────────────────────┘ │ -┌────────────────▼────────────────────────────┐ -│ loginWithSms() │ -│ - 输入手机号 │ -│ - 点击“获取验证码” │ -│ - trySolveSlider() 自动滑块(可选) │ -│ - 提示人工输入短信验证码 │ -│ - 提交并校验登录状态 │ -└────────────────▲────────────────────────────┘ +┌────────────────▼──────────────────┐ +│ loginWithSms() │ +│ - 输入手机号 │ +│ - 触发短信验证码 │ +│ - 提示用户完成页面额外验证 │ +│ - 等待并提交短信验证码 │ +│ - 校验是否登录成功 │ +└────────────────────────────────────┘ │ -┌────────────────▼────────────────────────────┐ -│ trySolveSlider() │ -│ - locateSlider() 识别滑块所在 frame/元素 │ -│ - inferSliderDistance() 推测拖动距离 │ -│ - performSlide() 实际模拟拖动(来自 slider.ts)│ -│ - 检查滑块成功标记 │ -└─────────────────────────────────────────────┘ +┌────────────────▼──────────────────┐ +│ isLoggedIn() │ +│ - 检查关键 Cookie(dbcl2) │ +│ - 确认登录表单是否仍然可见 │ +└────────────────────────────────────┘ ``` -- `prepareContext()`:独立负责 Cookie 复用与上下文创建。 -- `isLoggedIn()`:封装登录状态检测逻辑,避免主流程重复判断。 -- `slider.ts`:抽离通用滑块控制方法,既服务登录流程,也支持命令行调试。 +- `prepareContext()`:负责加载已有 Cookie、创建新上下文以及兜底跳转登录页。 +- `loginWithSms()`:串联短信登录流程,涵盖用户输入与结果确认。 +- `isLoggedIn()`:封装判定逻辑,避免各处重复编写 Cookie/页面检查。 ## 依赖与交互 -- Playwright:浏览器自动化; -- Node.js:运行环境、文件/路径操作; -- readline:控制台交互,输入验证码; -- 环境变量:控制手机号、滑块自动化开关与参数; -- `~/cookies.json`:持久化登录态,供下一次运行直接复用。 - -## 扩展点 - -- **滑块识别**:`sliderHandleSelectors` 与 `sliderTrackSelectors` 可按需扩充、覆盖,以支持不同验证码厂商。 -- **距离计算**:先截取背景图与拼图块做模板匹配确定缺口位置,必要时退回二值化列分析,再配合多组偏移反复尝试;也可用 `DOUBAN_SLIDER_DISTANCE` / `DOUBAN_SLIDER_OFFSETS` 手动覆盖。 -- **距离推断**:默认通过轨道宽度估算,特殊情况可直接设置 `DOUBAN_SLIDER_DISTANCE`。 -- **验证码输入**:目前依赖人工短信验证码,可接入短信网关或 API 进一步自动化。 -- **多账号管理**:现仅支持单账号,可通过配置文件或参数改造为批量登录。 +- **Playwright**:启动浏览器、操作页面元素、持久化 `storageState`。 +- **Node.js**:文件读写、路径与环境变量处理。 +- **readline**:在控制台等待用户输入短信验证码。 +- **环境变量**:当前仅使用 `DOUBAN_PHONE` 指定登录手机号。 +- **`~/douban-cookie.json`**:保存登录态的 storageState 文件,下次运行直接复用。 ## 数据流 -1. 启动脚本读取 `DOUBAN_PHONE`、Cookies 路径等基础配置; -2. 初始化浏览器上下文,必要时进入登录页面; -3. 提交手机号,触发滑块验证; -4. 若启用自动滑块,定位组件并拖动;否则提示人工操作; -5. 读取短信验证码,提交登录表单; -6. 验证成功后将 `storageState` 写入 `cookies.json`; -7. 后续执行逻辑复用当前登录态或退出浏览器。 +1. 读取 `DOUBAN_PHONE`,未配置则终止; +2. 若存在本地 Cookie 文件,加载后访问登录页以确认是否仍然有效; +3. 无有效登录态时执行短信登录: + - Playwright 填写手机号并请求验证码; + - 用户在浏览器中手动完成滑块等验证; + - 控制台输入短信验证码并提交; +4. 登录成功后调用 `context.storageState()` 写入 `~/douban-cookie.json`; +5. 浏览器关闭,后续脚本可直接复用该文件。 ## 日志与错误处理 -- 主流程捕获未处理异常并输出错误信息; -- 自动滑块阶段出现异常时仅发出警告并回退到人工操作; -- CLI 提示说明每一步的执行结果,便于排查问题。 +- 关键步骤均在控制台打印提示,便于追踪流程; +- 验证码相关操作采用提示 + `prompt` 方式等待人工输入; +- 登录失败或异常会设置 `process.exitCode` 并输出详细错误信息。 diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 9b7e4bd..463b15d 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -1,237 +1,80 @@ -# 滑块验证自动化实现总结 +# 登录脚本实现笔记 -## 实现概述 - -参考 https://github.com/omigo/crack-slide-captcha 项目,成功实现了滑轨自动验证功能。 +本文记录当前版本豆瓣登录脚本的实现细节、关键函数以及后续可扩展点。滑块验证码相关逻辑已移除,若页面出现额外验证需人工完成。 ## 文件结构 ``` src/ -├── login.ts # 主登录流程,集成滑块验证 -├── slider.ts # 滑块验证核心实现 -└── examples.ts # 使用示例代码 +└── login.ts # Playwright 入口脚本 ``` -## 核心功能 +辅助文档位于项目根目录: -### 1. slider.ts - 滑块验证核心模块 +- `README.md`:使用说明与常见问题; +- `ARCHITECTURE.md`:整体架构与流程拆解; +- `login.md`:早期需求说明,可作为手动操作参考。 -**主要函数:** +## 核心流程 -- `autoSlide(page, config)` - 自动完成滑块验证 -- `hasSlider(page, config)` - 检测是否存在滑块 -- `waitAndHandleSlider(page, config)` - 等待并自动处理滑块 -- `generateTrack(distance)` - 生成模拟人类的滑动轨迹 -- `calculateDistance(bgBuffer, pieceBuffer)` - 通过图像处理计算滑动距离 +1. **读取配置** + 通过 `process.env.DOUBAN_PHONE` 获取手机号,缺失时直接退出。 -**核心特性:** +2. **准备浏览器上下文** (`prepareContext`) + - 若存在 `~/douban-cookie.json`,以 `storageState` 形式加载; + - 打开登录页并调用 `isLoggedIn` 校验是否仍在登录态; + - 失效时关闭旧上下文并创建全新 session。 -1. **图像处理识别** - - 使用 sharp 库处理图像 - - 灰度化和边缘检测 - - 计算缺口位置 +3. **执行短信登录** (`loginWithSms`) + - 输入手机号 → 点击「获取验证码」; + - 控制台提醒用户在浏览器中手动完成滑块等页面验证; + - 通过 `prompt` 等待用户输入短信验证码并提交; + - 等待 Playwright 检测到页面离开登录地址或抛出超时。 -2. **真实轨迹模拟** - - 三段式速度曲线:加速 → 匀速 → 减速 - - 垂直方向随机抖动 - - 随机总时长(1-2秒) - - 随机反应时间 +4. **确认状态并写入 Cookie 文件** + - `isLoggedIn` 再次判断是否登录成功; + - 调用 `context.storageState({ path })` 将状态写入 `~/douban-cookie.json`; + - 终端提示成功信息,方便用户确认文件路径。 -3. **多次重试机制** - - 默认偏移序列:[0, -2, 2, -5, 5, -10, 10] - - 自动尝试不同偏移值 - - 直到成功或尝试完毕 +## 关键函数 -### 2. login.ts - 登录流程集成 +### `isLoggedIn(page: Page): Promise` -**修改内容:** +检查 `dbcl2` Cookie 是否存在,并确认登录表单元素是否仍可见。该组合可较准确判断是否处于登录态,同时避免依赖豆瓣首页 DOM。 -1. 导入滑块验证模块 -2. 添加 `AUTO_SLIDER` 环境变量支持 -3. 在 `loginWithSms` 函数中集成滑块处理: - - 点击"获取验证码"后检测滑块 - - 根据配置自动或手动完成验证 - - 支持环境变量自定义参数 +### `prepareContext(browser: Browser)` -### 3. examples.ts - 使用示例 +负责上下文复用策略:优先尝试加载本地 Cookie 创建上下文,如果判定仍未登录则回退到全新会话并跳转登录页。函数返回 `{ context, page, usedCookies }`,调用方可据此判断是否需要重走登录流程。 -提供了 6 个详细示例: -1. 基础使用 - 自动检测并处理 -2. 手动检测和处理 -3. 自定义配置 -4. 登录流程集成 -5. 批量处理多个滑块 -6. 使用环境变量配置 +### `loginWithSms(page: Page, phone: string)` -## 使用方法 +串联短信验证码登录的主要逻辑,所有用户交互点都通过控制台提示: -### 在登录时启用自动滑块 +- 页面操作由脚本自动完成(填手机号、点击按钮); +- 人机验证与短信输入由用户处理; +- 函数内部对提交过程设置合理的等待时间,避免过早关闭浏览器。 -```bash -# 基础使用 -DOUBAN_AUTO_SLIDER=1 DOUBAN_PHONE=13800138000 npm run login +### `main()` -# 带自定义参数 -DOUBAN_AUTO_SLIDER=1 \ -DOUBAN_SLIDER_DISTANCE=250 \ -DOUBAN_SLIDER_OFFSETS=0,-5,5,-10,10 \ -DOUBAN_PHONE=13800138000 \ -npm run login -``` +作为 CLI 入口,负责整体 orchestrate:校验配置 → 启动浏览器 → 调用上述函数 → 捕获异常并设置 `process.exitCode`。 -### 独立测试滑块功能 +## 错误处理与提示 -```bash -npm run slider -``` +- 打印清晰的步骤提示,例如“请等待短信验证码…”、“正在提交验证码…”; +- 捕获 Playwright 的超时异常,允许在页面未完全跳转时通过 `isLoggedIn` 再次确认; +- 如登录失败会输出明确日志并保持退出码非零,方便在 CI 或脚本中检测。 -### 在代码中调用 +## 手动操作注意事项 -```typescript -import { autoSlide, hasSlider } from './slider'; +- Playwright 会以非无头模式启动 Chromium,务必保持窗口前台以便人工处理滑块或图形验证码; +- 如短信验证码输入错误,可重新运行脚本并继续人工操作; +- 保存的 `douban-cookie.json` 与账号强绑定,若切换账号需手动删除或覆盖该文件。 -// 检测并自动处理 -if (await hasSlider(page)) { - const success = await autoSlide(page, { - distance: 250, - offsets: [0, -5, 5, -10, 10], - }); -} -``` +## 后续拓展建议 -## 配置选项 +1. **多账号支持**:通过配置文件或命令行参数管理多组手机号与存储路径; +2. **验证码服务集成**:接入外部短信/验证码平台以减少人工步骤; +3. **任务编排**:在登录后追加业务逻辑(例如抓取列表、导出数据),可在 `main` 函数成功分支追加调用; +4. **CLI 体验**:封装命令行参数解析,避免频繁依赖环境变量。 -支持以下环境变量: - -| 变量名 | 说明 | 默认值 | -|--------|------|--------| -| `DOUBAN_AUTO_SLIDER` | 启用自动滑块 | `0` | -| `DOUBAN_SLIDER_DISTANCE` | 手动指定距离(像素) | 自动计算 | -| `DOUBAN_SLIDER_OFFSETS` | 偏移尝试序列(逗号分隔) | `0,-2,2,-5,5,-10,10` | -| `DOUBAN_SLIDER_HANDLE_SELECTOR` | 滑块按钮选择器 | 多个候选 | -| `DOUBAN_SLIDER_TRACK_SELECTOR` | 滑块轨道选择器 | 多个候选 | -| `DOUBAN_SLIDER_BG_SELECTOR` | 背景图选择器 | 多个候选 | -| `DOUBAN_SLIDER_PIECE_SELECTOR` | 缺口图选择器 | 多个候选 | -| `DOUBAN_SLIDER_TIMEOUT` | 超时时间(毫秒) | `20000` | - -## 技术亮点 - -### 1. 图像识别算法 - -```typescript -// 边缘检测卷积核 -kernel: [-1, -1, -1, -1, 8, -1, -1, -1, -1] - -// 窗口平滑减少噪声 -const windowScore = columnScores.slice(i - 5, i + 5).reduce((a, b) => a + b, 0); -``` - -### 2. 轨迹生成算法 - -```typescript -// 加速阶段 - 二次函数 -const x = accelDist * ratio * ratio; - -// 减速阶段 - 平方根函数 -const x = decelDist * Math.sqrt(ratio); - -// 垂直抖动 -const y = (Math.random() - 0.5) * range; -``` - -### 3. 多次重试逻辑 - -```typescript -for (const offset of offsets) { - const adjustedDistance = distance + offset; - const track = generateTrack(adjustedDistance); - await executeSlide(page, handle, track); - - if (await checkSuccess(page)) { - return true; - } -} -``` - -## 参考实现对比 - -| 特性 | 原项目 (Go+OpenCV) | 本实现 (TypeScript+Sharp) | -|------|-------------------|-------------------------| -| 语言环境 | Go | TypeScript/Node.js | -| 图像处理 | OpenCV | Sharp | -| 执行方式 | Go服务 + JS客户端 | 纯 Playwright | -| 模板匹配 | 多种算法 | 边缘检测 + 列分析 | -| 轨迹模拟 | 简单匀速 | 三段式变速 + 抖动 | -| 集成方式 | 独立服务 | 代码库集成 | - -## 优化建议 - -### 提高识别准确率 - -1. **使用更强大的图像处理算法** - - 集成 OpenCV.js - - 实现模板匹配 - - 使用机器学习模型 - -2. **缓存已识别的验证码** - - 计算图片哈希 - - 缓存距离结果 - - 避免重复计算 - -3. **动态调整偏移策略** - - 记录成功的偏移值 - - 学习最优偏移分布 - - 自适应调整 - -### 提高真实性 - -1. **更复杂的轨迹算法** - - 贝塞尔曲线 - - 真实数据训练 - - 个性化轨迹 - -2. **设备指纹模拟** - - Canvas 指纹 - - WebGL 指纹 - - 音频指纹 - -3. **行为特征模拟** - - 鼠标移动历史 - - 按键节奏 - - 页面交互模式 - -## 注意事项 - -1. ⚠️ **准确率限制**:简化的图像识别方法准确率约 70-80% -2. ⚠️ **反爬限制**:频繁使用可能触发更严格验证 -3. ⚠️ **合规使用**:仅用于学习研究,遵守网站服务条款 -4. ⚠️ **维护成本**:需要根据验证码更新调整选择器 - -## 测试情况 - -✅ TypeScript 编译通过 -✅ 代码结构清晰 -✅ 类型定义完整 -✅ 文档详细完善 - -## 后续改进 - -- [ ] 实际测试豆瓣滑块验证 -- [ ] 根据测试结果优化参数 -- [ ] 添加更多验证码类型支持 -- [ ] 集成更强大的图像识别库 -- [ ] 添加单元测试 -- [ ] 性能优化 - -## 相关文档 - -- [SLIDER.md](../SLIDER.md) - 详细使用文档 -- [README.md](../README.md) - 项目总览 -- [examples.ts](./examples.ts) - 使用示例 - -## 参考资源 - -- [crack-slide-captcha](https://github.com/omigo/crack-slide-captcha) - 原始参考项目 -- [Sharp 文档](https://sharp.pixelplumbing.com/) -- [Playwright 文档](https://playwright.dev/) +以上内容覆盖当前脚本主要实现。若后续重新引入滑块自动化,可在此文档扩展新的模块说明。 diff --git a/README.md b/README.md index b31a2ee..e85e82b 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,72 @@ # douban-crawler -使用 Playwright + TypeScript 实现的豆瓣登录与辅助脚本,主要功能包括: +> Playwright + TypeScript 脚本,用于完成豆瓣短信验证码登录,并将登录态持久化到本地 Cookie 文件。滑块验证码需人工处理,本项目不再尝试自动识别。 -- 通过短信验证码完成豆瓣登录,并持久化 Cookies; -- 自动尝试滑块验证,降低人工干预; -- 可单独运行的滑块模拟脚本,便于在其它场景复用。 +## 功能概览 -## 快速开始 +- 启动 Chromium 浏览器并访问豆瓣登录页; +- 自动填写手机号,触发短信验证码; +- 控制台提示用户完成页面内的额外验证(如滑块)并输入短信验证码; +- 登录成功后将 Cookie 状态保存到 `~/douban-cookie.json`,后续运行可直接复用。 + +## 环境准备 ```bash npm install npx playwright install chromium ``` -首次运行登录脚本需要提供手机号: +需要 Node.js ≥ 18。Playwright 会自动下载 Chromium,首次运行请确保网络可访问 Playwright CDN。 -```bash -DOUBAN_PHONE=13357108011 npm run login -``` +## 使用方式 -若需启用滑块自动化,可增加 `DOUBAN_AUTO_SLIDER=1`,更多环境变量见下文。 +1. 设置手机号环境变量并运行登录脚本: -## 脚本说明 + ```bash + DOUBAN_PHONE=13800000000 npm run login + ``` -| 命令 | 说明 | -| -------------------- | ------------------------------- | -| `npm run login` | 豆瓣短信登录,复用 `~/cookies.json` | -| `npm run slider` | 独立测试滑块验证功能 | +2. 浏览器会自动打开豆瓣登录页,脚本完成以下操作: + - 填入手机号并点击「获取验证码」; + - 控制台提示等待页面验证(若出现滑块,请手动完成); + - 控制台等待用户输入短信验证码; + - 验证码提交成功后,脚本将登录态写入 `~/douban-cookie.json` 并退出。 -## 配置项 +3. 下次运行会优先尝试加载该 Cookie 文件,若仍在有效期内可直接登录。 -登录流程支持以下环境变量: +## 命令列表 -| 变量名 | 说明 | 默认值 | -| ---------------------------------- | ----------------------------------------------------------------------- | ---------------- | -| `DOUBAN_PHONE` | 登录手机号(必填) | - | -| `DOUBAN_AUTO_SLIDER` | 是否尝试自动完成滑块验证(`1` 表示开启) | `0` | -| `DOUBAN_SLIDER_DISTANCE` | 自定义滑块拖动距离(像素);缺省时脚本根据轨道宽度推测 | 自动推测或 200px | -| `DOUBAN_SLIDER_OFFSETS` | 距离微调列表(逗号分隔,逐个尝试以校正识别误差) | 自动选择 | -| `DOUBAN_SLIDER_HANDLE_SELECTOR` | 覆盖默认滑块按钮选择器 | 内置候选 | -| `DOUBAN_SLIDER_TRACK_SELECTOR` | 覆盖默认滑块轨道选择器 | 内置候选 | -| `DOUBAN_SLIDER_BG_SELECTOR` | 覆盖滑块背景图选择器 | 内置候选 | -| `DOUBAN_SLIDER_PIECE_SELECTOR` | 覆盖滑块拼图块选择器 | 内置候选 | -| `DOUBAN_SLIDER_TIMEOUT` | 等待滑块组件出现的超时(毫秒) | 20000 | +| 命令 | 说明 | +| --------------- | ---------------------------- | +| `npm run login` | 启动豆瓣登录流程并保存 Cookie | -Cookies 将默认保存到用户主目录下的 `~/cookies.json`,可根据需要修改 `src/login.ts` 中的路径。 +## 可配置项 -## 滑块验证自动化 +当前脚本仅使用一个环境变量: -本项目集成了滑块验证码自动破解功能,参考了 [crack-slide-captcha](https://github.com/omigo/crack-slide-captcha) 项目。 +| 变量名 | 说明 | 是否必填 | 默认值 | +| -------------- | ---------------- | -------- | ------ | +| `DOUBAN_PHONE` | 登录手机号(大陆) | 必填 | - | -### 核心特性 +若需要更改 Cookie 保存位置,可在 `src/login.ts` 中调整 `COOKIES_PATH` 定义。 -- 🔍 **智能识别**:通过图像处理自动计算滑动距离 -- 🎭 **模拟真人**:先快后慢的速度曲线、轨迹抖动、随机反应时间 -- 🔄 **多次重试**:支持偏移修正,提高成功率 -- ⚙️ **高度可配**:支持自定义选择器、距离、偏移等参数 +## 工作流程说明 -### 快速使用 +1. 读取 `DOUBAN_PHONE`,未提供则直接退出; +2. 若存在 `~/douban-cookie.json`,加载后访问登录页并校验登录态; +3. 如未登录,执行短信验证码流程,期间需手动处理页面可能出现的滑块或图形验证码; +4. 用户在终端输入收到的短信验证码; +5. 验证通过后,将当前浏览器上下文的 `storageState` 写入 `~/douban-cookie.json`。 + +## 常见问题 + +- **登录后仍提示手机号未填写?** 确认 Playwright 浏览器窗口焦点在页面内,避免浏览器阻止自动填充。 +- **提示滑块验证但脚本无动作?** 脚本已停止自动滑块功能,请在浏览器中手动拖动滑块完成验证。 +- **Cookie 未生成?** 只有当脚本确认登录成功时才会写入 Cookie。若终端未看到 “登录成功,Cookies 已保存…” 的日志,请检查短信验证码是否正确。 + +## 声明 + +该项目仅供学习与功能验证,请勿用于违反豆瓣平台服务条款的场景。开发者需自行承担使用风险。 ```bash # 启用自动滑块验证