Compare commits

...

1 Commits

Author SHA1 Message Date
travel cd65b4ccc9 docs: 补充不使用 Playwright 的详细技术说明
在 README 中说明 DOM 自动化脆弱性、风控冲突、二次验证、架构复杂度及 HTTP SSO 取舍,便于后续维护与部署决策。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 11:07:56 +08:00
+98 -3
View File
@@ -13,13 +13,108 @@
> 若服务器 IP 被抖音风控(错误码 4031),请配置**住宅代理 API**。 > 若服务器 IP 被抖音风控(错误码 4031),请配置**住宅代理 API**。
## 为什么不使用 Playwright
本项目早期版本基于 **Playwright + Headless Chromium** 实现扫码登录,但在实际使用与维护中暴露出大量问题。经过多轮修复后,仍无法稳定支撑「一键提取 Cookie」这一核心目标,因此彻底移除 Playwright,改为直接调用抖音 Passport / SSO 的 HTTP 接口。
### 1. 登录流程依赖脆弱的 DOM 自动化
Playwright 方案需要模拟用户在网页上的每一步操作:
- 打开 `douyin.com` 并点击「登录」
- 切换到「扫码登录」标签
- 从页面 `<img>` / `<canvas>` 中提取二维码
- 扫码后识别「身份验证」弹窗,再自动点击「短信验证码」「发送验证码」等按钮
- 跨 iframe、Shadow DOM 查找输入框并填入验证码
抖音前端 UI 频繁改版,按钮文案、CSS 类名、弹窗结构随时可能变化。任何一次改版都会导致:
- 找不到登录入口或二维码
- 误判登录状态(例如把「等待确认」当成「需要验证」)
- 自动填验证码失败,用户无法完成二次验证
这类问题无法通过局部修补根治,因为**本质是在用浏览器自动化对抗一个持续变化的前端**。
### 2. Headless 模式与风控冲突
无头浏览器(`headless: true`)极易触发抖音反爬与风控策略:
- `navigator.webdriver` 等特征可被检测
- 滑块、图形验证码在 headless 下几乎无法完成
- 扫码后常出现二次验证(短信 / 密码 / 滑块),自动化脚本无法可靠处理
改为「可见浏览器 + 用户手动验证」虽能缓解,但又带来新问题:必须在服务器上弹出 GUI 窗口(Linux 无桌面环境不可用),且仍依赖 DOM 点击逻辑,**并没有降低维护成本**。
### 3. 二次验证是最大不稳定因素
真实场景中,用户手机确认登录后,网页端仍可能要求:
- 接收短信验证码
- 验证登录密码
- 完成滑块验证
旧方案试图用 Playwright 自动点击、自动填码、自动提交,实际效果很差:
- 验证码输入框分布在不同 iframe 中,选择器经常失效
- 轮询逻辑与用户手动操作互相覆盖(例如自动点击「接收短信」与用户选择密码验证冲突)
- 提交按钮文案不统一(「确定」「提交」「验证」等),跨 frame 点击失败率高
**Cookie 提取工具不应承担「代替用户在网页里完成风控验证」的职责**;这类步骤更适合由用户在 App 或官方页面自行完成,服务端只负责检测登录结果。
### 4. 架构复杂、难以维护
Playwright 版本将全部逻辑塞在单文件 `app.py`(约 1200 行),并引入额外复杂度:
| 问题 | 说明 |
|------|------|
| Flask 与 asyncio 桥接 | 需要自定义 `run_async_sync()` 和全局 event loop,易出现协程/线程竞态 |
| 浏览器生命周期 | 登录成功即关闭浏览器,调试困难;异常时容易残留僵尸进程 |
| 单全局会话 | `LoginSession` + 锁,同一时刻仅支持一个扫码任务 |
| 部署依赖重 | 除 Python 外还需 `playwright install chromium`(数百 MB |
| 二维码提取不可靠 | 常退化为「整页截图」,用户扫到的并非标准 QR |
模块化拆分后,浏览器相关代码仍是最难测试、最难 Mock 的部分,**投入产出比极低**。
### 5. 与项目目标不匹配
本项目的核心目标是:
> **扫码登录成功后,导出网页端可用的 Cookie JSON**
完成这一目标,并不需要渲染完整页面,只需要走通抖音官方的 **扫码 SSO 协议**
```
get_qrcode → 展示二维码 → check_qrconnect 轮询 → redirect_url 换票 → 拿到 Cookie
```
这是一条稳定的 HTTP 状态机,与页面 DOM 无关。抖音网页版、创作者平台、早期开源项目均采用同一套 `sso.douyin.com` 接口,**协议层比 UI 层可靠得多**。
### 6. HTTP SSO 方案的优势与代价
**优势:**
- 无需安装 Chromium,部署仅需 `pip install -r requirements.txt`
- 无 GUI / 无头浏览器依赖,适合 Linux 服务器与 Docker
- 逻辑清晰:`backend/sso/qr_login.py` 独立维护,易于单测
- 资源占用低:一个 `requests.Session` 即可,内存占用从数百 MB 降至数 MB
- 前端只展示二维码与轮询状态,不再耦合浏览器截图、验证表单等复杂 UI
**代价(需知晓):**
- 依赖抖音 SSO 接口,若接口参数变更需跟进适配
- 部分机房 IP 会被风控(错误码 `4031`),需配置住宅代理 API
- 若账号在 SSO 层仍要求额外验证,需用户在手机端完成;HTTP 层无法代替网页内操作
综合权衡:**HTTP SSO 更轻、更稳、更易部署**,更符合「一键提取 Cookie」的产品定位;Playwright 适合需要完整浏览器行为的场景(如自动化发帖、复杂交互),**不适合作为 Cookie 提取的主路径**。
### 与其他方案对比 ### 与其他方案对比
| 方案 | 说明 | 本项目 | | 方案 | 说明 | 本项目 |
|------|------|--------| |------|------|--------|
| HTTP SSO | 逆向 passport 接口,轻量快速 | **当前采用** | | HTTP SSO | 直接调用 passport / SSO 接口,轻量、可部署 | **当前采用** |
| Playwright | 模拟浏览器,重、易碎 | 已移除 | | Playwright | 模拟真实浏览器,重、易受 UI 改版影响 | **已移除**(见上文) |
| 开放平台 OAuth | 需注册应用,返回 access_token 非网页 Cookie | 不适用 | | 开放平台 OAuth | 需注册应用,返回 `access_token`非网页 Cookie | 不适用 |
| 读取本机浏览器 Cookie | 需用户事先在 Chrome 登录,非远程一键扫码 | 未采用 |
## 环境要求 ## 环境要求