Files
ViGent2/Docs/DevLogs/Day7.md
Kevin Wong e226224119 更新
2026-02-08 19:54:11 +08:00

536 lines
16 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.
# 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`) 解决了后台任务闪退问题。
**下一步**:
- 进行实际视频发布测试。