初始提交:抖音视频批量采集流水线

App 端免签名接口(设备注册 + detail + CDN 直链),一体化流水线
下载→抽音→传COS→记录→删本地,AI 作品四档判定,四份文档:
README(使用指南)、PROGRESS(批次进度)、RE(逆向全过程)、AI(判定规则)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-09-29 16:31:10 +08:00
commit 2bb83f3685
39 changed files with 298874 additions and 0 deletions

85
douyin/urls.py Normal file
View File

@@ -0,0 +1,85 @@
"""链接解析:把用户随手粘的东西还原成 aweme_id。
支持的输入形态:
7xxxxxxxxxxxxxxxxxx 裸 id
https://v.douyin.com/xxxxxxx/ 分享短链(需要一次网络跳转)
4.53 复制打开抖音... https://v.douyin.com/xxx/ ... 整段分享口令
https://www.douyin.com/video/7xxxxxx
https://www.douyin.com/note/7xxxxxx 图文
https://www.douyin.com/?modal_id=7xxxxxx
https://www.iesdouyin.com/share/video/7xxxxxx/
"""
from __future__ import annotations
import re
from typing import Optional
import requests
# 从一段中文分享口令里把 url 抠出来
URL_RE = re.compile(r"https?://[-\w./?=&%#:]+")
SHORT_HOSTS = ("v.douyin.com", "v.iesdouyin.com")
# 按优先级尝试的 id 提取规则
ID_PATTERNS = (
re.compile(r"/(?:video|note|slides|share/video|share/note)/(\d{15,25})"),
re.compile(r"[?&](?:modal_id|aweme_id|item_ids|vid)=(\d{15,25})"),
)
BARE_ID_RE = re.compile(r"^\d{15,25}$")
class ParseError(ValueError):
"""输入里找不到可用的 aweme_id。"""
def _first_url(text: str) -> Optional[str]:
m = URL_RE.search(text)
return m.group(0) if m else None
def _extract_id(url: str) -> Optional[str]:
for pat in ID_PATTERNS:
m = pat.search(url)
if m:
return m.group(1)
return None
def resolve_short_link(url: str, session: requests.Session, timeout: float = 15.0) -> str:
"""跟随 v.douyin.com 短链跳转,返回落地长链。"""
resp = session.get(url, timeout=timeout, allow_redirects=True)
return resp.url
def extract_aweme_id(raw: str, session: Optional[requests.Session] = None) -> str:
"""从任意输入中解析出 aweme_id,必要时联网还原短链。"""
raw = raw.strip()
if BARE_ID_RE.match(raw):
return raw
url = _first_url(raw)
if not url:
raise ParseError(f"输入里没找到链接也不是纯数字 id: {raw[:80]!r}")
aid = _extract_id(url)
if aid:
return aid
if any(h in url for h in SHORT_HOSTS):
if session is None:
session = requests.Session()
session.headers["User-Agent"] = (
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) "
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 "
"Mobile/15E148 Safari/604.1"
)
final = resolve_short_link(url, session)
aid = _extract_id(final)
if aid:
return aid
raise ParseError(f"短链 {url} 跳转到 {final},但里面没有 aweme_id")
raise ParseError(f"无法从 {url} 中解析出 aweme_id")