Track bundled vendor runtime sources
Some checks failed
CI / main (push) Has been cancelled
CI / release-e2e (push) Has been cancelled

This commit is contained in:
2026-07-07 10:05:50 +08:00
parent fbe179ab53
commit 52636c91ae
2111 changed files with 1850012 additions and 14 deletions

View File

@@ -0,0 +1,233 @@
#!/bin/bash
# export_douyin_cookie.sh
# 导出已登录 Chrome 的抖音 cookie 到 douyin_{8位随机字符}.json
# 使用 curl 直接调用 Chrome DevTools HTTP API
set -e
# 解析参数
USERNAME=""
while [ $# -gt 0 ]; do
case "$1" in
--account)
USERNAME="$2"
shift 2
;;
*)
echo "用法: $0 --account <用户名>"
exit 1
;;
esac
done
if [ -z "$USERNAME" ]; then
echo "未指定用户名,将使用随机文件名"
fi
DEBUG_PORT=9222
echo "=========================================="
echo " 抖音 Cookie 导出工具"
echo "=========================================="
echo ""
# 依赖: curl, python3, websocket-client
echo "检查 Chrome remote debugging..."
RESPONSE=$(curl -s "http://localhost:${DEBUG_PORT}/json" 2>/dev/null) || true
if ! echo "$RESPONSE" | grep -q "webSocketDebuggerUrl"; then
echo "Chrome remote debugging 未运行"
echo "请先启动 Chrome: chromium --remote-debugging-port=9222 ..."
exit 1
fi
echo "Chrome remote debugging 已运行"
echo ""
echo "获取抖音 Cookie..."
USERNAME="$USERNAME" python3 << 'PYEOF'
import json
import os
import uuid
import sys
# Shell 把 USERNAME 作为环境变量传过来, Python 需要显式取
USERNAME = os.environ.get('USERNAME', '')
DEBUG_PORT = 9222
if USERNAME:
COOKIE_FILE = f"cookies/douyin_{USERNAME}.json"
else:
COOKIE_FILE = f"cookies/douyin_{uuid.uuid4().hex[:8]}.json"
def get_douyin_cookies():
import urllib.request
import websocket
# 获取页面列表
url = f"http://localhost:{DEBUG_PORT}/json"
with urllib.request.urlopen(url, timeout=10) as response:
pages = json.loads(response.read().decode())
# 查找抖音创作者页面
douyin_page = None
for page in pages:
page_url = page.get("url", "")
if "creator.douyin.com" in page_url:
douyin_page = page
break
if not douyin_page:
print("未找到抖音创作者平台页面")
print("请先在 Chrome 中打开并登录 https://creator.douyin.com")
return False
page_url = douyin_page["url"]
ws_url = douyin_page.get("webSocketDebuggerUrl", "")
print(f"找到页面: {page_url}")
# 连接到目标页面的 WebSocket
print(f"连接页面 WebSocket...")
ws = websocket.create_connection(ws_url, timeout=30)
# 获取所有 Cookie
ws.send(json.dumps({"id": 1, "method": "Network.getAllCookies"}))
response = json.loads(ws.recv())
cookies = response.get("result", {}).get("cookies", [])
# 过滤抖音相关的 cookie
douyin_cookies = [
c for c in cookies
if "douyin.com" in c.get("domain", "") or ".douyin.com" in c.get("domain", "")
]
print(f"获取到 {len(douyin_cookies)} 个抖音 Cookie")
if len(douyin_cookies) == 0:
print("未获取到任何抖音 Cookie可能未登录")
return False
# 获取 localStorage (origins)
print(f"获取 localStorage...")
local_storage_by_origin = {}
# 获取页面 frame 树
ws.send(json.dumps({"id": 2, "method": "Page.getResourceTree"}))
resp = json.loads(ws.recv())
frames = resp.get("result", {}).get("frameTree", {}).get("childFrames", [])
all_frames = [resp.get("result", {}).get("frameTree", {})] + frames
for frame in all_frames:
frame_url = frame.get("url", "")
frame_id = frame.get("id", "")
if "douyin.com" in frame_url or "bytedance.com" in frame_url:
# 执行 JavaScript 获取该 frame 的 localStorage
script = """
(function() {
var result = [];
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
result.push([key, localStorage.getItem(key)]);
}
return result;
})()
"""
ws.send(json.dumps({
"id": 3,
"method": "Runtime.evaluate",
"params": {"expression": script, "contextId": frame.get("id")}
}))
resp = json.loads(ws.recv())
result_eval = resp.get("result", {})
if result_eval.get("result", {}).get("type") == "array":
items = result_eval.get("result", {}).get("value", [])
if items:
origin = frame_url.rsplit("/", 2)[0] + "//" + frame_url.split("/")[2]
local_storage_by_origin[origin] = items
# 获取主文档的 localStorage
script_main = """
(function() {
var result = [];
try {
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
result.push([key, localStorage.getItem(key)]);
}
} catch(e) {}
return result;
})()
"""
ws.send(json.dumps({
"id": 4,
"method": "Runtime.evaluate",
"params": {"expression": script_main}
}))
resp = json.loads(ws.recv())
result_eval = resp.get("result", {})
if result_eval.get("result", {}).get("type") == "array":
items = result_eval.get("result", {}).get("value", [])
if items:
origin = page_url.rsplit("/", 2)[0] + "//" + page_url.split("/")[2]
local_storage_by_origin[origin] = items
ws.close()
# 构建 JSON
result = {
"cookies": [],
"origins": []
}
for c in douyin_cookies:
result["cookies"].append({
"name": c.get("name", ""),
"value": c.get("value", ""),
"domain": c.get("domain", ""),
"path": c.get("path", "/"),
"expires": c.get("expires", -1),
"httpOnly": c.get("httpOnly", False),
"secure": c.get("secure", True),
"sameSite": c.get("sameSite", "Lax")
})
# 添加 origins
for origin, items in local_storage_by_origin.items():
origin_entry = {
"origin": origin,
"localStorage": [{"name": name, "value": value} for name, value in items]
}
result["origins"].append(origin_entry)
# 保存
os.makedirs("cookies", exist_ok=True)
with open(COOKIE_FILE, "w", encoding="utf-8") as f:
json.dump(result, f, indent=2, ensure_ascii=False)
print(f"Cookie 已保存到: {COOKIE_FILE}")
print("")
# 打印关键 Cookie
key_cookies = ["sessionid", "uid_tt", "ssid", "ttwid"]
print("关键 Cookie:")
for c in douyin_cookies:
if c.get("name") in key_cookies:
val = c.get("value", "")
if len(val) > 30:
val = val[:30] + "..."
print(f" {c.get('name')}: {val}")
return True
if __name__ == "__main__":
if not get_douyin_cookies():
sys.exit(1)
PYEOF
echo ""
echo "=========================================="
echo " 完成!文件已导出为$COOKIE_FILE"
echo "=========================================="