@cloud411716/fancy-webnovel 0.2.9 → 0.2.11
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/package.json
CHANGED
|
@@ -249,6 +249,7 @@ function cleanDesc(raw) {
|
|
|
249
249
|
// ---------------------------------------------------------------------------
|
|
250
250
|
|
|
251
251
|
const args = process.argv.slice(2);
|
|
252
|
+
const PROBE = getArg(args, "--probe") !== null;
|
|
252
253
|
const LOGIN_WAIT = parseInt(getArg(args, "--login-wait") || "0", 10);
|
|
253
254
|
const OUTDIR = getArg(args, "--outdir") || ".";
|
|
254
255
|
const CHANNEL = getArg(args, "--channel") || "1";
|
|
@@ -306,6 +307,69 @@ async function scrapeChannel(ch, type) {
|
|
|
306
307
|
console.log(` ⚠ 页面未挂载 __INITIAL_STATE__,将尝试兜底扫描,结果可能不完整。`);
|
|
307
308
|
}
|
|
308
309
|
|
|
310
|
+
// ─── 调试模式:拦截所有请求,找出真实数据接口 ───
|
|
311
|
+
if (PROBE) {
|
|
312
|
+
const intercepted = [];
|
|
313
|
+
const seen = new Set();
|
|
314
|
+
|
|
315
|
+
// 先注册拦截器,再导航到目标页(避免漏掉 initial 请求)
|
|
316
|
+
context.on("request", req => {
|
|
317
|
+
const url = req.url();
|
|
318
|
+
if (seen.has(url)) return;
|
|
319
|
+
if (/\.(css|woff|jpg|png|ico)/.test(url)) return;
|
|
320
|
+
if (!url.includes("fanqie")) return;
|
|
321
|
+
seen.add(url);
|
|
322
|
+
console.log(`[REQ] ${url}`);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
page.on("response", async (resp) => {
|
|
326
|
+
const url = resp.url();
|
|
327
|
+
const ct = (resp.headers()["content-type"] || "").toLowerCase();
|
|
328
|
+
if (seen.has(url)) return;
|
|
329
|
+
if (!ct.includes("json") && !ct.includes("text") && !url.includes("api")) return;
|
|
330
|
+
if (/\.(css|woff|jpg|png|ico)/.test(url)) return;
|
|
331
|
+
try {
|
|
332
|
+
const body = await resp.text();
|
|
333
|
+
if (!body || body.length < 50) return;
|
|
334
|
+
let parsed;
|
|
335
|
+
try { parsed = JSON.parse(body); } catch { return; }
|
|
336
|
+
const str = JSON.stringify(parsed);
|
|
337
|
+
if (str.includes("bookId") || str.includes("book_name") || str.includes("bookName") || str.includes("authorName")) {
|
|
338
|
+
console.log(`[JSON] ${url}`);
|
|
339
|
+
console.log(` 预览: ${str.slice(0, 300)}`);
|
|
340
|
+
intercepted.push({ url, preview: str.slice(0, 400) });
|
|
341
|
+
}
|
|
342
|
+
} catch {}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
// 直接导航到品类页(不用 waitUntil,避免卡住)
|
|
346
|
+
const cats = await extractCategories(page, ch, type);
|
|
347
|
+
if (!cats.length) {
|
|
348
|
+
await page.goto(`https://fanqienovel.com/rank/${ch}_${type}_${initCatId}`);
|
|
349
|
+
await page.waitForTimeout(3000);
|
|
350
|
+
const moreCats = await extractCategories(page, ch, type);
|
|
351
|
+
if (moreCats.length) {
|
|
352
|
+
console.log(` 发现 ${moreCats.length} 个品类`);
|
|
353
|
+
for (const c of moreCats.slice(0, 3)) {
|
|
354
|
+
console.log(` 探测品类: ${c.name} → ${c.href}`);
|
|
355
|
+
await page.goto(`https://fanqienovel.com${c.href}`);
|
|
356
|
+
await page.waitForTimeout(2000);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
console.log(` 发现 ${cats.length} 个品类`);
|
|
361
|
+
for (const c of cats.slice(0, 3)) {
|
|
362
|
+
console.log(` 探测品类: ${c.name} → ${c.href}`);
|
|
363
|
+
await page.goto(`https://fanqienovel.com${c.href}`);
|
|
364
|
+
await page.waitForTimeout(2000);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
console.log(`\n=== 共拦截到 ${intercepted.length} 个含书籍数据的接口 ===`);
|
|
369
|
+
await browser.close();
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
|
|
309
373
|
// 提取品类菜单
|
|
310
374
|
let categories = await extractCategories(page, ch, type);
|
|
311
375
|
if (!categories.length) {
|