feat(video-analysis): 抖音免浏览器解析链路 + 快手支持 + 小红书加固 + 发送防重复
- 抖音(2026-10-13):删除 SSR + playwright 旧链路(douyin_ssr.py 移除, douyin_api.py 精简为下载工具),新增 douyin_web.py(x-tt-argus 网关头 + web detail 接口 + 最高码率梯/多 CDN 回退下载)与 douyin_sign.py (纯 Python a_bogus 签名,vendor 自 f2(Apache-2.0),依赖 gmssl SM3); 实测 10/10 成功率、单作品 <1s(旧浏览器链路 5-15s 且随机撞验证码) - 快手(2026-10-08):kuaishou_content.py 分享页 INIT_STATE 静态解析(无登录态), 清晰度梯最佳档 + 图集 URL 组装,入口/策略/Web 面板同步接入 - 小红书:按链接来源定国际/国内站优先序、视频 backupUrls 逐候选回退、 图片 urlDefault→infoList WB_DFT→url 三档回退 - 长视频防重复发送(2026-10-13):媒体发送带 per-call _timeout(默认 300s), 超时=结果未知不再降级重试;auto/active 两条 handler 互斥 - Web 解析封面抽帧 ffmpeg 加 CREATE_NO_WINDOW(pythonw 下不再弹 cmd 黑窗) - 依赖:+gmssl;测试:新增 test_douyin_web / test_kuaishou_parse / test_video_cleanup, 扩充 test_video_policy / test_video_sender_link / test_video_group_file / test_video_media_naming Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
a31aab00e8
commit
a789a44f5d
25 files changed
+3536
-895
No files matched your search
@@ -15,14 +15,15 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from nonebot import get_adapter
|
||||
from nonebot.adapters.onebot.v11 import Adapter
|
||||
|
||||
from hexi.web_hub.web_auth import require_admin
|
||||
from hexi.web_hub.web_auth import get_current_user, require_admin
|
||||
|
||||
from .cleanup import cleanup_config, run_stats, submit_clean
|
||||
from .policy import PLANS, PLATFORMS, STORE, Policy
|
||||
from .services.web_jobs import JOBS, extract_urls
|
||||
|
||||
@@ -167,6 +168,50 @@ def build_admin_app() -> FastAPI | None:
|
||||
removed = JOBS.clear_finished()
|
||||
return _ok({"removed": removed}, f"已清理 {removed} 条任务")
|
||||
|
||||
# ── temp 缓存:占用统计 + 手动清理 ──────────────────────
|
||||
# 与「清理temp / temp统计」命令、每日定时任务同一套函数(cleanup.py),
|
||||
# 不重写清理逻辑;文件系统操作丢线程池,别卡住事件循环。
|
||||
|
||||
@app.get("/temp/stats", response_class=JSONResponse, dependencies=[auth])
|
||||
async def temp_stats_api():
|
||||
"""temp 目录占用(文件数/总大小/目录数)+ 当前自动清理配置。"""
|
||||
st = await run_stats()
|
||||
st["mode"] = cleanup_config.video_analysis_temp_cleanup_mode
|
||||
st["max_age_days"] = cleanup_config.video_analysis_temp_max_age_days
|
||||
st["hour"] = cleanup_config.video_analysis_temp_cleanup_hour
|
||||
return _ok(st)
|
||||
|
||||
@app.post("/temp/cleanup", response_class=JSONResponse, dependencies=[auth])
|
||||
async def temp_cleanup_api(data: dict, user: dict = Depends(get_current_user)):
|
||||
"""手动清理 temp:**提交到任务槽后立即返回**,进度走 /hub/api/tasks/stream。
|
||||
|
||||
`days=0` 表示全部清空,不传则用配置的保留天数。清理本身是几十秒级的阻塞
|
||||
任务,放请求里会把页面交互一起卡住;同槽已有任务时返回它并带 `reused=true`
|
||||
(前端据此提示"已在运行",服务端这层才是防连点的真正保证)。
|
||||
"""
|
||||
raw = data.get("days")
|
||||
if raw is None or str(raw).strip() == "":
|
||||
days: int | None = None # 用配置的保留天数
|
||||
shown = cleanup_config.video_analysis_temp_max_age_days
|
||||
else:
|
||||
try:
|
||||
days = max(0, int(raw))
|
||||
except (TypeError, ValueError):
|
||||
return _fail("天数参数不合法")
|
||||
shown = days
|
||||
|
||||
title = "清理 temp(全部)" if shown == 0 else f"清理 temp(保留 {shown} 天)"
|
||||
task, reused = submit_clean(
|
||||
days,
|
||||
title=title,
|
||||
trigger="web",
|
||||
actor=str((user or {}).get("username") or ""),
|
||||
)
|
||||
return _ok(
|
||||
{"task": task.to_dict(), "reused": reused},
|
||||
"已有清理任务在跑" if reused else "清理已开始",
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user