@cloud411716/fancy-webnovel 0.2.8 → 0.2.10

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloud411716/fancy-webnovel",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -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,58 @@ 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
+ page.on("response", async (resp) => {
316
+ const url = resp.url();
317
+ const ct = resp.headers()["content-type"] || "";
318
+ // 只关心 JSON 响应
319
+ if (!ct.includes("json") && !ct.includes("text")) return;
320
+ // 跳过静态资源
321
+ if (/\.(css|woff|jpg|png|ico)/.test(url)) return;
322
+ try {
323
+ const body = await resp.text();
324
+ if (!body || body.length < 50) return;
325
+ // 尝试解析 JSON
326
+ let parsed;
327
+ try { parsed = JSON.parse(body); } catch { return; }
328
+ // 找含书籍数据的响应
329
+ const str = JSON.stringify(parsed);
330
+ if (str.includes("bookId") || str.includes("book_name") || str.includes("bookName") || str.includes("authorName")) {
331
+ if (!seen.has(url)) {
332
+ seen.add(url);
333
+ intercepted.push({ url, preview: str.slice(0, 400) });
334
+ }
335
+ }
336
+ } catch {}
337
+ });
338
+
339
+ // 触发几个品类页的请求
340
+ const cats = await extractCategories(page, ch, type);
341
+ if (!cats.length) {
342
+ await scrollLoad(page, 2);
343
+ sleep(1000);
344
+ }
345
+ const targets = cats.length ? cats.slice(0, 3) : [{ name: "入口页", href: `/rank/${ch}_${type}_${initCatId}` }];
346
+ for (const c of targets) {
347
+ console.log(` 探测: ${c.name} → ${c.href}`);
348
+ await page.goto(`https://fanqienovel.com${c.href}`, { waitUntil: "networkidle" });
349
+ await page.waitForTimeout(2000);
350
+ }
351
+
352
+ console.log(`\n=== 拦截到的接口 (${intercepted.length}) ===\n`);
353
+ for (const { url, preview } of intercepted) {
354
+ console.log(`URL: ${url}`);
355
+ console.log(`预览: ${preview}`);
356
+ console.log("---");
357
+ }
358
+ await browser.close();
359
+ return null;
360
+ }
361
+
309
362
  // 提取品类菜单
310
363
  let categories = await extractCategories(page, ch, type);
311
364
  if (!categories.length) {
@@ -105,7 +105,8 @@ export const scan = {
105
105
  `2. 分析爆款书籍的题材、卖点、节奏、人设等特征`,
106
106
  `3. 生成扫榜报告(包含:市场趋势、热门题材分析、用户画像、竞争度评估)`,
107
107
  `4. 给出 3-5 个可行的选题方向建议`,
108
- `5. 将分析报告追加写入文件:\n` +
108
+ `5. 先创建空文件(如果不存在),再追加报告内容:\n` +
109
+ ` touch ${topicFile}\n` +
109
110
  ` echo "你的报告内容" >> ${topicFile}\n` +
110
111
  ` (使用 tee -a 或 >> ,不要覆盖现有内容)`,
111
112
  ``,