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

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 11:07:56 +08:00

172 lines
6.8 KiB
Markdown
Raw 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.
# 抖音 Cookie 一键提取
扫码登录抖音后,自动导出 JSON 格式 Cookie。
## 原理
采用 **HTTP SSO 接口**(无需 Playwright / 浏览器):
1. 注册 `ttwid` 设备标识
2. 调用 `passport/web/get_qrcode``sso.douyin.com/get_qrcode` 获取二维码
3. 轮询 `check_qrconnect` 检测扫码状态
4. 确认后跟随 `redirect_url` 完成会话,导出 Cookie
> 若服务器 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 / SSO 接口,轻量、可部署 | **当前采用** |
| Playwright | 模拟真实浏览器,重、易受 UI 改版影响 | **已移除**(见上文) |
| 开放平台 OAuth | 需注册应用,返回 `access_token` 而非网页 Cookie | 不适用 |
| 读取本机浏览器 Cookie | 需用户事先在 Chrome 登录,非远程一键扫码 | 未采用 |
## 环境要求
- Python 3.9+
- Node.js 18+(仅构建前端时需要)
## 安装
```bash
pip install -r requirements.txt
cd frontend
npm install
npm run build
```
## 运行
```bash
py -3 app.py
```
访问:http://127.0.0.1:5001
## 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `PORT` | `5001` | 服务端口 |
| `LOGIN_TIMEOUT` | `600` | 登录超时(秒) |
| `QR_POLL_INTERVAL` | `2` | 建议前端轮询间隔 |
| `DOUYIN_AID` | `6383` | 抖音 Web 应用 ID |
| `DOUYIN_SERVICE` | `https://www.douyin.com` | SSO service 参数 |
## API
| 接口 | 说明 |
|------|------|
| `POST /api/start_qr` | 获取二维码(HTTP SSO |
| `GET /api/check_login` | 轮询扫码/登录状态 |
| `POST /api/reset` | 重置会话 |
| `GET /api/debug` | SSO 轮询调试信息 |
| `POST /api/test_proxy` | 测试代理 |
## 项目结构
```
app.py
backend/
sso/qr_login.py # HTTP 扫码登录核心
cookies.py # Cookie 检测
routes/ # API + SPA
frontend/ # Vue 3 前端
```