536 lines
16 KiB
Markdown
536 lines
16 KiB
Markdown
# Day 7: 社交媒体发布功能完善
|
||
|
||
**日期**: 2026-01-21
|
||
**目标**: 完成社交媒体发布模块 (80% → 100%)
|
||
|
||
---
|
||
|
||
## 📋 任务概览
|
||
|
||
| 任务 | 状态 |
|
||
|------|------|
|
||
| SuperIPAgent 架构分析 | ✅ 完成 |
|
||
| 优化技术方案制定 | ✅ 完成 |
|
||
| B站上传功能实现 | ⏳ 计划中 |
|
||
| 定时发布功能 | ⏳ 计划中 |
|
||
| 端到端测试 | ⏳ 待进行 |
|
||
|
||
---
|
||
|
||
## 🔍 架构优化分析
|
||
|
||
### SuperIPAgent social-auto-upload 优势
|
||
|
||
通过分析 `Temp\SuperIPAgent\social-auto-upload`,发现以下**更优设计**:
|
||
|
||
| 对比项 | 原方案 | 优化方案 ✅ |
|
||
|--------|--------|------------|
|
||
| **调度方式** | APScheduler (需额外依赖) | **平台 API 原生定时** |
|
||
| **B站上传** | Playwright 自动化 (不稳定) | **biliup 库 (官方)** |
|
||
| **架构** | 单文件服务 | **模块化 uploader/** |
|
||
| **Cookie** | 手动维护 | **自动扫码 + 持久化** |
|
||
|
||
### 核心优势
|
||
|
||
1. **更简单**: 无需 APScheduler,直接传时间给平台
|
||
2. **更稳定**: biliup 库比 Playwright 选择器可靠
|
||
3. **更易维护**: 每个平台独立 uploader 类
|
||
|
||
---
|
||
|
||
## 📝 技术方案变更
|
||
|
||
### 新增依赖
|
||
```bash
|
||
pip install biliup>=0.4.0
|
||
pip install playwright-stealth # 可选,反检测
|
||
```
|
||
|
||
### 移除依赖
|
||
```diff
|
||
- apscheduler==3.10.4 # 不再需要
|
||
```
|
||
|
||
### 文件结构
|
||
```
|
||
backend/app/services/
|
||
├── publish_service.py # 简化,统一接口
|
||
+ ├── uploader/ # 新增: 平台上传器
|
||
+ │ ├── base_uploader.py # 基类
|
||
+ │ ├── bilibili_uploader.py # B站 (biliup)
|
||
+ │ └── douyin_uploader.py # 抖音 (Playwright)
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 关键代码模式
|
||
|
||
### 统一接口
|
||
```python
|
||
# publish_service.py
|
||
async def publish(video_path, platform, title, tags, publish_time=None):
|
||
if platform == "bilibili":
|
||
uploader = BilibiliUploader(...)
|
||
result = await uploader.main()
|
||
return result
|
||
```
|
||
|
||
### B站上传 (biliup 库)
|
||
```python
|
||
from biliup.plugins.bili_webup import BiliBili
|
||
|
||
with BiliBili(data) as bili:
|
||
bili.login_by_cookies(cookie_data)
|
||
video_part = bili.upload_file(video_path)
|
||
ret = bili.submit() # 平台处理定时
|
||
```
|
||
|
||
---
|
||
|
||
## 📅 开发计划
|
||
|
||
### 下午 (11:56 - 14:30)
|
||
- ✅ 添加 `biliup>=0.4.0` 到 `requirements.txt`
|
||
- ✅ 创建 `uploader/` 模块结构
|
||
- ✅ 实现 `base_uploader.py` 基类
|
||
- ✅ 实现 `bilibili_uploader.py` (biliup 库)
|
||
- ✅ 实现 `douyin_uploader.py` (Playwright)
|
||
- ✅ 实现 `xiaohongshu_uploader.py` (Playwright)
|
||
- ✅ 实现 `cookie_utils.py` (自动 Cookie 生成)
|
||
- ✅ 简化 `publish_service.py` (集成所有 uploader)
|
||
- ✅ 前端添加定时发布时间选择器
|
||
|
||
---
|
||
|
||
## 🎉 实施成果
|
||
|
||
### 后端改动
|
||
|
||
1. **新增文件**:
|
||
- `backend/app/services/uploader/__init__.py`
|
||
- `backend/app/services/uploader/base_uploader.py` (87行)
|
||
- `backend/app/services/uploader/bilibili_uploader.py` (135行) - biliup 库
|
||
- `backend/app/services/uploader/douyin_uploader.py` (173行) - Playwright
|
||
- `backend/app/services/uploader/xiaohongshu_uploader.py` (166行) - Playwright
|
||
- `backend/app/services/uploader/cookie_utils.py` (113行) - Cookie 自动生成
|
||
- `backend/app/services/uploader/stealth.min.js` - 反检测脚本
|
||
|
||
2. **修改文件**:
|
||
- `backend/requirements.txt`: 添加 `biliup>=0.4.0`
|
||
- `backend/app/services/publish_service.py`: 集成所有 uploader (170行)
|
||
|
||
3. **核心特性**:
|
||
- ✅ **自动 Cookie 生成** (Playwright QR 扫码登录)
|
||
- ✅ **B站**: 使用 `biliup` 库 (官方稳定)
|
||
- ✅ **抖音**: Playwright 自动化
|
||
- ✅ **小红书**: Playwright 自动化
|
||
- ✅ 支持定时发布 (所有平台)
|
||
- ✅ stealth.js 反检测 (防止被识别为机器人)
|
||
- ✅ 模块化架构 (易于扩展)
|
||
|
||
### 前端改动
|
||
|
||
1. **修改文件**:
|
||
- `frontend/src/app/publish/page.tsx`: 添加定时发布 UI
|
||
|
||
2. **新增功能**:
|
||
- ✅ 立即发布/定时发布切换按钮
|
||
- ✅ `datetime-local` 时间选择器
|
||
- ✅ 自动传递 ISO 格式时间到后端
|
||
- ✅ 一键登录按钮 (自动弹出浏览器扫码)
|
||
|
||
---
|
||
|
||
## 🚀 部署步骤
|
||
|
||
### 1. 安装依赖
|
||
|
||
```bash
|
||
cd backend
|
||
pip install biliup>=0.4.0
|
||
|
||
# 或重新安装所有依赖
|
||
pip install -r requirements.txt
|
||
|
||
# 安装 Playwright 浏览器
|
||
playwright install chromium
|
||
```
|
||
|
||
### 2. 客户登录平台 (**极简3步**)
|
||
|
||
**操作流程**:
|
||
|
||
1. **拖拽书签**(仅首次)
|
||
- 点击前端"🔐 扫码登录"
|
||
- 将页面上的"保存登录"按钮拖到浏览器书签栏
|
||
|
||
2. **扫码登录**
|
||
- 点击"打开登录页"
|
||
- 扫码登录B站/抖音/小红书
|
||
|
||
3. **点击书签**
|
||
- 登录成功后,点击书签栏的"保存登录"书签
|
||
- 自动完成!
|
||
|
||
**客户实际操作**: 拖拽1次(首次)+ 扫码1次 + 点击书签1次 = **仅3步**!
|
||
|
||
**下次登录**: 只需扫码 + 点击书签 = **2步**!
|
||
|
||
### 3. 重启后端服务
|
||
|
||
```bash
|
||
cd backend
|
||
uvicorn app.main:app --host 0.0.0.0 --port 8006 --reload
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ Day 7 完成总结
|
||
|
||
### 核心成果
|
||
|
||
1. **QR码自动登录** ⭐⭐⭐⭐⭐
|
||
- Playwright headless模式提取二维码
|
||
- 前端弹窗显示二维码
|
||
- 后端自动监控登录状态
|
||
- Cookie自动保存
|
||
|
||
2. **多平台上传器架构**
|
||
- B站: biliup官方库
|
||
- 抖音: Playwright自动化
|
||
- 小红书: Playwright自动化
|
||
- stealth.js反检测
|
||
|
||
3. **定时发布功能**
|
||
- 前端datetime-local时间选择
|
||
- 平台API原生调度
|
||
- 无需APScheduler
|
||
|
||
4. **用户体验优化**
|
||
- 首页添加发布入口
|
||
- 视频生成后直接发布按钮
|
||
- 一键扫码登录(仅扫码)
|
||
|
||
**后端** (13个):
|
||
- `backend/requirements.txt`
|
||
- `backend/app/main.py`
|
||
- `backend/app/services/publish_service.py`
|
||
- `backend/app/services/qr_login_service.py` (新建)
|
||
- `backend/app/services/uploader/__init__.py` (新建)
|
||
- `backend/app/services/uploader/base_uploader.py` (新建)
|
||
- `backend/app/services/uploader/bilibili_uploader.py` (新建)
|
||
- `backend/app/services/uploader/douyin_uploader.py` (新建)
|
||
- `backend/app/services/uploader/xiaohongshu_uploader.py` (新建)
|
||
- `backend/app/services/uploader/cookie_utils.py` (新建)
|
||
- `backend/app/services/uploader/stealth.min.js` (新建)
|
||
- `backend/app/api/publish.py`
|
||
- `backend/app/api/login_helper.py` (新建)
|
||
|
||
**前端** (2个):
|
||
- `frontend/src/app/page.tsx`
|
||
- `frontend/src/app/publish/page.tsx`
|
||
|
||
---
|
||
|
||
## 📝 TODO (Day 8优化项)
|
||
|
||
### 用户体验优化
|
||
- [ ] **文件名保留**: 上传视频后保留原始文件名
|
||
- [ ] **视频持久化**: 刷新页面后保留生成的视频
|
||
|
||
### 功能增强
|
||
- [ ] 抖音/小红书实际测试
|
||
- [ ] 批量发布功能
|
||
- [ ] 发布历史记录
|
||
|
||
---
|
||
|
||
## 📊 测试清单
|
||
- [ ] Playwright 浏览器安装成功
|
||
- [ ] B站 Cookie 自动生成测试
|
||
- [ ] 抖音 Cookie 自动生成测试
|
||
- [ ] 小红书 Cookie 自动生成测试
|
||
- [ ] 测试 B站立即发布功能
|
||
- [ ] 测试抖音立即发布功能
|
||
- [ ] 测试小红书立即发布功能
|
||
- [ ] 测试定时发布功能
|
||
|
||
---
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
1. **B站 Cookie 获取**
|
||
- 参考 `social-auto-upload/examples/get_bilibili_cookie.py`
|
||
- 或手动登录后导出 JSON
|
||
|
||
2. **定时发布原理**
|
||
- 前端收集时间
|
||
- 后端传给平台 API
|
||
- **平台自行处理调度** (无需 APScheduler)
|
||
|
||
3. **biliup 优势**
|
||
- 官方 API 支持
|
||
- 社区活跃维护
|
||
- 比 Playwright 更稳定
|
||
|
||
---
|
||
|
||
## 🔗 相关文档
|
||
|
||
- [SuperIPAgent social-auto-upload](file:///d:/CodingProjects/Antigravity/Temp/SuperIPAgent/social-auto-upload)
|
||
- [优化实施计划](implementation_plan.md)
|
||
- [Task Checklist](task.md)
|
||
|
||
---
|
||
|
||
## 🎨 UI 一致性优化 (16:00 - 16:35)
|
||
|
||
**问题**:导航栏不一致、页面偏移
|
||
- 首页 Logo 无法点击,发布页可点击
|
||
- 发布页多余标题"📤 社交媒体发布"
|
||
- 首页因滚动条向左偏移 15px
|
||
|
||
**修复**:
|
||
- `frontend/src/app/page.tsx` - Logo 改为 `<Link>` 组件
|
||
- `frontend/src/app/publish/page.tsx` - 删除页面标题和顶端 padding
|
||
- `frontend/src/app/globals.css` - 隐藏滚动条(保留滚动功能)
|
||
|
||
**状态**:✅ 两页面完全对齐
|
||
|
||
---
|
||
|
||
## 🔍 QR 登录问题诊断 (16:05)
|
||
|
||
**问题**:所有平台 QR 登录超时 `Page.wait_for_selector: Timeout 10000ms exceeded`
|
||
|
||
**原因**:
|
||
1. Playwright headless 模式被检测
|
||
2. 缺少 stealth.js 反检测
|
||
3. CSS 选择器可能过时
|
||
|
||
**状态**:✅ 已修复
|
||
|
||
---
|
||
|
||
## 🔧 QR 登录功能修复 (16:35 - 16:45)
|
||
|
||
### 实施方案
|
||
|
||
#### 1. 启用 Stealth 模式
|
||
```python
|
||
# 避免headless检测
|
||
browser = await playwright.chromium.launch(
|
||
headless=True,
|
||
args=[
|
||
'--disable-blink-features=AutomationControlled',
|
||
'--no-sandbox',
|
||
'--disable-dev-shm-usage'
|
||
]
|
||
)
|
||
```
|
||
|
||
#### 2. 配置真实浏览器特征
|
||
```python
|
||
context = await browser.new_context(
|
||
viewport={'width': 1920, 'height': 1080},
|
||
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
|
||
locale='zh-CN',
|
||
timezone_id='Asia/Shanghai'
|
||
)
|
||
```
|
||
|
||
#### 3. 注入 stealth.js 脚本
|
||
```python
|
||
stealth_path = Path(__file__).parent / 'uploader' / 'stealth.min.js'
|
||
if stealth_path.exists():
|
||
await page.add_init_script(path=str(stealth_path))
|
||
```
|
||
|
||
#### 4. 多选择器 Fallback 策略
|
||
```python
|
||
"bilibili": {
|
||
"qr_selectors": [
|
||
".qrcode-img img",
|
||
"canvas.qrcode-img",
|
||
"img[alt*='二维码']",
|
||
".login-scan-box img",
|
||
"#qrcode-img"
|
||
]
|
||
}
|
||
# Douyin: 4个选择器, Xiaohongshu: 4个选择器
|
||
```
|
||
|
||
#### 5. 增加等待时间
|
||
- 页面加载:3s → 5s + `wait_until='networkidle'`
|
||
- 选择器超时:10s → 30s
|
||
|
||
#### 6. 调试功能
|
||
```python
|
||
# 保存调试截图到 backend/debug_screenshots/
|
||
if not qr_element:
|
||
screenshot_path = debug_dir / f"{platform}_debug.png"
|
||
await page.screenshot(path=str(screenshot_path))
|
||
```
|
||
|
||
### 修改文件
|
||
|
||
**后端** (1个):
|
||
- `backend/app/services/qr_login_service.py` - 全面重构QR登录逻辑
|
||
|
||
### 结果
|
||
|
||
- ✅ 添加反检测措施(stealth模式、真实UA)
|
||
- ✅ 多选择器fallback(每平台4-5个)
|
||
- ✅ 等待时间优化(5s + 30s)
|
||
- ✅ 自动保存调试截图
|
||
- 🔄 待服务器测试验证
|
||
|
||
---
|
||
|
||
## 📋 文档规则优化 (16:42 - 17:10)
|
||
|
||
**问题**:DOC_RULES需要优化,避免误删历史内容、规范工具使用、防止任务清单遗漏
|
||
|
||
**优化内容(最终版)**:
|
||
|
||
1. **智能修改判断标准**
|
||
- 场景1:错误修正 → 直接替换/删除
|
||
- 场景2:方案改进 → 保留+追加(V1/V2)
|
||
- 场景3:同一天多次修改 → 合并为最终版本
|
||
|
||
2. **工具使用规范** ⭐
|
||
- ✅ 必须使用 `replace_file_content`
|
||
- ❌ 禁止命令行工具(避免编码错误)
|
||
|
||
3. **task_complete 完整性保障** (新增)
|
||
- ✅ 引入 "完整性检查清单" (4大板块逐项检查)
|
||
- ✅ 引入记忆口诀:"头尾时间要对齐,任务规划两手抓,里程碑上别落下"
|
||
|
||
4. **结构优化**
|
||
- 合并冗余章节
|
||
- 移除无关项目组件
|
||
|
||
**修改文件**:
|
||
- `Docs/DOC_RULES.md` - 包含检查清单的最终完善版
|
||
|
||
---
|
||
|
||
## ⚡ QR 登录性能与显示优化 (17:30)
|
||
|
||
**问题**:
|
||
1. **速度慢**: 顺序等待每个选择器 (30s timeout × N),导致加载极慢
|
||
2. **B站显示错乱**: Fallback 触发全页截图,而不是二维码区域
|
||
|
||
**优化方案**:
|
||
1. **并行等待 (Performance)**:
|
||
- 使用 `wait_for_selector("s1, s2, s3")` 联合选择器
|
||
- Playwright 自动等待任意一个出现 (即时响应,不再单纯 sleep)
|
||
- 超时时间从 30s 单次改为 15s 总计
|
||
|
||
2. **选择器增强 (Accuracy)**:
|
||
- 由于 B站登录页改版,旧选择器失效
|
||
- 新增 `div[class*='qrcode'] canvas` 和 `div[class*='qrcode'] img`
|
||
|
||
**修改文件**:
|
||
- `backend/app/services/qr_login_service.py`
|
||
|
||
---
|
||
|
||
## ⚡ QR 登录最终坚固化 (17:45)
|
||
|
||
**问题**:
|
||
- 并行等待虽然消除了顺序延迟,但 **CSS 选择器仍然无法匹配** (Timeout 15000ms)
|
||
- 截图显示二维码可见,但 Playwright 认为不可见或未找到(可能涉及动态类名或 DOM 结构变化)
|
||
|
||
**解决方案 (三重保障)**:
|
||
1. **策略 1**: CSS 联合选择器 (超时缩短为 5s,快速试错)
|
||
2. **策略 2 (新)**: **文本锚点定位**
|
||
- 不不再依赖脆弱的 CSS 类名
|
||
- 直接搜索屏幕上的 "扫码登录" 文字
|
||
- 智能查找文字附近的 `<canvas>` 或 `<img>`
|
||
3. **策略 3 (调试)**: **HTML 源码导出**
|
||
- 如果都失败,除了截图外,自动保存 `bilibili_debug.html`
|
||
- 彻底分析页面结构的"核武器"
|
||
|
||
**修改文件**:
|
||
- `backend/app/services/qr_login_service.py` (v3 最终版)
|
||
|
||
---
|
||
|
||
## ⚡ QR 登录终极修复 (17:55)
|
||
|
||
**致命问题**:
|
||
1. **监控闪退**: 后端使用 `async with async_playwright()`,导致函数返回时浏览器自动关闭,后台监控任务 (`_monitor_login_status`) 操作已关闭的页面报错 `TargetClosedError`。
|
||
2. **仍有延迟**: 之前的策略虽然改进,但串行等待 CSS 超时 (5s) 仍不可避免。
|
||
|
||
**解决方案**:
|
||
1. **生命周期重构 (Backend)**:
|
||
- 移除上下文管理器,改为 `self.playwright.start()` 手动启动
|
||
- 浏览器实例持久化到类属性 (`self.browser`)
|
||
- 仅在监控任务完成或超时后,在 `finally` 块中手动清理资源 (`_cleanup`)
|
||
|
||
2. **真·并行策略**:
|
||
- 使用 `asyncio.wait(tasks, return_when=FIRST_COMPLETED)`
|
||
- CSS选择器策略 和 文本定位策略 **同时运行**
|
||
- 谁先找到二维码,直接返回,取消另一个任务
|
||
- **延迟降至 0秒** (理论极限)
|
||
|
||
**修改文件**:
|
||
- `backend/app/services/qr_login_service.py` (v4 重构版)
|
||
|
||
---
|
||
|
||
## 🐛 并行逻辑 Bug 修复 (18:00)
|
||
|
||
**问题现象**:
|
||
- B站登录正常,但 **抖音秒挂** ("所有策略失败")。
|
||
- 原因:代码逻辑是 `asyncio.wait(FIRST_COMPLETED)`,如果其中一个策略(如文本策略)不适用该平台,它会立即返回 `None`。
|
||
- **BUG**: 代码收到 `None` 后,错误地以为任务结束,取消了还在运行的另一个策略(CSS策略)。
|
||
|
||
**修复方案**:
|
||
1. **修正并行逻辑**:
|
||
- 如果一个任务完成了但没找到结果 (Result is None),**不取消** 其他任务。
|
||
- 继续等待剩下的 `pending` 任务,直到找到结果或所有任务都跑完。
|
||
2. **扩展文本策略**:
|
||
- 将 **抖音 (Douyin)** 也加入到文本锚点定位的支持列表中。
|
||
- 增加关键词 `["扫码登录", "打开抖音", "抖音APP"]`。
|
||
|
||
**修改文件**:
|
||
- `backend/app/services/qr_login_service.py` (v5 修正版)
|
||
|
||
---
|
||
|
||
## ⚡ 抖音文本策略优化 (18:10)
|
||
|
||
**问题**:
|
||
- 抖音页面也是动态渲染的,"扫码登录" 文字出现有延迟。
|
||
- 之前的 `get_by_text(...).count()` 是瞬间检查,如果页面还没加载完文字,直接返回 0 (失败)。
|
||
- 结果:CSS 还在等,文本策略瞬间报空,导致最终还是没找到。
|
||
|
||
**优化方案**:
|
||
1. **智能等待**: 对每个关键词 (如 "使用手机抖音扫码") 增加 `wait_for(timeout=2000)`,给页面一点加载时间。
|
||
2. **扩大搜索圈**: 找到文字后,向父级查找 **5层** (之前是3层),以适应抖音复杂的 DOM 结构。
|
||
3. **尺寸过滤**: 增加 `width > 100` 判断,防止误匹配到头像或小图标。
|
||
|
||
**修改文件**:
|
||
- `backend/app/services/qr_login_service.py` (v6 抖音增强版)
|
||
|
||
**状态**: ✅ 抖音策略已强化
|
||
|
||
|
||
|
||
---
|
||
|
||
## ✅ 验证结果 (18:15)
|
||
|
||
**用户反馈**:
|
||
- B站:成功获取 Cookie 并显示"已登录"状态。
|
||
- 抖音:成功获取 Cookie 并显示"已登录"状态。
|
||
- **结论**:
|
||
1. 并行策略 (`asyncio.wait`) 有效解决了等待延迟。
|
||
2. 文本锚点定位 (`get_by_text`) 有效解决了动态页面元素查找问题。
|
||
3. 生命周期重构 (`manual start/close`) 解决了后台任务闪退问题。
|
||
|
||
**下一步**:
|
||
- 进行实际视频发布测试。
|