fix: add A0 path using App Feed API for Douyin extraction
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 38s
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 42s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 18s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m59s
CI/CD Pipeline / Integration Tests (push) Successful in 5m10s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m35s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m21s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m30s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m25s
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 38s
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 42s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 18s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m38s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m59s
CI/CD Pipeline / Integration Tests (push) Successful in 5m10s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m35s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m21s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m30s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m25s
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
This commit is contained in:
@@ -356,7 +356,7 @@ def _fetch_ttwid():
|
||||
# 方式一:直接调 ttwid 注册接口
|
||||
try:
|
||||
with httpx.Client(timeout=8, follow_redirects=True, verify=False) as http:
|
||||
http.post(
|
||||
r = http.post(
|
||||
"https://ttwid.bytedance.com/ttwid/union/register/",
|
||||
json={
|
||||
"region": "cn",
|
||||
@@ -769,7 +769,7 @@ def _ytdlp_download_and_local_asr(page_url, temp_dir, cookiefile=None):
|
||||
cookie_files_to_try.append(cookiefile)
|
||||
|
||||
# 2. 合成 cookie 重试(复用 _ytdlp_extract 的 cookie 生成逻辑,8次重试)
|
||||
import time as _time
|
||||
import secrets, time as _time
|
||||
ttwid = _fetch_ttwid()
|
||||
for i in range(8):
|
||||
if i % 3 == 0:
|
||||
@@ -945,10 +945,9 @@ def _html_scrape_direct_url(page_url, timeout=15):
|
||||
@router.get("/douyin/__debug_diag")
|
||||
def douyin_diag():
|
||||
"""[Staging only] 容器内网络/yt-dlp诊断"""
|
||||
import tempfile as _tf
|
||||
import time as _t
|
||||
|
||||
import httpx as _httpx
|
||||
import time as _t
|
||||
import tempfile as _tf
|
||||
import yt_dlp as _ytdlp
|
||||
|
||||
results = {}
|
||||
@@ -1085,6 +1084,22 @@ def douyin_diag():
|
||||
|
||||
# 6. yt-dlp version
|
||||
results["ytdlp_version"] = _ytdlp.version.__version__
|
||||
|
||||
# 7. App Feed API 直连测试(路径 A0)
|
||||
try:
|
||||
from packages.douyin_parser import fetch_douyin_video_url as _feed_fetch
|
||||
ft0 = _t.time()
|
||||
f_url, f_desc = _feed_fetch(page_url, timeout=10, max_retries=2)
|
||||
results["feed_api"] = {
|
||||
"ok": bool(f_url),
|
||||
"desc": (f_desc or "")[:100],
|
||||
"url_domain": f_url.split("/")[2] if f_url and "/" in f_url else None,
|
||||
"url_prefix": f_url[:100] if f_url else None,
|
||||
"time": round(_t.time() - ft0, 2),
|
||||
}
|
||||
except Exception as e:
|
||||
results["feed_api"] = {"ok": False, "error": str(e)[:200]}
|
||||
|
||||
results["total_time"] = round(_t.time() - t0, 2)
|
||||
return results
|
||||
|
||||
@@ -1101,6 +1116,18 @@ def extract_from_douyin(
|
||||
page_url = _canonicalize_douyin_url(page_url)
|
||||
_dbg("page_url", page_url)
|
||||
|
||||
# 路径 A0:抖音 App Feed API 直连(零依赖、无需 cookies/签名、最稳定,优先级最高)
|
||||
# 使用 Android 客户端 aid=1128 接口,直接返回 aweme_list 含无水印直链
|
||||
direct_url = None
|
||||
feed_desc = ""
|
||||
try:
|
||||
from packages.douyin_parser import fetch_douyin_video_url as _feed_fetch
|
||||
direct_url, feed_desc = _feed_fetch(page_url, timeout=15, max_retries=3)
|
||||
if direct_url:
|
||||
logger.info("抖音 App Feed API 直连成功: url=%s play_len=%d", page_url, len(direct_url))
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.warning("抖音 App Feed API 异常: %s", exc)
|
||||
|
||||
text = ""
|
||||
duration = 0.0
|
||||
cookiefile = _resolve_cookies_file()
|
||||
@@ -1108,23 +1135,21 @@ def extract_from_douyin(
|
||||
|
||||
# 整体重试:外层最多 2 轮完整链路,应对第三方 API 瞬时限流/CDN 抖动
|
||||
max_rounds = 2
|
||||
direct_url = None
|
||||
meta_duration = 0.0
|
||||
for round_idx in range(max_rounds):
|
||||
direct_url = None
|
||||
meta_duration = 0.0
|
||||
|
||||
# 路径 A1:第三方解析 API(最稳定,apizero 付费时 99.88% 可用)
|
||||
logger.info("抖音解析第%d轮开始: url=%s", round_idx + 1, page_url)
|
||||
try:
|
||||
direct_url, meta_duration = _parser_extract_direct_url(page_url)
|
||||
if direct_url:
|
||||
logger.info(
|
||||
"第三方解析 API 成功(第%d轮): url_domain=%s",
|
||||
round_idx + 1, direct_url.split("/")[2] if "/" in direct_url else "?",
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.warning("第三方解析 API 异常(第%d轮): %s", round_idx + 1, exc)
|
||||
# 路径 A0 已成功则跳过 A1/A2/A3;否则走兜底链路
|
||||
if not direct_url:
|
||||
# 路径 A1:第三方解析 API(apizero 付费时可用)
|
||||
logger.info("抖音解析第%d轮开始: url=%s a0_ok=%s", round_idx + 1, page_url, bool(direct_url))
|
||||
try:
|
||||
direct_url, meta_duration = _parser_extract_direct_url(page_url)
|
||||
if direct_url:
|
||||
logger.info(
|
||||
"第三方解析 API 成功(第%d轮): url_domain=%s",
|
||||
round_idx + 1, direct_url.split("/")[2] if "/" in direct_url else "?",
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.warning("第三方解析 API 异常(第%d轮): %s", round_idx + 1, exc)
|
||||
|
||||
# 路径 A2:yt-dlp 拿直链(作为兜底,需要 cookie 概率性成功)
|
||||
if not direct_url:
|
||||
|
||||
Reference in New Issue
Block a user