一叶春宵

https://www.yiyechunxiao.com

zpccool (13551) 1天前 下载:579

小说 言情 现代
一叶春宵小说网(含成人内容)
二维码导入(APP尚未完成该功能)
// @name        一叶春宵
// @uuid       yiyechunxiao
// @version     1.0.0
// @author      Ai
// @url         https://www.yiyechunxiao.com
// @type        novel
// @enabled false
// @tags        言情,现代
// @description 一叶春宵小说网(含成人内容)

var BASE = "https://www.yiyechunxiao.com";


// der>
// <main class="container">
//     <section class="chapter">
//         <h1 class="title">第31章</h1>
//         <div class="content">
//             <p>四个女孩鱼贯而出。</p><p>姚乐儿的头发睡得翘起一撮,像个呆毛;姚思思脸颊上还有没擦干的水珠。</p><p>谢小果的头发东倒西歪,肖妙妙则紧紧抱着她的安抚玩偶,眼睛半眯着,显然还没完全开机。</p><p></p>
// 此书源正文尚未修复 他不是  换行分割 他正文是若干p 来分割的


/**
 * 从 /tags/ 页面获取所有标签,返回 { name: tagPath } 映射
 * tagPath 如 '/tag/60/'
 */
async function _fetchTagMap() {
  var html = await legado.http.get(BASE + "/tags/");
  var doc = legado.dom.parse(html);
  var names = legado.dom.selectAllTexts(doc, ".tag-list a");
  var hrefs = legado.dom.selectAllAttrs(doc, ".tag-list a", "href");
  var map = {};
  for (var i = 0; i < names.length; i++) {
    // 去掉名称中的数字和"部"后缀,如 "调教11767 部" → "调教"
    var name = names[i].replace(/[\d\s]*部$/, "").trim();
    if (name && hrefs[i]) {
      map[name] = hrefs[i];
    }
  }
  return map;
}

/**
 * 发现页
 * category === 'GETALL' 时返回标签名数组
 * 否则返回该标签下的书籍列表
 */
async function explore(page, category) {
  legado.log("explore page=" + page + " category=" + category);
  var tagMap = await _fetchTagMap();

  if (!category || category === "GETALL") {
    var cats = [];
    cats.push("热门小说");
    for (var k in tagMap) {
      if (tagMap.hasOwnProperty(k)) {
        cats.push(k);
      }
    }
    legado.log("分类数量: " + cats.length);
    return cats;
  }

  var tagPath = tagMap[category];
  if (category === "热门小说") {
    tagPath = "/rank/hot/";
  } else if (!tagPath) {
    legado.log("未找到分类: " + category);
    return [];
  }

  var url = BASE + tagPath + "?page=" + (page || 1);
  legado.log("请求分类页: " + url);
  var html = await legado.http.get(url);
  var doc = legado.dom.parse(html);

  return _parseNovelList(doc);
}

/**
 * 解析 .novel-list 的书籍列表(分类页格式)
 */
function _parseNovelList(doc) {
  var items = legado.dom.selectAll(doc, ".novel-list a");
  var result = [];
  for (var i = 0; i < items.length; i++) {
    var el = items[i];
    var href = legado.dom.attr(el, "href");
    if (!href || href.indexOf("/book/") < 0) continue;
    var name = legado.dom.selectText(el, "h4");
    var author = legado.dom.selectText(el, "span");
    var coverRel = legado.dom.selectAttr(el, "img", "data-src");
    result.push({
      name: name || "",
      author: author || "",
      bookUrl: BASE + href,
      coverUrl: coverRel ? BASE + coverRel : "",
    });
  }
  return result;
}

/**
 * 书籍详情
 */
async function bookInfo(bookUrl) {
  legado.log("bookInfo: " + bookUrl);
  var html = await legado.http.get(bookUrl);
  var doc = legado.dom.parse(html);

  var name = legado.dom.selectText(doc, "h1");
  // 作者在第一个 dl dd 中
  var ddAll = legado.dom.selectAllTexts(doc, "dl dd");
  var author = ddAll.length > 0 ? ddAll[0] : "";
  // 分类在第三个 dl dd
  var kind = ddAll.length > 2 ? ddAll[2] : "";
  // 最新章节在最后一个 dl dd
  var lastChapter = ddAll.length > 0 ? ddAll[ddAll.length - 1] : "";

  var coverRel = legado.dom.selectAttr(doc, ".cover img", "src");
  // 封面懒加载时用 data-src
  if (!coverRel || coverRel.indexOf("/static/img/thumb") >= 0) {
    coverRel = legado.dom.selectAttr(doc, ".cover img", "data-src");
  }
  var coverUrl = coverRel ? (coverRel.indexOf("http") === 0 ? coverRel : BASE + coverRel) : "";

  var intro = legado.dom.selectText(doc, ".desc");

  // 目录页在 bookUrl + 'list/'
  var tocUrl = bookUrl.replace(/\/$/, "") + "/list/";

  legado.log("bookInfo name=" + name + " author=" + author);
  return {
    name: name || "",
    author: author || "",
    coverUrl: coverUrl,
    intro: (intro || "").trim(),
    kind: kind || "",
    lastChapter: lastChapter || "",
    tocUrl: tocUrl,
  };
}

/**
 * 章节目录(目录在独立的 list/ 页面)
 */
async function chapterList(tocUrl) {
  legado.log("chapterList: " + tocUrl);
  var html = await legado.http.get(tocUrl);
  var doc = legado.dom.parse(html);

  var items = legado.dom.selectAll(doc, ".chapter-list a");
  var hrefs = legado.dom.selectAllAttrs(doc, ".chapter-list a", "href");
  var names = legado.dom.selectAllTexts(doc, ".chapter-list a");

  var chapters = [];
  for (var i = 0; i < names.length; i++) {
    if (!hrefs[i] || hrefs[i].indexOf("/book/") < 0) continue;
    chapters.push({
      name: names[i] || "第" + (i + 1) + "章",
      url: BASE + hrefs[i],
    });
  }
  legado.log("章节数: " + chapters.length);
  return chapters;
}

/**
 * 章节正文
 */
async function chapterContent(chapterUrl) {
  legado.log("chapterContent: " + chapterUrl);
  var html = await legado.http.get(chapterUrl);
  var doc = legado.dom.parse(html);

  // 移除广告节点
  legado.dom.remove(doc, "script, .ad, .tips, .readinline");

  var content = legado.dom.selectText(doc, ".content");
  if (!content) {
    legado.log("正文容器未找到");
    return "";
  }
  // 清理常见噪声
  content = content.replace(/本章未完.*?下一页/g, "");
  content = content.replace(/\u5c0f\u8bf4\u7f51\u7ad9|www\.\S+/gi, "");
  return content.trim();
}

/**
 * 搜索
 */
async function search(keyword, page) {
  legado.log("search: " + keyword + " page=" + page);
  var url = BASE + "/search/?q=" + encodeURIComponent(keyword);
  if (page && page > 1) {
    url += "&page=" + page;
  }
  var html = await legado.http.get(url);
  var doc = legado.dom.parse(html);

  var items = legado.dom.selectAll(doc, ".novel-item");
  var result = [];
  for (var i = 0; i < items.length; i++) {
    var el = items[i];
    var titleEl = legado.dom.select(el, ".title");
    var coverEl = legado.dom.select(el, ".cover img");
    if (!titleEl) continue;
    var name = legado.dom.text(titleEl);
    var href = legado.dom.attr(titleEl, "href");
    var author = legado.dom.selectText(el, ".author");
    var coverRel = coverEl ? legado.dom.attr(coverEl, "data-src") : null;
    if (!href) continue;
    result.push({
      name: name || "",
      author: author || "",
      bookUrl: BASE + href,
      coverUrl: coverRel ? BASE + coverRel : "",
    });
  }
  legado.log("搜索结果: " + result.length);
  return result;
}

/**
 * 内置测试函数
 */
async function TEST(type) {
  if (type === "__list__") return ["search", "explore", "bookInfo", "chapterList", "chapterContent"];
  if (type === "search") {
    var r = await search("系统", 1);
    if (!r || r.length < 1) return { passed: false, message: "搜索无结果" };
    return { passed: true, message: "搜索返回 " + r.length + " 条" };
  }
  if (type === "explore") {
    var cats = await explore(1, "GETALL");
    if (!cats || cats.length < 1) return { passed: false, message: "发现页分类为空" };
    var books = await explore(1, cats[0]);
    if (!books || books.length < 1) return { passed: false, message: "发现页书籍为空" };
    return { passed: true, message: "分类 " + cats.length + " 个,书籍 " + books.length + " 条" };
  }
  if (type === "bookInfo") {
    var r = await bookInfo("https://www.yiyechunxiao.com/book/223125/");
    return { passed: !!r.name, message: "bookInfo name=" + r.name };
  }
  if (type === "chapterList") {
    var r = await chapterList("https://www.yiyechunxiao.com/book/223125/list/");
    return { passed: r.length > 0, message: "chapterList cnt=" + r.length + " first=" + (r[0] ? r[0].name : "N/A") };
  }
  if (type === "chapterContent") {
    var r = await chapterContent("https://www.yiyechunxiao.com/book/223125/2887665.html");
    return { passed: r.length > 100, message: "chapterContent len=" + r.length + " first=" + r.substring(0, 40) };
  }
  return { passed: false, message: "未知测试: " + type };
}
广告