问题:snapshot_last_own_message 用 [class*='message']/[class*='bubble'] 等宽泛 选择器扫全页并靠位置猜自己消息,抓到的是整个聊天区容器节点。导致 confirm_message_sent 永远比不上单条气泡文本,100% 误报失败,每条消息 纯浪费 ~80 秒空转 + 进入失败队列反复重试。 改动: 1. snapshot_last_own_message 完全重写——直接用抖音 DOM 结构: - 找所有 box-item- 行 - 从底部往上扫 time- 时间分隔符,碰到 昨天/星期/2026- 就标记今日边界 - 今日区域内从底部找第一个 is-me 行,从 <pre> 取文本 2. 新增 count_today_own_message_matches——只数今日 is-me 气泡里精确匹配 指定文本的条数。用于发送前后增量比较,挡住手机并发发消息把最后一条 顶掉导致主路径漏判的场景。 3. confirm_message_sent 加 count 兜底——主路径(最后一条自己消息==本次 发送文本)未命中时,回退到 count 增量判断;超时前再兜底一次。 4. 保留 _detect_send_failure_indicator——轮询中一旦发现红色感叹号/ 重试按钮/发送失败文字立即判失败,不写 sentAt。 原文件备份:tasks.py.bak-20260624-snapshot-fix(容器内)
DouYinSparkFlow - 核心应用
抖音多账号火花自动维护系统 - 核心源码模块
这是 DouYin SparkFlow 的核心应用源码目录,包含所有业务逻辑、Web 界面和自动化任务实现。
📁 目录结构
core/ - 核心功能模块
核心业务逻辑实现,包括浏览器自动化、消息发送、好友管理等。
| 文件 | 说明 | 大小 |
|---|---|---|
browser.py |
浏览器控制和页面操作 | 3.4 KB |
friends.py |
好友列表管理和刷新逻辑 | 5.2 KB |
login.py |
登录流程控制 | 2.8 KB |
msg_builder.py |
消息内容构建(一言、祝福等) | 4.5 KB |
protocol_dispatch.py |
协议分发和路由 | 9.7 KB |
protocol_sender.mjs |
消息发送协议(Node.js 脚本) | 21 KB |
tasks.py |
任务调度核心(定时任务、状态管理) | 83 KB |
webui/ - Web 管理界面
基于 FastAPI 的 Web 管理控制台,提供可视化操作界面。
后端模块
| 文件 | 说明 |
|---|---|
app.py |
FastAPI 主应用,路由定义 |
auth.py |
用户认证和会话管理 |
login_sessions.py |
登录会话生命周期管理 |
ops.py |
操作接口(启动/停止任务、刷新好友等) |
前端资源
webui/
├── static/ # 静态资源
│ ├── app.css # 主题样式(亮色/暗色)
│ ├── app.js # 主题切换脚本
│ ├── styles.css # 基础样式
│ └── multiPagePlugins/ # 浏览器扩展插件
└── templates/ # HTML 模板
├── base.html # 基础布局模板
├── dashboard.html # 仪表盘(主界面)
├── login.html # 登录页
├── login_workspace.html # 登录工作区
├── accounts.html # 账号管理
├── send_console.html # 发送控制台
├── logs.html # 日志查看
└── settings.html # 系统设置
utils/ - 工具模块
通用辅助功能和配置管理。
| 文件 | 说明 |
|---|---|
config.py |
配置文件加载和管理 |
logger.py |
日志系统配置 |
hitokoto.py |
一言 API 接口封装 |
github_action_config.py |
GitHub Actions 配置生成 |
scripts/ - 辅助脚本
| 文件 | 说明 |
|---|---|
cron_runner.py |
Cron 任务运行器 |
start_login_desktop.sh |
登录桌面启动脚本 |
docs/ - 文档和资源
| 文件/目录 | 说明 |
|---|---|
usage.md |
详细使用教程(含截图) |
images/ |
界面截图和示意图 |
🚀 运行方式
开发环境运行
1. 安装依赖
# 核心依赖
pip install -r requirements.txt
# Web UI 依赖
pip install -r requirements-web.txt
# 安装 Playwright 浏览器
playwright install chromium
2. 启动方式
Web 管理模式(推荐):
python main.py --web
# 访问 http://localhost:8787
命令行模式:
python main.py
# 直接运行任务调度
登录桌面服务:
python login_desktop_server.py
# 启动登录桌面 API(用于扫码登录)
Docker 容器运行
参考根目录的 docker-compose.yml 配置:
# 构建镜像
docker build -f Dockerfile.server -t douyin-sparkflow:local .
# 运行容器
docker run -d \
-p 8787:8787 \
-v $(pwd):/app \
douyin-sparkflow:local
⚙️ 配置文件
config.json - 应用配置
主配置文件,控制任务行为和系统设置。
{
"send_window_start": "09:00",
"send_window_end": "22:00",
"send_interval_min": 300,
"message_template": "hitokoto",
"enable_send_confirm": true,
"friend_refresh_interval": 3600,
"browser_headless": false,
"browser_timeout": 30000,
"max_retry_count": 3,
"cooldown_on_failure": 600
}
配置项说明:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
send_window_start |
string | "09:00" | 发送窗口开始时间 |
send_window_end |
string | "22:00" | 发送窗口结束时间 |
send_interval_min |
int | 300 | 最小发送间隔(秒) |
message_template |
string | "hitokoto" | 消息模板类型 |
enable_send_confirm |
bool | true | 是否启用发送确认 |
friend_refresh_interval |
int | 3600 | 好友列表刷新间隔(秒) |
browser_headless |
bool | false | 浏览器无头模式 |
browser_timeout |
int | 30000 | 浏览器操作超时(毫秒) |
max_retry_count |
int | 3 | 失败重试次数 |
cooldown_on_failure |
int | 600 | 失败后冷却时间(秒) |
usersData.json - 用户数据
存储账号信息、好友列表、发送记录等运行时数据。
⚠️ 此文件包含敏感数据,不应提交到 Git 仓库
示例结构:
{
"accounts": [
{
"id": "user_123",
"nickname": "用户昵称",
"friends": [...],
"last_send_time": "2026-06-20T10:30:00",
"send_history": [...]
}
]
}
webui_settings.json - Web UI 设置
Web 管理界面的配置(管理员密码、端口等)。
⚠️ 此文件包含敏感数据,不应提交到 Git 仓库
🔌 API 接口
Web UI 提供以下 RESTful API 接口:
账号管理
GET /api/accounts- 获取账号列表POST /api/accounts/refresh- 刷新好友列表DELETE /api/accounts/{id}- 删除账号
任务控制
POST /api/tasks/start- 启动定时任务POST /api/tasks/stop- 停止定时任务GET /api/tasks/status- 获取任务状态
登录管理
GET /api/login/qrcode- 获取登录二维码GET /api/login/status- 检查登录状态POST /api/login/logout- 登出账号
消息发送
POST /api/send/manual- 手动发送消息GET /api/send/history- 获取发送历史
详细 API 文档请查看 webui/app.py 中的路由定义。
🔧 核心工作流程
1. 登录流程
用户扫码 → browser.py 打开登录页
→ login.py 生成二维码
→ 用户扫码确认
→ 保存登录态到 state/
→ 返回登录成功
2. 好友列表刷新
触发刷新 → friends.py 启动浏览器
→ 访问好友列表页面
→ 解析好友数据(昵称、火花状态等)
→ 保存到 usersData.json
→ 关闭浏览器
3. 消息发送流程
定时触发 → tasks.py 检查发送条件
→ 筛选需要发送的好友
→ msg_builder.py 构建消息内容
→ protocol_sender.mjs 发送消息
→ 等待发送确认
→ 记录发送历史
→ 更新下次发送时间
4. 任务调度逻辑
tasks.py 是核心调度器,负责:
- ⏰ 定时检查发送窗口
- 🔄 循环遍历所有账号
- 📊 统计发送成功/失败
- 🛡️ 失败保护(冷却机制)
- 📝 日志记录
🐛 调试和开发
日志系统
日志文件位于 logs/ 目录:
logs/
├── app.log # 应用主日志
├── webui.log # Web UI 日志
├── tasks.log # 任务调度日志
└── browser.log # 浏览器操作日志
查看实时日志:
tail -f logs/app.log
开发建议
- 修改模板文件:编辑
webui/templates/*.html,刷新浏览器即可看到效果(自动重载已启用) - 修改 Python 代码:需要重启服务才能生效
- 调试浏览器操作:设置
browser_headless: false可以看到浏览器窗口 - 测试消息发送:使用 Web UI 的"手动发送"功能,避免等待定时任务
常见问题
Q: 登录二维码不显示?
A: 检查 login_desktop_server.py 是否正常运行,端口 18090 是否被占用。
Q: 浏览器启动失败?
A: 确保已安装 Playwright:playwright install chromium
Q: 消息发送失败?
A: 检查网络连接,查看 logs/tasks.log 中的错误信息。
Q: Web UI 无法访问?
A: 检查端口 8787 是否被占用,防火墙是否允许该端口。
📦 依赖说明
requirements.txt - 核心依赖
playwright>=1.40.0 # 浏览器自动化
apscheduler>=3.10.0 # 任务调度
requirements-web.txt - Web 依赖
fastapi>=0.104.0 # Web 框架
uvicorn>=0.24.0 # ASGI 服务器
jinja2>=3.1.0 # 模板引擎
完整依赖列表请查看对应的 requirements*.txt 文件。
🔐 安全注意事项
敏感文件保护
以下文件绝对不要提交到 Git 仓库:
- ❌
usersData.json- 包含账号数据和好友信息 - ❌
webui_settings.json- 包含管理员密码 - ❌
.env- 包含环境变量和密钥 - ❌
state/- 包含浏览器登录态 - ❌
logs/- 可能包含敏感日志 - ❌
.im_sdk_cache/- IM SDK 缓存
已在 .gitignore 中配置忽略这些文件。
密码安全
- 修改
webui_settings.json中的默认管理员密码 - 不要在配置文件中明文存储密码
- 使用环境变量管理敏感配置
📚 相关文档
- 项目主 README - 整体介绍和快速开始
- 使用文档 - 详细使用教程
- 更新日志 - 版本更新历史
- Docker 部署 - 容器编排配置
🤝 贡献指南
欢迎提交代码改进和功能建议!
开发规范:
- Python 代码遵循 PEP 8 规范
- 提交前运行测试确保功能正常
- 添加必要的代码注释
- 更新相关文档
📄 许可证
MIT License - 详见 LICENSE 文件
返回 项目主页
Made with ❤️ by halfwaystudent