stnh70 commited on
Commit
3938f5e
·
verified ·
1 Parent(s): 67172ad

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +176 -2
server.js CHANGED
@@ -49,7 +49,7 @@ async function extractFirstIframeSrc(page, domain) {
49
  }
50
  }
51
 
52
- async function getVideoAndSubtitles(finalUrl) {
53
  try {
54
  const response = await fetch(finalUrl);
55
  if (!response.ok) {
@@ -92,10 +92,70 @@ async function getVideoAndSubtitles(finalUrl) {
92
  }
93
  }
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  // 修改 scrapeProvider 函数
97
  // 在 scrapeProvider 函数中添加调试代码
98
- async function scrapeProvider(domain, url, signal) {
99
  if (signal.aborted) throw new Error('Aborted');
100
  console.log(`\n[${domain}] Starting scrape for URL: ${url}`);
101
 
@@ -179,6 +239,120 @@ async function scrapeProvider(domain, url, signal) {
179
  }
180
  }
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  // 修改 handleSpecificTurnstile 函数
183
  async function handleSpecificTurnstile(page, domain) {
184
  try {
 
49
  }
50
  }
51
 
52
+ async function getVideoAndSubtitles_(finalUrl) {
53
  try {
54
  const response = await fetch(finalUrl);
55
  if (!response.ok) {
 
92
  }
93
  }
94
 
95
+ async function getVideoAndSubtitles(url) {
96
+ console.log(`[getVideoAndSubtitles] Processing URL: ${url}`);
97
+
98
+ // 如果是 cloudnestra.com/rcp/ 的URL,直接返回解析结果
99
+ if (url.includes('cloudnestra.com/rcp/')) {
100
+ try {
101
+ const response = await fetch(url);
102
+ const text = await response.text();
103
+
104
+ // 尝试解析JSON
105
+ try {
106
+ const data = JSON.parse(text);
107
+ if (data.file) {
108
+ console.log(`[getVideoAndSubtitles] Found video URL in cloudnestra response:`, data.file);
109
+ return {
110
+ videoFileUrl: data.file,
111
+ subtitleSources: data.subtitles || []
112
+ };
113
+ }
114
+ } catch (e) {
115
+ // 如果不是JSON,尝试查找m3u8链接
116
+ const m3u8Match = text.match(/https?:\/\/[^\s"']+\.m3u8[^\s"']*/);
117
+ if (m3u8Match) {
118
+ console.log(`[getVideoAndSubtitles] Found m3u8 URL in cloudnestra response:`, m3u8Match[0]);
119
+ return {
120
+ videoFileUrl: m3u8Match[0],
121
+ subtitleSources: []
122
+ };
123
+ }
124
+ }
125
+
126
+ throw new Error("No video URL found in cloudnestra response");
127
+ } catch (error) {
128
+ console.error(`[getVideoAndSubtitles] Error fetching cloudnestra response:`, error);
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ // 原有的处理逻辑
134
+ try {
135
+ const response = await fetch(url);
136
+ const html = await response.text();
137
+
138
+ const videoMatch = html.match(/file:\s*["']([^"']+\.m3u8[^"']*)["']/);
139
+ const subtitleMatch = html.match(/tracks:\s*\[\s*{[^}]*}\s*\]/);
140
+
141
+ if (!videoMatch || !videoMatch[1]) {
142
+ throw new Error("HLS URL not found");
143
+ }
144
+
145
+ const videoFileUrl = videoMatch[1];
146
+ const subtitleSources = subtitleMatch ? [JSON.parse(subtitleMatch[0])] : [];
147
+
148
+ return { videoFileUrl, subtitleSources };
149
+ } catch (error) {
150
+ console.error(`[getVideoAndSubtitles] Error processing URL:`, error);
151
+ throw error;
152
+ }
153
+ }
154
+
155
 
156
  // 修改 scrapeProvider 函数
157
  // 在 scrapeProvider 函数中添加调试代码
158
+ async function scrapeProvider_(domain, url, signal) {
159
  if (signal.aborted) throw new Error('Aborted');
160
  console.log(`\n[${domain}] Starting scrape for URL: ${url}`);
161
 
 
239
  }
240
  }
241
 
242
+ async function scrapeProvider(domain, url, signal) {
243
+ if (signal.aborted) throw new Error('Aborted');
244
+ console.log(`\n[${domain}] Starting scrape for URL: ${url}`);
245
+
246
+ let browserInstance = null;
247
+ try {
248
+ browserInstance = await browserPool.get();
249
+ const browser = browserInstance.browser;
250
+
251
+ // 创建初始页面
252
+ const page = await browser.newPage();
253
+
254
+ // 启用请求拦截
255
+ await page.route('**/*', route => {
256
+ const requestUrl = route.request().url();
257
+ console.log(`[${domain}] Request: ${requestUrl}`);
258
+
259
+ // 如果是 cloudnestra.com/rcp/ 的请求,记录响应但不拦截
260
+ if (requestUrl.includes('cloudnestra.com/rcp/')) {
261
+ route.continue().then(response => {
262
+ response.text().then(text => {
263
+ console.log(`[${domain}] Cloudnestra response:`, text);
264
+ // 将响应保存到页面属性中
265
+ page.cloudnestraResponse = text;
266
+ });
267
+ });
268
+ } else {
269
+ route.continue();
270
+ }
271
+ });
272
+
273
+ await page.goto(url, {
274
+ waitUntil: 'networkidle',
275
+ timeout: 60000
276
+ });
277
+
278
+ // 检查是否有Turnstile
279
+ const hasTurnstile = await page.evaluate(() => {
280
+ return document.querySelector('.cf-turnstile') !== null;
281
+ });
282
+ console.log(`[${domain}] Has Turnstile: ${hasTurnstile}`);
283
+
284
+ // 处理Turnstile
285
+ if (hasTurnstile) {
286
+ await handleSpecificTurnstile(page, domain);
287
+ }
288
+
289
+ // 获取第一个iframe的URL
290
+ const firstIframeSrc = await extractFirstIframeSrc(page, domain);
291
+ if (!firstIframeSrc) throw new Error('First iframe not found');
292
+
293
+ // 创建新页面来加载iframe内容
294
+ const iframePage = await browser.newPage();
295
+ await iframePage.goto(firstIframeSrc, {
296
+ waitUntil: 'networkidle',
297
+ timeout: 60000
298
+ });
299
+
300
+ // 处理可能存在的第二个Turnstile
301
+ const iframeHasTurnstile = await iframePage.evaluate(() => {
302
+ return document.querySelector('.cf-turnstile') !== null;
303
+ });
304
+ console.log(`[${domain}] Iframe has Turnstile: ${iframeHasTurnstile}`);
305
+
306
+ if (iframeHasTurnstile) {
307
+ await handleSpecificTurnstile(iframePage, domain);
308
+ }
309
+
310
+ // 获取最终iframe的URL
311
+ const finalIframeSrc = await extractFinalIframeSrc(iframePage, domain);
312
+ if (!finalIframeSrc) throw new Error('Final iframe not found');
313
+
314
+ // 检查是否是 cloudnestra.com/rcp/ 的URL
315
+ if (finalIframeSrc.includes('cloudnestra.com/rcp/')) {
316
+ // 使用保存的响应
317
+ const responseText = page.cloudnestraResponse;
318
+ if (!responseText) throw new Error('No cloudnestra response found');
319
+
320
+ // 解析响应
321
+ try {
322
+ const data = JSON.parse(responseText);
323
+ if (data.file) {
324
+ console.log(`[${domain}] Found video URL in cloudnestra response:`, data.file);
325
+ return {
326
+ source_domain: domain,
327
+ hls_url: data.file,
328
+ subtitles: data.subtitles || [],
329
+ error: null
330
+ };
331
+ }
332
+ throw new Error("No video URL found in cloudnestra response");
333
+ } catch (e) {
334
+ throw new Error("Failed to parse cloudnestra response");
335
+ }
336
+ }
337
+
338
+ // 如果不是 cloudnestra.com/rcp/ 的URL,使用原有的处理方式
339
+ const { videoFileUrl, subtitleSources } = await getVideoAndSubtitles(finalIframeSrc);
340
+ if (!videoFileUrl) throw new Error("HLS URL not found");
341
+
342
+ return { source_domain: domain, hls_url: videoFileUrl, subtitles: subtitleSources, error: null };
343
+
344
+ } catch (error) {
345
+ console.error(`[${domain}] Error in scrapeProvider: ${error.message}`);
346
+ throw error;
347
+ } finally {
348
+ if (browserInstance) {
349
+ console.log(`[${domain}] Releasing browser ${browserInstance.id} back to pool.`);
350
+ await browserPool.release(browserInstance);
351
+ }
352
+ }
353
+ }
354
+
355
+
356
  // 修改 handleSpecificTurnstile 函数
357
  async function handleSpecificTurnstile(page, domain) {
358
  try {