11
This commit is contained in:
@@ -73,7 +73,11 @@ class DouyinBrowserManager {
|
||||
constructor() {
|
||||
this.browser = null;
|
||||
this.isInitializing = false;
|
||||
this.userDataPath = getRuntimeDataPath("browser-data", "douyin");
|
||||
// 下载链路使用独立临时 profile,避免与其他流程/遗留进程抢占同一目录锁。
|
||||
this.userDataPath = getRuntimeDataPath(
|
||||
"temp",
|
||||
`douyin-pipeline-${process.pid}-${Date.now()}`
|
||||
);
|
||||
}
|
||||
|
||||
static getInstance() {
|
||||
@@ -180,8 +184,10 @@ class DouyinBrowserManager {
|
||||
const page = await this.browser.newPage();
|
||||
await page.setUserAgent(DEFAULT_USER_AGENT);
|
||||
await page.evaluateOnNewDocument(STEALTH_INIT_SCRIPT);
|
||||
page.setDefaultNavigationTimeout(60000);
|
||||
page.setDefaultTimeout(60000);
|
||||
const pageTimeoutMs =
|
||||
Number(process.env.AICLIENT_DOUYIN_PAGE_TIMEOUT_MS) || 90_000;
|
||||
page.setDefaultNavigationTimeout(pageTimeoutMs);
|
||||
page.setDefaultTimeout(pageTimeoutMs);
|
||||
return page;
|
||||
}
|
||||
|
||||
@@ -192,6 +198,16 @@ class DouyinBrowserManager {
|
||||
this.browser = null;
|
||||
console.log("浏览器管理器已关闭");
|
||||
}
|
||||
if (
|
||||
this.userDataPath &&
|
||||
this.userDataPath.includes(`${path.sep}temp${path.sep}douyin-pipeline-`)
|
||||
) {
|
||||
try {
|
||||
fs.rmSync(this.userDataPath, { recursive: true, force: true });
|
||||
} catch {
|
||||
/* ignore temp dir cleanup errors */
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("关闭浏览器管理器失败:", error);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,16 @@ const { DouyinBrowserManager, getRuntimeDataPath } = require("./douyin_browser_m
|
||||
const DIRECT_VIDEO_PATTERN =
|
||||
/https?:\/\/[^\s"'<>]+?\.(mp4|mov|m4v|webm|avi|mkv)(\?[^\s"'<>]*)?/i;
|
||||
|
||||
/** 视频页导航超时(毫秒),可通过 AICLIENT_DOUYIN_PAGE_TIMEOUT_MS 覆盖 */
|
||||
const PAGE_NAV_TIMEOUT_MS =
|
||||
Number(process.env.AICLIENT_DOUYIN_PAGE_TIMEOUT_MS) || 60_000;
|
||||
/** 等待 aweme detail API 拦截的超时(毫秒) */
|
||||
const API_INTERCEPT_TIMEOUT_MS =
|
||||
Number(process.env.AICLIENT_DOUYIN_API_WAIT_MS) || 120_000;
|
||||
/** 打开视频页后额外等待,便于接口与播放器初始化 */
|
||||
const PAGE_SETTLE_MS =
|
||||
Number(process.env.AICLIENT_DOUYIN_PAGE_SETTLE_MS) || 5_000;
|
||||
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
class DouyinVideoDownloader {
|
||||
@@ -214,7 +224,7 @@ class DouyinVideoDownloader {
|
||||
console.log("API 拦截超时,将尝试其他方法");
|
||||
resolve(null);
|
||||
}
|
||||
}, 30000);
|
||||
}, API_INTERCEPT_TIMEOUT_MS);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -287,8 +297,9 @@ class DouyinVideoDownloader {
|
||||
try {
|
||||
await page.goto(directVideoUrl, {
|
||||
waitUntil: "domcontentloaded",
|
||||
timeout: 30000,
|
||||
timeout: PAGE_NAV_TIMEOUT_MS,
|
||||
});
|
||||
await sleep(PAGE_SETTLE_MS);
|
||||
const currentUrl = page.url();
|
||||
const isLoginPage =
|
||||
currentUrl.includes("/login") || currentUrl.includes("login?");
|
||||
@@ -297,8 +308,9 @@ class DouyinVideoDownloader {
|
||||
await this.ensureLoggedIn(page);
|
||||
await page.goto(directVideoUrl, {
|
||||
waitUntil: "domcontentloaded",
|
||||
timeout: 30000,
|
||||
timeout: PAGE_NAV_TIMEOUT_MS,
|
||||
});
|
||||
await sleep(PAGE_SETTLE_MS);
|
||||
if (page.url().includes("/login")) {
|
||||
return {
|
||||
success: false,
|
||||
@@ -405,9 +417,9 @@ class DouyinVideoDownloader {
|
||||
|
||||
await page.goto("https://www.douyin.com/", {
|
||||
waitUntil: "domcontentloaded",
|
||||
timeout: 30000,
|
||||
timeout: PAGE_NAV_TIMEOUT_MS,
|
||||
});
|
||||
await sleep(2000);
|
||||
await sleep(PAGE_SETTLE_MS);
|
||||
|
||||
const isLoggedIn = await page.evaluate(() => {
|
||||
const loginBtnSelectors = [
|
||||
|
||||
Reference in New Issue
Block a user