commit 58dd30f0e327108b5f1e2f6768cfb960915c075e Author: douboer Date: Fri Oct 24 20:23:16 2025 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0922eeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +node_modules/ +dist/ +coverage/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Test +*.test.js +*.spec.js \ No newline at end of file diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..4520560 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,81 @@ +# 架构说明 + +本文档描述项目中的主要模块、职责划分以及关键流程,帮助维护者快速理解整体结构。 + +## 模块概览 + +``` +├── README.md // 使用说明与命令入口 +├── ARCHITECTURE.md // 架构与流程说明(本文档) +├── login.md // 需求与步骤原始描述 +├── block.md // 滑块破解背景与参考脚本 +├── src/ +│ ├── login.ts // 豆瓣登录主流程(Cookie 复用、短信登录、滑块自动化) +│ └── slider.ts // 滑块模拟工具函数与命令行入口 +└── typescript-spec.md // TypeScript 编码规范与示例 +``` + +## 登录流程分层 + +``` +┌─────────────────────────────────────────────┐ +│ main() │ +│ - 创建浏览器 │ +│ - 复用或创建上下文 │ +│ - 调用 loginWithSms() │ +│ - 保存 Cookies │ +└─────────────────────────────────────────────┘ + │ +┌────────────────▼────────────────────────────┐ +│ loginWithSms() │ +│ - 输入手机号 │ +│ - 点击“获取验证码” │ +│ - trySolveSlider() 自动滑块(可选) │ +│ - 提示人工输入短信验证码 │ +│ - 提交并校验登录状态 │ +└────────────────▲────────────────────────────┘ + │ +┌────────────────▼────────────────────────────┐ +│ trySolveSlider() │ +│ - locateSlider() 识别滑块所在 frame/元素 │ +│ - inferSliderDistance() 推测拖动距离 │ +│ - performSlide() 实际模拟拖动(来自 slider.ts)│ +│ - 检查滑块成功标记 │ +└─────────────────────────────────────────────┘ +``` + +- `prepareContext()`:独立负责 Cookie 复用与上下文创建。 +- `isLoggedIn()`:封装登录状态检测逻辑,避免主流程重复判断。 +- `slider.ts`:抽离通用滑块控制方法,既服务登录流程,也支持命令行调试。 + +## 依赖与交互 + +- Playwright:浏览器自动化; +- Node.js:运行环境、文件/路径操作; +- readline:控制台交互,输入验证码; +- 环境变量:控制手机号、滑块自动化开关与参数; +- `~/cookies.json`:持久化登录态,供下一次运行直接复用。 + +## 扩展点 + +- **滑块识别**:`sliderHandleSelectors` 与 `sliderTrackSelectors` 可按需扩充、覆盖,以支持不同验证码厂商。 +- **距离计算**:先截取背景图与拼图块做模板匹配确定缺口位置,必要时退回二值化列分析,再配合多组偏移反复尝试;也可用 `DOUBAN_SLIDER_DISTANCE` / `DOUBAN_SLIDER_OFFSETS` 手动覆盖。 +- **距离推断**:默认通过轨道宽度估算,特殊情况可直接设置 `DOUBAN_SLIDER_DISTANCE`。 +- **验证码输入**:目前依赖人工短信验证码,可接入短信网关或 API 进一步自动化。 +- **多账号管理**:现仅支持单账号,可通过配置文件或参数改造为批量登录。 + +## 数据流 + +1. 启动脚本读取 `DOUBAN_PHONE`、Cookies 路径等基础配置; +2. 初始化浏览器上下文,必要时进入登录页面; +3. 提交手机号,触发滑块验证; +4. 若启用自动滑块,定位组件并拖动;否则提示人工操作; +5. 读取短信验证码,提交登录表单; +6. 验证成功后将 `storageState` 写入 `cookies.json`; +7. 后续执行逻辑复用当前登录态或退出浏览器。 + +## 日志与错误处理 + +- 主流程捕获未处理异常并输出错误信息; +- 自动滑块阶段出现异常时仅发出警告并回退到人工操作; +- CLI 提示说明每一步的执行结果,便于排查问题。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..935f3cc --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# douban-crawler + +使用 Playwright + TypeScript 实现的豆瓣登录与辅助脚本,主要功能包括: + +- 通过短信验证码完成豆瓣登录,并持久化 Cookies; +- 自动尝试滑块验证,降低人工干预; +- 可单独运行的滑块模拟脚本,便于在其它场景复用。 + +## 快速开始 + +```bash +npm install +npx playwright install chromium +``` + +首次运行登录脚本需要提供手机号: + +```bash +DOUBAN_PHONE=13357108011 npm run login +``` + +若需启用滑块自动化,可增加 `DOUBAN_AUTO_SLIDER=1`,更多环境变量见下文。 + +## 脚本说明 + +| 命令 | 说明 | +| -------------------- | ------------------------------- | +| `npm run login` | 豆瓣短信登录,复用 `~/cookies.json` | +| `npm run slider --` | 手动指定页面/选择器进行滑块模拟 | + +## 配置项 + +登录流程支持以下环境变量: + +| 变量名 | 说明 | 默认值 | +| ---------------------------------- | ----------------------------------------------------------------------- | ---------------- | +| `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 | + +Cookies 将默认保存到用户主目录下的 `~/cookies.json`,可根据需要修改 `src/login.ts` 中的路径。 + +## 开发脚本 + +- `src/login.ts`:主登录流程,负责 Cookie 复用、短信登录以及滑块自动化; +- `src/slider.ts`:滑块模拟工具,既提供通用函数,也能独立运行; +- `login.md`:原始业务需求与操作步骤; +- `block.md`:滑块破解思路(Python 版)与 TypeScript 脚本参考; +- `typescript-spec.md`:团队 TypeScript 编码规范与示例。 + +## 许可 + +本项目仅用于功能验证和学习,使用时请遵守目标网站的服务条款。 diff --git a/block.md b/block.md new file mode 100644 index 0000000..404b89b --- /dev/null +++ b/block.md @@ -0,0 +1,144 @@ +使用Python和Playwright破解滑动验证码 + +滑动验证码是一种常见的验证码形式,通过拖动滑块将缺失的拼图块对准原图中的空缺位置来验证用户操作。本文将介绍如何使用Python中的OpenCV进行模板匹配,并结合Playwright实现自动化破解滑动验证码的过程。 + +所需技术 +OpenCV模板匹配:用于识别滑块在背景图中的正确位置。 +Python:主要编程语言。 +Playwright:用于浏览器自动化,模拟用户操作。 +破解过程概述 +获取验证码图像: +下载背景图和滑块图。 +进行必要的图像预处理。 +模板匹配: +使用OpenCV的模板匹配算法,计算滑块在背景图中的最佳匹配位置。 +模拟滑动: +生成模拟人类滑动的轨迹,避免被识别为机器人。 +使用Playwright模拟滑动操作。 +实现步骤 + +设置环境 +首先,我们需要设置Python环境并安装相关的依赖包。 +sh + +pip install playwright opencv-python-headless numpy +playwright install + +2. 获取并预处理验证码图像 +接下来,编写Python代码,下载验证码的背景图和滑块图,并对图像进行预处理。 + +python + +import cv2 +import numpy as np +import requests +from PIL import Image +from io import BytesIO + +def get_images(bg_url, slider_url): + bg_response = requests.get(bg_url) + slider_response = requests.get(slider_url) + +bg_image = Image.open(BytesIO(bg_response.content)) + slider_image = Image.open(BytesIO(slider_response.content)) + +bg_image.save("background.png") + slider_image.save("slider.png") + +def preprocess_images(): + bg_img = cv2.imread('background.png') + slider_img = cv2.imread('slider.png', cv2.IMREAD_GRAYSCALE) + +return bg_img, slider_img +在上述代码中,我们下载并保存验证码图像,然后将滑块图转换为灰度图进行处理。 + +模板匹配 +使用OpenCV的模板匹配算法来确定滑块在背景图中的正确位置。 +python + +def find_slider_position(bg_img, slider_img): + result = cv2.matchTemplate(bg_img, slider_img, cv2.TM_CCOEFF_NORMED) + _, _, _, max_loc = cv2.minMaxLoc(result) + top_left = max_loc + +return top_left[0] + +bg_url = 'background_image_url' +slider_url = 'slider_image_url' + +get_images(bg_url, slider_url) +bg_img, slider_img = preprocess_images() +slider_position = find_slider_position(bg_img, slider_img) + +print('Slider Position:', slider_position) +这里我们使用TM_CCOEFF_NORMED算法进行匹配,并找到最佳匹配位置的坐标。 + +模拟滑动操作 +通过生成一条模拟人类滑动的轨迹,并使用Playwright模拟滑动操作。 +python +更多内容联系1436423940 +from playwright.sync_api import sync_playwright +import time +import random + +def generate_track(distance): + track = [] + current = 0 + mid = distance * 4 / 5 + t = 0.2 + v = 0 + +while current < distance: + if current < mid: + a = 2 + else: + a = -3 + v0 = v + v = v0 + a * t + move = v0 * t + 0.5 * a * t * t + current += move + track.append(round(move)) + + return track + +def simulate_slider_move(page, slider, track): + page.mouse.move(slider['x'], slider['y']) + page.mouse.down() + for x in track: + page.mouse.move(slider['x'] + x, slider['y'], steps=10) + time.sleep(random.uniform(0.02, 0.03)) + page.mouse.up() + +with sync_playwright() as p: + browser = p.chromium.launch(headless=False) + page = browser.new_page() + page.goto('your_target_website_with_captcha')更多内容访问ttocr.com或联系1436423940 + +slider = page.query_selector('your_slider_css_selector') + bounding_box = slider.bounding_box() + +track = generate_track(slider_position) + simulate_slider_move(page, bounding_box, track) + +browser.close() + +## TypeScript 实现 + +项目中提供了等价的 TypeScript/Playwright 脚本 `src/slider.ts`,按照以下方式运行: + +```bash +npm run slider -- <滑块选择器> <拖动距离> +``` + +示例: + +```bash +npm run slider -- https://example.com '.slider-handle' 180 +``` + +脚本核心逻辑: + +- `generateTrack(distance)`:生成类似人类滑动加速/减速的位移序列; +- `performSlide(page, selector, distance)`:定位滑块元素,模拟按下、移动及释放; +- 默认以非无头模式启动浏览器(可直接观察效果),完成滑动后自动关闭。 + diff --git a/keyhtml.md b/keyhtml.md new file mode 100644 index 0000000..0ac7c07 --- /dev/null +++ b/keyhtml.md @@ -0,0 +1,1259 @@ +# 关键html+流程 +## 登录页 + + +### step1: "手机号"框输入手机号(账号),账号可配置 +### step2: 点击"获取验证码"后,弹出滑块验证浮窗。需要等待人工获取登录完成。 +### step3: 获得验证码后,在“验证码”框输入"验证码" +### step4: 点击"登录豆瓣" +
拖动下方滑块完成拼图
确定
刷新验证 刷新验证
问题反馈 问题反馈
AI生成背景
success
&nbsp;slider
刷新验证
关闭验证
确定
+### step5 登录完成后,顶部BAR中点击“读书” + + +## 书籍查询 +### step6: 在搜索框中输入书名 + +
+### step7: 点击搜索按钮🔍 + +
+## 书籍列表 +查找结果: +1. 没有找到关于 “发多少发水电” 的书,换个搜索词试试吧。 + 匹配关键字“没有找到” +
没有找到关于 “fa aafdf;jalsd'fa” 的书,换个搜索词试试吧。
+2. 返回找到的书籍 + - 返回单本书籍 + +
众生无束 : 劳动社会的未来
7.5(45人评价)
[德]理查德·大卫·普莱希特(Richard David Precht) / 廖然 / 郭欢 / 李骜然 / 中国科学技术出版社 / 2024-8 / 89.00元

想读在读读过

+- 返回多本书籍,先精确匹配标题,如果没有精确匹配标题,按打分最多者(评分最高者?)。 + +
读客文化 / 共3册 / 2021年出版
三体 : “地球往事”三部曲之一
8.9(510365人评价)
刘慈欣 / 重庆出版社 / 2008-1 / 23.00

想读在读读过

三体Ⅱ : 黑暗森林
9.3(312935人评价)
刘慈欣 / 重庆出版社 / 2008-5 / 32.00

想读在读读过

三体Ⅲ : 死神永生
9.2(292064人评价)
刘慈欣 / 重庆出版社 / 2010-11 / 38.00元

想读在读读过

三体全集 : 地球往事三部曲
9.5(209051人评价)
刘慈欣 / 重庆出版社 / 2012-1 / 168.00元

想读在读读过

中国科幻基石丛书·三体(全三册)
9.5(7473人评价)
刘慈欣 / 重庆出版社 / 2008-1 / 93.00

想读在读读过

三体
9.4(800人评价)
刘慈欣 / 重庆出版社 / 2022-12 / 42.00

想读在读读过

三体全集
9.3(19253人评价)
刘慈欣 / 读客文化 / 2018-11-26

想读在读读过

三体 : 十周年纪念版
9.6(3608人评价)
刘慈欣 / 重庆出版社 / 2017-8 / 288.00元

想读在读读过

三体 : 典藏本
8.8(4036人评价)
刘慈欣 / 重庆出版社 / 2016-6 / CNY 26.00

想读在读读过

三体·黑暗森林
9.3(1211人评价)
刘慈欣 / 重庆出版社 / 2022-4 / 68.00元

想读在读读过

三体·死神永生
9.4(826人评价)
刘慈欣 / 重庆出版社 / 2022-4 / 78.00元

想读在读读过

三体2 : 黑暗森林
9.3(6793人评价)
刘慈欣 / 重庆出版社 / 2016-6 / 42.00

想读在读读过

三体 1
8.8(3445人评价)
刘慈欣 / 读客文化 / 2018-12 / 12.09元

想读在读读过

三體
8.8(2913人评价)
劉慈欣 / 貓頭鷹出版社 / 2011-3-7 / NT$ 300.00

想读在读读过

三体3 : 死神永生
9.2(4676人评价)
刘慈欣 / 重庆出版社 / 2016-7 / 48.00

想读在读读过

+数据结构:统一一本和多本搜索列表书籍数据结构 +search-book-list = +[ + { + "title": "三体 : “地球往事”三部曲之一", + "url": "https://book.douban.com/subject/2567698/", + "cover": "https://img1.doubanio.com/view/subject/m/public/s2768378.jpg", + "rating": 8.9, + "votes": 510365, + "author": "刘慈欣", + "publisher": "重庆出版社", + "publish_date": "2008-1", + "price": "23.00" + }, + { + "title": "三体Ⅱ : 黑暗森林", + "url": "https://book.douban.com/subject/3066477/", + "cover": "https://img3.doubanio.com/view/subject/m/public/s3078482.jpg", + "rating": 9.3, + "votes": 312935, + "author": "刘慈欣", + "publisher": "重庆出版社", + "publish_date": "2008-5", + "price": "32.00" + }, + { + "title": "三体Ⅲ : 死神永生", + "url": "https://book.douban.com/subject/5363767/", + "cover": "https://img9.doubanio.com/view/subject/m/public/s26012674.jpg", + "rating": 9.2, + "votes": 292064, + "author": "刘慈欣", + "publisher": "重庆出版社", + "publish_date": "2010-11", + "price": "38.00元" + } +] +### step8: 点击书籍标题(title-text),进入书籍页: + +众生无束 : 劳动社会的未来 + +## 书籍页 + +
+
+
+
+ +
+ + 作者: + 鲍里斯·维昂 +
+ 出版社: + 广西师范大学出版社 +
+ 出品方: + 野spring +
+ 原作名: L'Écume des jours
+ + 译者: + 胥弋 +
+ 出版年: 2025-9-2
+ 页数: 344
+ 定价: 42.00元
+ 装帧: 平装
+ ISBN: 9787559885593
+
+
+
+
+ +
+ 8.0 + +
+
+
+ + 71人评价 + +
+
+
+ + 5星 + +
+ 26.8% +
+ + 4星 + +
+ 54.9% +
+ + 3星 + +
+ 18.3% +
+ + 2星 + +
+ 0.0% +
+ + 1星 + +
+ 0.0% +
+
+
+
+
+ + + +
+ + + 评价: + + + + + + + +
+
+
+ +
+
+ + + +
+ +
+
+
+