douyin-downloader 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/bin/dydl.d.ts +2 -0
- package/dist/bin/dydl.js +17 -0
- package/dist/bin/dydl.js.map +1 -0
- package/dist/src/cli/commands/check.d.ts +10 -0
- package/dist/src/cli/commands/check.js +102 -0
- package/dist/src/cli/commands/check.js.map +1 -0
- package/dist/src/cli/commands/info.d.ts +10 -0
- package/dist/src/cli/commands/info.js +106 -0
- package/dist/src/cli/commands/info.js.map +1 -0
- package/dist/src/cli/commands/list.d.ts +10 -0
- package/dist/src/cli/commands/list.js +85 -0
- package/dist/src/cli/commands/list.js.map +1 -0
- package/dist/src/cli/commands/login.d.ts +10 -0
- package/dist/src/cli/commands/login.js +158 -0
- package/dist/src/cli/commands/login.js.map +1 -0
- package/dist/src/cli/commands/open.d.ts +10 -0
- package/dist/src/cli/commands/open.js +141 -0
- package/dist/src/cli/commands/open.js.map +1 -0
- package/dist/src/cli/commands/video.d.ts +10 -0
- package/dist/src/cli/commands/video.js +209 -0
- package/dist/src/cli/commands/video.js.map +1 -0
- package/dist/src/cli/index.d.ts +15 -0
- package/dist/src/cli/index.js +134 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/progress-display.d.ts +80 -0
- package/dist/src/cli/progress-display.js +225 -0
- package/dist/src/cli/progress-display.js.map +1 -0
- package/dist/src/cli/utils.d.ts +31 -0
- package/dist/src/cli/utils.js +171 -0
- package/dist/src/cli/utils.js.map +1 -0
- package/dist/src/douyin/auth/cookie-path.d.ts +22 -0
- package/dist/src/douyin/auth/cookie-path.js +72 -0
- package/dist/src/douyin/auth/cookie-path.js.map +1 -0
- package/dist/src/douyin/auth/cookie-storage.d.ts +19 -0
- package/dist/src/douyin/auth/cookie-storage.js +65 -0
- package/dist/src/douyin/auth/cookie-storage.js.map +1 -0
- package/dist/src/douyin/auth/errors.d.ts +28 -0
- package/dist/src/douyin/auth/errors.js +49 -0
- package/dist/src/douyin/auth/errors.js.map +1 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.d.ts +24 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.js +90 -0
- package/dist/src/douyin/auth/getDefaultCookiePath.js.map +1 -0
- package/dist/src/douyin/auth/index.d.ts +16 -0
- package/dist/src/douyin/auth/index.js +68 -0
- package/dist/src/douyin/auth/index.js.map +1 -0
- package/dist/src/douyin/auth/isValidCookie.d.ts +18 -0
- package/dist/src/douyin/auth/isValidCookie.js +60 -0
- package/dist/src/douyin/auth/isValidCookie.js.map +1 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.d.ts +17 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.js +45 -0
- package/dist/src/douyin/auth/loadAndValidateCookie.js.map +1 -0
- package/dist/src/douyin/auth/loadCookie.d.ts +17 -0
- package/dist/src/douyin/auth/loadCookie.js +79 -0
- package/dist/src/douyin/auth/loadCookie.js.map +1 -0
- package/dist/src/douyin/auth/login.d.ts +33 -0
- package/dist/src/douyin/auth/login.js +157 -0
- package/dist/src/douyin/auth/login.js.map +1 -0
- package/dist/src/douyin/auth/saveCookie.d.ts +17 -0
- package/dist/src/douyin/auth/saveCookie.js +89 -0
- package/dist/src/douyin/auth/saveCookie.js.map +1 -0
- package/dist/src/douyin/auth/validate.d.ts +11 -0
- package/dist/src/douyin/auth/validate.js +104 -0
- package/dist/src/douyin/auth/validate.js.map +1 -0
- package/dist/src/douyin/browser/manager.d.ts +54 -0
- package/dist/src/douyin/browser/manager.js +344 -0
- package/dist/src/douyin/browser/manager.js.map +1 -0
- package/dist/src/douyin/download/download-manager.d.ts +25 -0
- package/dist/src/douyin/download/download-manager.js +107 -0
- package/dist/src/douyin/download/download-manager.js.map +1 -0
- package/dist/src/douyin/download/error-handler.d.ts +49 -0
- package/dist/src/douyin/download/error-handler.js +160 -0
- package/dist/src/douyin/download/error-handler.js.map +1 -0
- package/dist/src/douyin/download/index.d.ts +39 -0
- package/dist/src/douyin/download/index.js +156 -0
- package/dist/src/douyin/download/index.js.map +1 -0
- package/dist/src/douyin/download/path-formatter.d.ts +42 -0
- package/dist/src/douyin/download/path-formatter.js +107 -0
- package/dist/src/douyin/download/path-formatter.js.map +1 -0
- package/dist/src/douyin/download/video-downloader.d.ts +35 -0
- package/dist/src/douyin/download/video-downloader.js +223 -0
- package/dist/src/douyin/download/video-downloader.js.map +1 -0
- package/dist/src/douyin/index.d.ts +19 -0
- package/dist/src/douyin/index.js +52 -0
- package/dist/src/douyin/index.js.map +1 -0
- package/dist/src/douyin/info/batch-processor.d.ts +15 -0
- package/dist/src/douyin/info/batch-processor.js +65 -0
- package/dist/src/douyin/info/batch-processor.js.map +1 -0
- package/dist/src/douyin/info/browser-manager.d.ts +56 -0
- package/dist/src/douyin/info/browser-manager.js +225 -0
- package/dist/src/douyin/info/browser-manager.js.map +1 -0
- package/dist/src/douyin/info/error-handler.d.ts +36 -0
- package/dist/src/douyin/info/error-handler.js +172 -0
- package/dist/src/douyin/info/error-handler.js.map +1 -0
- package/dist/src/douyin/info/fetch-video-detail.d.ts +14 -0
- package/dist/src/douyin/info/fetch-video-detail.js +247 -0
- package/dist/src/douyin/info/fetch-video-detail.js.map +1 -0
- package/dist/src/douyin/info/index.d.ts +29 -0
- package/dist/src/douyin/info/index.js +85 -0
- package/dist/src/douyin/info/index.js.map +1 -0
- package/dist/src/douyin/info/text-processor.d.ts +15 -0
- package/dist/src/douyin/info/text-processor.js +47 -0
- package/dist/src/douyin/info/text-processor.js.map +1 -0
- package/dist/src/douyin/info/user.d.ts +26 -0
- package/dist/src/douyin/info/user.js +237 -0
- package/dist/src/douyin/info/user.js.map +1 -0
- package/dist/src/douyin/parser/containsDouyinLink.d.ts +18 -0
- package/dist/src/douyin/parser/containsDouyinLink.js +27 -0
- package/dist/src/douyin/parser/containsDouyinLink.js.map +1 -0
- package/dist/src/douyin/parser/extract-links.d.ts +23 -0
- package/dist/src/douyin/parser/extract-links.js +79 -0
- package/dist/src/douyin/parser/extract-links.js.map +1 -0
- package/dist/src/douyin/parser/extractDouyinLinks.d.ts +18 -0
- package/dist/src/douyin/parser/extractDouyinLinks.js +58 -0
- package/dist/src/douyin/parser/extractDouyinLinks.js.map +1 -0
- package/dist/src/douyin/parser/index.d.ts +35 -0
- package/dist/src/douyin/parser/index.js +70 -0
- package/dist/src/douyin/parser/index.js.map +1 -0
- package/dist/src/douyin/parser/link-patterns.d.ts +34 -0
- package/dist/src/douyin/parser/link-patterns.js +121 -0
- package/dist/src/douyin/parser/link-patterns.js.map +1 -0
- package/dist/src/douyin/parser/parse-batch.d.ts +26 -0
- package/dist/src/douyin/parser/parse-batch.js +67 -0
- package/dist/src/douyin/parser/parse-batch.js.map +1 -0
- package/dist/src/douyin/parser/parseDouyinLinks.d.ts +30 -0
- package/dist/src/douyin/parser/parseDouyinLinks.js +164 -0
- package/dist/src/douyin/parser/parseDouyinLinks.js.map +1 -0
- package/dist/src/douyin/parser/resolve-links.d.ts +25 -0
- package/dist/src/douyin/parser/resolve-links.js +131 -0
- package/dist/src/douyin/parser/resolve-links.js.map +1 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +72 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types.d.ts +217 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/browser.d.ts +73 -0
- package/dist/src/utils/browser.js +96 -0
- package/dist/src/utils/browser.js.map +1 -0
- package/dist/src/utils/error.d.ts +160 -0
- package/dist/src/utils/error.js +334 -0
- package/dist/src/utils/error.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +41 -0
- package/dist/src/utils/fetch.js +155 -0
- package/dist/src/utils/fetch.js.map +1 -0
- package/dist/src/utils/file.d.ts +46 -0
- package/dist/src/utils/file.js +189 -0
- package/dist/src/utils/file.js.map +1 -0
- package/dist/src/utils/index.d.ts +11 -0
- package/dist/src/utils/index.js +29 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/logger.d.ts +161 -0
- package/dist/src/utils/logger.js +286 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/performance.d.ts +98 -0
- package/dist/src/utils/performance.js +292 -0
- package/dist/src/utils/performance.js.map +1 -0
- package/dist/src/utils/retry.d.ts +56 -0
- package/dist/src/utils/retry.js +127 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/package.json +61 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
"use strict";
|
2
|
+
/**
|
3
|
+
* 影片詳情提取核心功能
|
4
|
+
* 從抖音影片頁面獲取詳細資訊 (基於 reference/DouyinParser.ts 邏輯)
|
5
|
+
*/
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
+
exports.fetchVideoDetail = fetchVideoDetail;
|
8
|
+
const logger_1 = require("../../utils/logger");
|
9
|
+
// import * as fs from 'fs'; // For potential debugging output
|
10
|
+
// import * as path from 'path'; // For potential debugging output
|
11
|
+
// import { fileURLToPath } from 'url'; // For potential debugging output
|
12
|
+
/**
|
13
|
+
* 從抖音影片頁面獲取詳細資訊
|
14
|
+
* @param videoUrl 標準的抖音影片 URL
|
15
|
+
* @param cookie 抖音 Cookie 字串
|
16
|
+
* @returns Promise<VideoInfo | null> 影片資訊或 null
|
17
|
+
*/
|
18
|
+
async function fetchVideoDetail(page, // Changed: Accept Page object
|
19
|
+
videoUrl
|
20
|
+
// cookie: string // Removed: Cookie should be set on the page beforehand
|
21
|
+
) {
|
22
|
+
// let page: Page | null = null; // Removed: Page is passed in
|
23
|
+
try {
|
24
|
+
logger_1.infoLogger.debug(`[fetchVideoDetail] 使用傳入的 Page 獲取影片資訊: ${videoUrl}`);
|
25
|
+
// Removed: Page creation and setup (User-Agent, Cookie) are now handled by the caller
|
26
|
+
// --- 導航到頁面 ---
|
27
|
+
logger_1.infoLogger.debug(`[fetchVideoDetail] 正在導航至 ${videoUrl}...`);
|
28
|
+
await page.goto(videoUrl, {
|
29
|
+
waitUntil: 'networkidle2', // 等待網路大致空閒
|
30
|
+
timeout: page.getDefaultTimeout() || 60000 // 使用頁面預設超時或 60s
|
31
|
+
});
|
32
|
+
logger_1.infoLogger.debug('[fetchVideoDetail] 頁面導航完成');
|
33
|
+
// --- 等待關鍵元素出現 ---
|
34
|
+
const videoSelector = 'video'; // 主要等待目標
|
35
|
+
const waitTimeout = 20000; // 增加等待時間
|
36
|
+
try {
|
37
|
+
logger_1.infoLogger.debug(`[fetchVideoDetail] 正在等待影片選擇器: ${videoSelector} (最多 ${waitTimeout}ms)...`);
|
38
|
+
await page.waitForSelector(videoSelector, { timeout: waitTimeout });
|
39
|
+
logger_1.infoLogger.debug('[fetchVideoDetail] 影片選擇器已找到!');
|
40
|
+
// 將影片元素的 src 屬性字首 'blob:' 移除,以強制重新加載
|
41
|
+
await page.evaluate(() => {
|
42
|
+
const videoElement = document.querySelector('video[src]');
|
43
|
+
if (videoElement) {
|
44
|
+
const src = videoElement.getAttribute('src');
|
45
|
+
if (src && src.startsWith('blob:')) {
|
46
|
+
videoElement.setAttribute('src', src.replace('blob:', ''));
|
47
|
+
console.log('已移除 blob: 前綴');
|
48
|
+
}
|
49
|
+
}
|
50
|
+
});
|
51
|
+
await page.waitForSelector('video source[src]', { timeout: waitTimeout });
|
52
|
+
}
|
53
|
+
catch (waitError) {
|
54
|
+
const error = waitError instanceof Error ? waitError : new Error(String(waitError));
|
55
|
+
logger_1.infoLogger.error(`[fetchVideoDetail] 等待元素 (${videoSelector}) 時超時或出錯: ${error.message}`);
|
56
|
+
logger_1.infoLogger.warn('[fetchVideoDetail] 頁面可能未完全加載或結構已更改。');
|
57
|
+
// --- 可選:保存 HTML 以便調試 ---
|
58
|
+
// try {
|
59
|
+
// const pageContent = await page.content();
|
60
|
+
// // 需要找到替代 import.meta.url 的方法來確定路徑,或使用固定路徑
|
61
|
+
// // const debugHtmlPath = path.join(__dirname, '../../../', 'debug_page_wait_error.html');
|
62
|
+
// // fs.writeFileSync(debugHtmlPath, pageContent);
|
63
|
+
// // logger.info(`頁面 HTML 已保存到 ${debugHtmlPath} 以便調試。`);
|
64
|
+
// } catch (writeError) {
|
65
|
+
// const err = writeError instanceof Error ? writeError : new Error(String(writeError));
|
66
|
+
// logger.error('保存 debug HTML 時出錯:', err.message);
|
67
|
+
// }
|
68
|
+
// --- 結束可選調試 ---
|
69
|
+
return null; // 等待失敗,無法繼續提取
|
70
|
+
}
|
71
|
+
// --- 直接從 HTML 元素提取資訊 ---
|
72
|
+
logger_1.infoLogger.debug('[fetchVideoDetail] 等待完成,正在嘗試直接從 HTML 元素提取資訊...');
|
73
|
+
const extractedDetails = await page.evaluate(() => {
|
74
|
+
// --- 提取邏輯 (合併自 reference 和 extractors) ---
|
75
|
+
// 提取 ID (參考 extractVideoId)
|
76
|
+
let id = '';
|
77
|
+
const urlMatch = window.location.href.match(/\/video\/(\d+)/);
|
78
|
+
if (urlMatch && urlMatch[1]) {
|
79
|
+
id = urlMatch[1];
|
80
|
+
}
|
81
|
+
else {
|
82
|
+
const canonicalLink = document.querySelector('link[rel="canonical"]');
|
83
|
+
if (canonicalLink) {
|
84
|
+
const href = canonicalLink.getAttribute('href') || '';
|
85
|
+
const canonicalMatch = href.match(/\/video\/(\d+)/);
|
86
|
+
if (canonicalMatch && canonicalMatch[1]) {
|
87
|
+
id = canonicalMatch[1];
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
if (!id) {
|
92
|
+
const metaUrl = document.querySelector('meta[property="og:url"]');
|
93
|
+
if (metaUrl) {
|
94
|
+
const content = metaUrl.getAttribute('content') || '';
|
95
|
+
const metaMatch = content.match(/\/video\/(\d+)/);
|
96
|
+
if (metaMatch && metaMatch[1]) {
|
97
|
+
id = metaMatch[1];
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
// 可以在此處添加從頁面源碼提取 ID 的備用邏輯,但 evaluate 中訪問 innerHTML 可能有限制
|
102
|
+
// 提取標題 (參考 reference 和 extractTitle)
|
103
|
+
let title = '';
|
104
|
+
// 1. 嘗試使用 reference 中的特定 H1 選擇器
|
105
|
+
const specificH1Selector = 'h1 > span > span:nth-child(2) > span > span:first-child > span:first-child > span:first-child > span:first-child';
|
106
|
+
const specificH1Element = document.querySelector(specificH1Selector);
|
107
|
+
if (specificH1Element) {
|
108
|
+
title = specificH1Element.textContent?.trim() || '';
|
109
|
+
}
|
110
|
+
// 2. 如果特定 H1 失敗,回退到 document.title
|
111
|
+
if (!title) {
|
112
|
+
title = document.title || '';
|
113
|
+
}
|
114
|
+
// 3. 如果 document.title 也失敗,嘗試 og:title
|
115
|
+
if (!title) {
|
116
|
+
const metaTitle = document.querySelector('meta[property="og:title"]');
|
117
|
+
if (metaTitle) {
|
118
|
+
title = metaTitle.getAttribute('content') || '';
|
119
|
+
}
|
120
|
+
}
|
121
|
+
// 最終如果還是空,會在返回時處理為 '未知標題'
|
122
|
+
title = (title || '').split('#')[0].trim(); // 去除 # 及其後的內容
|
123
|
+
// 提取影片播放連結 (參考 reference 和 extractVideoUrl)
|
124
|
+
let videoPlayUrl = '';
|
125
|
+
let cdnPlayUrls = [];
|
126
|
+
const videoSourceSelector = 'video source[src]';
|
127
|
+
const sourceElements = document.querySelectorAll(videoSourceSelector);
|
128
|
+
let videoUrls = Array.from(sourceElements).map(v => v.getAttribute('src') || '');
|
129
|
+
videoPlayUrl = videoUrls.pop() || '';
|
130
|
+
cdnPlayUrls = videoUrls;
|
131
|
+
// 可以在此處添加從 script 提取的備用邏輯
|
132
|
+
// 提取作者資訊 (參考 reference 和 extractAuthorInfo)
|
133
|
+
let userName = '';
|
134
|
+
let userUrl = '';
|
135
|
+
const userJsonSelector = 'script[type="application/ld+json"]';
|
136
|
+
const userJsonElement = document.querySelector(userJsonSelector);
|
137
|
+
if (userJsonElement) {
|
138
|
+
try {
|
139
|
+
const userJsonText = userJsonElement.textContent?.trim() || '{}';
|
140
|
+
const userJson = JSON.parse(userJsonText);
|
141
|
+
// reference 中的邏輯是取 itemListElement[1] 或 itemListElement[length - 2]
|
142
|
+
if (userJson.itemListElement && userJson.itemListElement.length > 1) {
|
143
|
+
// 假設作者信息在倒數第二個元素
|
144
|
+
const userItem = userJson.itemListElement[userJson.itemListElement.length - 2];
|
145
|
+
if (userItem && userItem.name && userItem.item) {
|
146
|
+
userName = userItem.name;
|
147
|
+
userUrl = userItem.item;
|
148
|
+
}
|
149
|
+
else if (userJson.itemListElement.length > 1) { // 備用:取第二個
|
150
|
+
const backupUserItem = userJson.itemListElement[1];
|
151
|
+
if (backupUserItem && backupUserItem.name && backupUserItem.item) {
|
152
|
+
userName = backupUserItem.name;
|
153
|
+
userUrl = backupUserItem.item;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
catch (e) {
|
159
|
+
console.error('解析用戶 JSON-LD 失敗:', e);
|
160
|
+
}
|
161
|
+
}
|
162
|
+
// 可以在此處添加從其他元素提取作者的備用邏輯
|
163
|
+
// 提取發布日期 (參考 reference 和 extractReleaseDate)
|
164
|
+
let releaseDate = '';
|
165
|
+
const metaDescriptionSelector = 'meta[name="description"]';
|
166
|
+
const metaDescriptionElement = document.querySelector(metaDescriptionSelector);
|
167
|
+
if (metaDescriptionElement) {
|
168
|
+
const content = metaDescriptionElement.getAttribute('content') || '';
|
169
|
+
const dateMatch = content.match(/于(\d{8}|\d{4}-\d{2}-\d{2})发布/); // 匹配 YYYYMMDD 或 YYYY-MM-DD
|
170
|
+
if (dateMatch && dateMatch[1]) {
|
171
|
+
const rawDate = dateMatch[1];
|
172
|
+
if (rawDate.includes('-')) {
|
173
|
+
releaseDate = rawDate;
|
174
|
+
}
|
175
|
+
else if (rawDate.length === 8) {
|
176
|
+
releaseDate = `${rawDate.slice(0, 4)}-${rawDate.slice(4, 6)}-${rawDate.slice(6, 8)}`;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
// 可以在此處添加從 time 元素或其他元素提取日期的備用邏輯
|
181
|
+
// 提取封面 URL (參考 extractCoverUrl)
|
182
|
+
let coverUrl = '';
|
183
|
+
const metaOgImage = document.querySelector('meta[property="og:image"]');
|
184
|
+
if (metaOgImage) {
|
185
|
+
coverUrl = metaOgImage.getAttribute('content') || '';
|
186
|
+
}
|
187
|
+
else {
|
188
|
+
const videoPoster = document.querySelector('video[poster]');
|
189
|
+
if (videoPoster) {
|
190
|
+
coverUrl = videoPoster.getAttribute('poster') || '';
|
191
|
+
}
|
192
|
+
}
|
193
|
+
// 可以在此處添加從 JSON-LD 或頁面源碼提取封面的備用邏輯
|
194
|
+
return {
|
195
|
+
id: id || '',
|
196
|
+
title: title || '未知標題',
|
197
|
+
videoPlayUrl: videoPlayUrl || '',
|
198
|
+
cdnPlayUrls: cdnPlayUrls || [],
|
199
|
+
userName: userName || '未知用戶',
|
200
|
+
userUrl: userUrl || '',
|
201
|
+
releaseDate: releaseDate || '',
|
202
|
+
coverUrl: coverUrl || '',
|
203
|
+
};
|
204
|
+
});
|
205
|
+
// 檢查是否成功提取到必要資訊 (播放連結)
|
206
|
+
if (!extractedDetails || !extractedDetails.videoPlayUrl) {
|
207
|
+
logger_1.infoLogger.error(`[fetchVideoDetail] 未能從 HTML 元素中提取到必要的影片 ID 或播放連結: ${videoUrl}`);
|
208
|
+
logger_1.infoLogger.debug('[fetchVideoDetail] 提取到的部分資訊:', extractedDetails);
|
209
|
+
// --- 可選:保存 HTML 以便調試 ---
|
210
|
+
// try {
|
211
|
+
// const pageContent = await page.content();
|
212
|
+
// // 需要找到替代 import.meta.url 的方法來確定路徑,或使用固定路徑
|
213
|
+
// // const debugHtmlPath = path.join(__dirname, '../../../', 'debug_page_extract_error.html');
|
214
|
+
// // fs.writeFileSync(debugHtmlPath, pageContent);
|
215
|
+
// // logger.info(`頁面 HTML 已保存到 ${debugHtmlPath} 以便調試。`);
|
216
|
+
// } catch (writeError) {
|
217
|
+
// const err = writeError instanceof Error ? writeError : new Error(String(writeError));
|
218
|
+
// logger.error('保存 debug HTML 時出錯:', err.message);
|
219
|
+
// }
|
220
|
+
// --- 結束可選調試 ---
|
221
|
+
return null;
|
222
|
+
}
|
223
|
+
logger_1.infoLogger.debug('[fetchVideoDetail] 成功從 HTML 元素提取到影片資訊!');
|
224
|
+
// 構建 VideoInfo 物件
|
225
|
+
const videoInfo = {
|
226
|
+
id: extractedDetails.id,
|
227
|
+
title: extractedDetails.title,
|
228
|
+
videoPlayUrl: extractedDetails.videoPlayUrl,
|
229
|
+
cdnPlayUrls: extractedDetails.cdnPlayUrls,
|
230
|
+
userName: extractedDetails.userName,
|
231
|
+
userUrl: extractedDetails.userUrl,
|
232
|
+
releaseDate: extractedDetails.releaseDate || undefined, // 如果為空字符串,設為 undefined
|
233
|
+
coverUrl: extractedDetails.coverUrl || undefined, // 如果為空字符串,設為 undefined
|
234
|
+
};
|
235
|
+
logger_1.infoLogger.info(`[fetchVideoDetail] 成功獲取影片資訊: ${videoInfo.title}`);
|
236
|
+
return videoInfo;
|
237
|
+
}
|
238
|
+
catch (error) {
|
239
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
240
|
+
logger_1.infoLogger.error(`[fetchVideoDetail] 獲取影片資訊失敗: ${videoUrl}`, err);
|
241
|
+
// 可以在此處添加更詳細的錯誤堆棧打印
|
242
|
+
// logger.error(err.stack);
|
243
|
+
return null;
|
244
|
+
}
|
245
|
+
// Removed: finally block - page lifecycle is managed by the caller
|
246
|
+
}
|
247
|
+
//# sourceMappingURL=fetch-video-detail.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"fetch-video-detail.js","sourceRoot":"","sources":["../../../../src/douyin/info/fetch-video-detail.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/**
|
2
|
+
* 影片資訊獲取模組
|
3
|
+
* 提供從抖音影片連結獲取詳細資訊的功能
|
4
|
+
*/
|
5
|
+
import { VideoInfo, FetchVideoOptions } from '../../types';
|
6
|
+
import { Page } from 'puppeteer';
|
7
|
+
export { fetchVideoDetail } from './fetch-video-detail';
|
8
|
+
export { processBatch } from './batch-processor';
|
9
|
+
export { processTextContent } from './text-processor';
|
10
|
+
export { isRetryableError, handleDouyinApiError } from './error-handler';
|
11
|
+
export { fetchUserVideos, extractSecUserId } from './user';
|
12
|
+
/**
|
13
|
+
* 從文本中解析抖音影片連結,並獲取這些影片的詳細資訊
|
14
|
+
* @param text 包含一個或多個抖音連結的文本
|
15
|
+
* @param cookie 有效的抖音 Cookie 字串
|
16
|
+
* @param options 獲取選項
|
17
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊陣列
|
18
|
+
*/
|
19
|
+
export declare function fetchVideosInfoText(text: string, page: Page, // Changed: Accept Page object
|
20
|
+
options?: FetchVideoOptions): Promise<VideoInfo[]>;
|
21
|
+
/**
|
22
|
+
* 獲取指定抖音影片 URL 的詳細資訊
|
23
|
+
* @param videoUrls 抖音影片 URL 陣列
|
24
|
+
* @param cookie 有效的抖音 Cookie 字串
|
25
|
+
* @param options 獲取選項
|
26
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊陣列
|
27
|
+
*/
|
28
|
+
export declare function fetchVideosInfoUrls(videoUrls: string[], page: Page, // Changed: Accept Page object
|
29
|
+
options?: FetchVideoOptions): Promise<VideoInfo[]>;
|
@@ -0,0 +1,85 @@
|
|
1
|
+
"use strict";
|
2
|
+
// Copied from src/info/index.ts
|
3
|
+
// Original file path: src/info/index.ts
|
4
|
+
/**
|
5
|
+
* 影片資訊獲取模組
|
6
|
+
* 提供從抖音影片連結獲取詳細資訊的功能
|
7
|
+
*/
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.extractSecUserId = exports.fetchUserVideos = exports.handleDouyinApiError = exports.isRetryableError = exports.processTextContent = exports.processBatch = exports.fetchVideoDetail = void 0;
|
10
|
+
exports.fetchVideosInfoText = fetchVideosInfoText;
|
11
|
+
exports.fetchVideosInfoUrls = fetchVideosInfoUrls;
|
12
|
+
const logger_1 = require("../../utils/logger"); // Updated path to shared utils logger
|
13
|
+
const batch_processor_1 = require("./batch-processor");
|
14
|
+
const text_processor_1 = require("./text-processor");
|
15
|
+
// 重新導出影片資訊獲取功能
|
16
|
+
var fetch_video_detail_1 = require("./fetch-video-detail");
|
17
|
+
Object.defineProperty(exports, "fetchVideoDetail", { enumerable: true, get: function () { return fetch_video_detail_1.fetchVideoDetail; } });
|
18
|
+
// Removed export from './extractors' as the file is deleted
|
19
|
+
var batch_processor_2 = require("./batch-processor");
|
20
|
+
Object.defineProperty(exports, "processBatch", { enumerable: true, get: function () { return batch_processor_2.processBatch; } });
|
21
|
+
var text_processor_2 = require("./text-processor");
|
22
|
+
Object.defineProperty(exports, "processTextContent", { enumerable: true, get: function () { return text_processor_2.processTextContent; } });
|
23
|
+
// export { browserManager, cleanupBrowser } from '../../utils/browser'; // Removed: Use new browser manager
|
24
|
+
var error_handler_1 = require("./error-handler"); // Keep local error handler for now
|
25
|
+
Object.defineProperty(exports, "isRetryableError", { enumerable: true, get: function () { return error_handler_1.isRetryableError; } });
|
26
|
+
Object.defineProperty(exports, "handleDouyinApiError", { enumerable: true, get: function () { return error_handler_1.handleDouyinApiError; } });
|
27
|
+
// fetchWithRetry is now just withRetry from utils/retry
|
28
|
+
var user_1 = require("./user");
|
29
|
+
Object.defineProperty(exports, "fetchUserVideos", { enumerable: true, get: function () { return user_1.fetchUserVideos; } });
|
30
|
+
Object.defineProperty(exports, "extractSecUserId", { enumerable: true, get: function () { return user_1.extractSecUserId; } });
|
31
|
+
/**
|
32
|
+
* 從文本中解析抖音影片連結,並獲取這些影片的詳細資訊
|
33
|
+
* @param text 包含一個或多個抖音連結的文本
|
34
|
+
* @param cookie 有效的抖音 Cookie 字串
|
35
|
+
* @param options 獲取選項
|
36
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊陣列
|
37
|
+
*/
|
38
|
+
async function fetchVideosInfoText(text, page, // Changed: Accept Page object
|
39
|
+
// cookie: string, // Removed
|
40
|
+
options = {}) {
|
41
|
+
if (!text || text.trim() === '') {
|
42
|
+
logger_1.infoLogger.warn('提供的文本為空');
|
43
|
+
return [];
|
44
|
+
}
|
45
|
+
// Removed: Cookie check, assuming page is valid and has cookies if needed
|
46
|
+
logger_1.infoLogger.info('[fetchVideosInfoText] 從文本中提取並獲取影片資訊');
|
47
|
+
try {
|
48
|
+
// 使用文本處理器處理文本內容
|
49
|
+
return await (0, text_processor_1.processTextContent)(text, page, options); // Pass page instead of cookie
|
50
|
+
}
|
51
|
+
catch (error) {
|
52
|
+
logger_1.infoLogger.error('[fetchVideosInfoText] 從文本獲取影片資訊失敗:', error);
|
53
|
+
throw error;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
/**
|
57
|
+
* 獲取指定抖音影片 URL 的詳細資訊
|
58
|
+
* @param videoUrls 抖音影片 URL 陣列
|
59
|
+
* @param cookie 有效的抖音 Cookie 字串
|
60
|
+
* @param options 獲取選項
|
61
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊陣列
|
62
|
+
*/
|
63
|
+
async function fetchVideosInfoUrls(videoUrls, page, // Changed: Accept Page object
|
64
|
+
// cookie: string, // Removed
|
65
|
+
options = {}) {
|
66
|
+
if (!videoUrls || videoUrls.length === 0) {
|
67
|
+
logger_1.infoLogger.warn('未提供影片 URL');
|
68
|
+
return [];
|
69
|
+
}
|
70
|
+
// Removed: Cookie check, assuming page is valid and has cookies if needed
|
71
|
+
logger_1.infoLogger.info(`[fetchVideosInfoUrls] 準備獲取 ${videoUrls.length} 個影片的資訊`);
|
72
|
+
try {
|
73
|
+
// 使用批量處理功能獲取影片資訊
|
74
|
+
return await (0, batch_processor_1.processBatch)(videoUrls, page, options); // Pass page instead of cookie
|
75
|
+
}
|
76
|
+
catch (error) {
|
77
|
+
logger_1.infoLogger.error('[fetchVideosInfoUrls] 獲取影片資訊失敗:', error);
|
78
|
+
throw error;
|
79
|
+
}
|
80
|
+
finally {
|
81
|
+
// 可以選擇在這裡清理瀏覽器資源,但通常我們會保持瀏覽器實例以備後續使用
|
82
|
+
// 進程結束時會自動清理
|
83
|
+
}
|
84
|
+
}
|
85
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/douyin/info/index.ts"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,wCAAwC;AACxC;;;GAGG;;;AAyBH,kDAsBC;AASD,kDAyBC;AA/ED,+CAAoE,CAAC,sCAAsC;AAE3G,uDAAmE;AACnE,qDAAuE;AAGvE,eAAe;AACf,2DAAwD;AAA/C,sHAAA,gBAAgB,OAAA;AACzB,4DAA4D;AAC5D,qDAAiD;AAAxC,+GAAA,YAAY,OAAA;AACrB,mDAAsD;AAA7C,oHAAA,kBAAkB,OAAA;AAC3B,4GAA4G;AAC5G,iDAAyE,CAAC,mCAAmC;AAApG,iHAAA,gBAAgB,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAC/C,wDAAwD;AACxD,+BAA2D;AAAlD,uGAAA,eAAe,OAAA;AAAE,wGAAA,gBAAgB,OAAA;AAE1C;;;;;;GAMG;AACI,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,IAAU,EAAE,8BAA8B;AAC1C,6BAA6B;AAC7B,UAA6B,EAAE;IAE/B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAChC,mBAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,0EAA0E;IAE1E,mBAAM,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,gBAAgB;QAChB,OAAO,MAAM,IAAA,mCAAa,EAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B;IACjF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mBAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE,KAAc,CAAC,CAAC;QACnE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,mBAAmB,CACvC,SAAmB,EACnB,IAAU,EAAE,8BAA8B;AAC1C,6BAA6B;AAC7B,UAA6B,EAAE;IAE/B,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,mBAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,0EAA0E;IAE1E,mBAAM,CAAC,IAAI,CAAC,8BAA8B,SAAS,CAAC,MAAM,SAAS,CAAC,CAAC;IAErE,IAAI,CAAC;QACH,iBAAiB;QACjB,OAAO,MAAM,IAAA,8BAAc,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B;IACvF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mBAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAc,CAAC,CAAC;QAChE,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,qCAAqC;QACrC,aAAa;IACf,CAAC;AACH,CAAC"}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* 文本解析與處理
|
3
|
+
* 結合連結解析模組,實現從文本中提取並獲取影片資訊
|
4
|
+
*/
|
5
|
+
import { VideoInfo, FetchVideoOptions } from '../../types';
|
6
|
+
import { Page } from 'puppeteer';
|
7
|
+
/**
|
8
|
+
* 從文本內容中提取抖音連結並獲取影片資訊
|
9
|
+
* @param text 包含抖音連結的文本
|
10
|
+
* @param cookie 抖音 Cookie 字串
|
11
|
+
* @param options 獲取選項
|
12
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊結果陣列
|
13
|
+
*/
|
14
|
+
export declare function processTextContent(text: string, page: Page, // Changed: Accept Page object
|
15
|
+
options?: FetchVideoOptions): Promise<VideoInfo[]>;
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"use strict";
|
2
|
+
// Copied from src/info/text-processor.ts
|
3
|
+
// Original file path: src/info/text-processor.ts
|
4
|
+
/**
|
5
|
+
* 文本解析與處理
|
6
|
+
* 結合連結解析模組,實現從文本中提取並獲取影片資訊
|
7
|
+
*/
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.processTextContent = processTextContent;
|
10
|
+
const logger_1 = require("../../utils/logger"); // Updated path to shared utils logger
|
11
|
+
const parser_1 = require("../parser"); // Corrected path
|
12
|
+
const batch_processor_1 = require("./batch-processor");
|
13
|
+
/**
|
14
|
+
* 從文本內容中提取抖音連結並獲取影片資訊
|
15
|
+
* @param text 包含抖音連結的文本
|
16
|
+
* @param cookie 抖音 Cookie 字串
|
17
|
+
* @param options 獲取選項
|
18
|
+
* @returns Promise<VideoInfoResult[]> 影片資訊結果陣列
|
19
|
+
*/
|
20
|
+
async function processTextContent(text, page, // Changed: Accept Page object
|
21
|
+
// cookie: string, // Removed
|
22
|
+
options = {}) {
|
23
|
+
logger_1.infoLogger.debug('[processTextContent] 開始從文本中提取抖音連結');
|
24
|
+
// 使用連結解析模組從文本中提取抖音連結
|
25
|
+
const parseResults = await (0, parser_1.parseDouyinLinks)(text, {
|
26
|
+
concurrency: options.concurrency,
|
27
|
+
onProgress: options.onProgress
|
28
|
+
});
|
29
|
+
if (parseResults.length === 0) {
|
30
|
+
logger_1.infoLogger.warn('未從文本中找到有效的抖音連結');
|
31
|
+
return [];
|
32
|
+
}
|
33
|
+
logger_1.infoLogger.info(`[processTextContent] 從文本中找到 ${parseResults.length} 個抖音連結,開始獲取詳細資訊`);
|
34
|
+
// 獲取標準 URL 陣列
|
35
|
+
const videoUrls = parseResults.map((result) => result.standardUrl);
|
36
|
+
// 使用批量處理功能獲取影片資訊
|
37
|
+
const results = await (0, batch_processor_1.processBatch)(videoUrls, page, options); // Pass page instead of cookie
|
38
|
+
// 檢查是否有失敗的獲取
|
39
|
+
if (results.length < videoUrls.length) {
|
40
|
+
const failedCount = videoUrls.length - results.length;
|
41
|
+
logger_1.infoLogger.warn(`[processTextContent] 無法獲取影片資訊: ${failedCount} 個影片獲取失敗`, 'fetchVideoDetail 返回 null');
|
42
|
+
}
|
43
|
+
// 直接返回處理結果,不添加額外屬性
|
44
|
+
logger_1.infoLogger.info(`[processTextContent] 文本處理完成,成功獲取 ${results.length} 個影片的資訊`);
|
45
|
+
return results;
|
46
|
+
}
|
47
|
+
//# sourceMappingURL=text-processor.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"text-processor.js","sourceRoot":"","sources":["../../../../src/douyin/info/text-processor.ts"],"names":[],"mappings":";AAAA,yCAAyC;AACzC,iDAAiD;AACjD;;;GAGG;;AAeH,gDAqCC;AAlDD,+CAA0D,CAAC,sCAAsC;AACjG,sCAA6C,CAAC,iBAAiB;AAC/D,uDAAiD;AAIjD;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,IAAU,EAAE,8BAA8B;AAC1C,6BAA6B;AAC7B,UAA6B,EAAE;IAE/B,mBAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAElD,qBAAqB;IACrB,MAAM,YAAY,GAAG,MAAM,IAAA,yBAAgB,EAAC,IAAI,EAAE;QAChD,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,UAAU,EAAE,OAAO,CAAC,UAAU;KAC/B,CAAC,CAAC;IAEH,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,mBAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,mBAAM,CAAC,IAAI,CAAC,+BAA+B,YAAY,CAAC,MAAM,iBAAiB,CAAC,CAAC;IAEjF,cAAc;IACd,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,MAAmB,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEhF,iBAAiB;IACjB,MAAM,OAAO,GAAG,MAAM,IAAA,8BAAY,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,8BAA8B;IAE5F,aAAa;IACb,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACtD,mBAAM,CAAC,IAAI,CAAC,kCAAkC,WAAW,UAAU,EAAE,0BAA0B,CAAC,CAAC;IACnG,CAAC;IAED,mBAAmB;IACnB,mBAAM,CAAC,IAAI,CAAC,oCAAoC,OAAO,CAAC,MAAM,SAAS,CAAC,CAAC;IAEzE,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/**
|
2
|
+
* 用戶影片獲取模組
|
3
|
+
* 提供獲取抖音用戶發布影片列表的功能
|
4
|
+
*/
|
5
|
+
import { UserVideoItem, UserVideosOptions } from '../../types';
|
6
|
+
/**
|
7
|
+
* 從 URL 列表中獲取官方影片下載地址
|
8
|
+
* @param urlList URL 列表
|
9
|
+
* @returns 官方影片下載地址
|
10
|
+
*/
|
11
|
+
export declare function getOfficialVideoUrl(urlList: string[] | undefined): string;
|
12
|
+
/**
|
13
|
+
* 從 URL 中提取用戶 ID (sec_uid)
|
14
|
+
* @param userUrl 用戶主頁 URL
|
15
|
+
* @returns 用戶 ID 或 null
|
16
|
+
*/
|
17
|
+
export declare function extractSecUserId(userUrl: string): string | null;
|
18
|
+
/**
|
19
|
+
* 獲取指定用戶的影片列表
|
20
|
+
* @param userUrl 用戶主頁 URL
|
21
|
+
* @param cookie 有效的抖音 Cookie
|
22
|
+
* @param limit 限制獲取的影片數量,0 表示獲取全部
|
23
|
+
* @param options 獲取選項
|
24
|
+
* @returns Promise<UserVideoItem[]> 用戶影片列表
|
25
|
+
*/
|
26
|
+
export declare function fetchUserVideos(userUrl: string, cookie: string, limit?: number, options?: UserVideosOptions): Promise<UserVideoItem[]>;
|