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

16 KiB
Raw Blame History

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 类

📝 技术方案变更

新增依赖

pip install biliup>=0.4.0
pip install playwright-stealth  # 可选,反检测

移除依赖

- apscheduler==3.10.4  # 不再需要

文件结构

backend/app/services/
├── publish_service.py          # 简化,统一接口
+ ├── uploader/                 # 新增: 平台上传器
+ │   ├── base_uploader.py      # 基类
+ │   ├── bilibili_uploader.py  # B站 (biliup)
+ │   └── douyin_uploader.py    # 抖音 (Playwright)

🎯 关键代码模式

统一接口

# 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 库)

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.0requirements.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. 安装依赖

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. 重启后端服务

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 更稳定

🔗 相关文档


🎨 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 模式

# 避免headless检测
browser = await playwright.chromium.launch(
    headless=True,
    args=[
        '--disable-blink-features=AutomationControlled',
        '--no-sandbox',
        '--disable-dev-shm-usage'
    ]
)

2. 配置真实浏览器特征

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 脚本

stealth_path = Path(__file__).parent / 'uploader' / 'stealth.min.js'
if stealth_path.exists():
    await page.add_init_script(path=str(stealth_path))

4. 多选择器 Fallback 策略

"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. 调试功能

# 保存调试截图到 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'] canvasdiv[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) 解决了后台任务闪退问题。

下一步:

  • 进行实际视频发布测试。