奇书网

https://www.qishuxia.com

zpccool (13551) 1天前 下载:363

小说 小说 免费
奇书网 - 好看的小说大全免费在线阅读和txt下载
二维码导入(APP尚未完成该功能)
// @name        奇书网
// @version     1.1.0
// @uuid        qishuwang
// @author      Ai
// @url         https://www.qishuxia.com
// @type        novel
// @enabled     true
// @tags        小说,免费
// @description 奇书网 - 好看的小说大全免费在线阅读和txt下载

var BASE = 'https://www.qishuxia.com';

var CATEGORIES = [
  { title: '玄幻奇幻', id: 'xuanhuanxiaoshuo' },
  { title: '武侠仙侠', id: 'xiuzhenxiaoshuo' },
  { title: '都市言情', id: 'dushixiaoshuo' },
  { title: '历史军事', id: 'lishixiaoshuo' },
  { title: '科幻灵异', id: 'kehuanxiaoshuo' },
  { title: '网游竞技', id: 'wangyouxiaoshuo' },
  { title: '女生频道', id: 'nvshengxiaoshuo' }
];

function absUrl(url, baseUrl) {
  if (!url) return '';
  if (url.indexOf('http') === 0) return url;
  if (url.indexOf('/') === 0) return BASE + url;
  var base = baseUrl || BASE;
  var lastSlash = base.lastIndexOf('/');
  if (lastSlash <= 7) return base + '/' + url;
  return base.substring(0, lastSlash + 1) + url;
}

// isSearch: 搜索结果 s4=作者, s5=日期; 发现页 s5=作者
function parseBooks(doc, defaultKind, isSearch) {
  var books = [];
  var items = legado.dom.selectAll(doc, 'li');
  var seen = {};
  for (var i = 0; i < items.length; i++) {
    var li = items[i];
    var kind = legado.dom.selectText(li, 'span.s1') || defaultKind || '';
    kind = kind.replace(/^\[|\]$/g, '');
    var aEl = legado.dom.select(li, 'span.s2 a');
    if (!aEl) continue;
    var href = legado.dom.attr(aEl, 'href') || '';
    var name = legado.dom.text(aEl) || '';
    if (!name || !href) continue;
    var author = '';
    if (isSearch) {
      author = legado.dom.selectText(li, 'span.s4') || '';
    } else {
      author = legado.dom.selectText(li, 'span.s5') || legado.dom.selectText(li, 'span.s4') || '';
    }
    var bookUrl = absUrl(href);
    if (!seen[bookUrl]) {
      seen[bookUrl] = true;
      books.push({ name: name, author: author, bookUrl: bookUrl, coverUrl: '', kind: kind, lastChapter: '' });
    }
  }
  return books;
}

function parseBookInfo(html) {
  var result = { name: '', author: '', coverUrl: '', intro: '', kind: '', lastChapter: '' };
  var metas = [
    { key: 'name', pattern: /<meta property="og:novel:book_name" content="([^"]+)"/i },
    { key: 'name', pattern: /<meta property="og:title" content="([^"]+)"/i },
    { key: 'author', pattern: /<meta property="og:novel:author" content="([^"]+)"/i },
    { key: 'coverUrl', pattern: /<meta property="og:image" content="([^"]+)"/i },
    { key: 'intro', pattern: /<meta property="og:description" content="([^"]+)"/i },
    { key: 'kind', pattern: /<meta property="og:novel:category" content="([^"]+)"/i },
    { key: 'lastChapter', pattern: /<meta property="og:novel:latest_chapter_name" content="([^"]+)"/i }
  ];
  for (var i = 0; i < metas.length; i++) {
    var meta = metas[i];
    if (result[meta.key]) continue;
    var match = html.match(meta.pattern);
    if (match && match[1]) result[meta.key] = match[1];
  }
  if (!result.name) result.name = '未知书名';
  if (!result.author) result.author = '未知作者';
  return result;
}

async function explore(page, category) {
  try {
    if (category === 'GETALL' || !category) {
      var names = [];
      for (var i = 0; i < CATEGORIES.length; i++) names.push(CATEGORIES[i].title);
      return names;
    }
    var catId = null;
    for (var j = 0; j < CATEGORIES.length; j++) {
      if (CATEGORIES[j].title === category) { catId = CATEGORIES[j].id; break; }
    }
    if (!catId) return [];
    var pageNum = page || 1;
    var url = BASE + '/' + catId + '/';
    if (pageNum > 1) url = BASE + '/' + catId + '/' + pageNum + '.html';
    var html = await legado.http.get(url);
    var doc = legado.dom.parse(html);
    var books = parseBooks(doc, category, false);
    legado.log('[explore] cat=' + category + ' count=' + books.length);
    return books;
  } catch (e) {
    legado.log('[explore] error: ' + (e.message || 'unknown'));
    return [];
  }
}

async function bookInfo(bookUrl) {
  try {
    var url = absUrl(bookUrl);
    var html = await legado.http.get(url);
    var info = parseBookInfo(html);
    return {
      name: info.name, author: info.author, bookUrl: url, tocUrl: url,
      coverUrl: absUrl(info.coverUrl), intro: info.intro, kind: info.kind, lastChapter: info.lastChapter
    };
  } catch (e) {
    legado.log('[bookInfo] error: ' + (e.message || 'unknown'));
    return { name: '未知书名', author: '未知作者', bookUrl: bookUrl, tocUrl: bookUrl, coverUrl: '', intro: '', kind: '小说', lastChapter: '' };
  }
}

async function chapterList(tocUrl) {
  try {
    var url = absUrl(tocUrl);
    var html = await legado.http.get(url);
    var doc = legado.dom.parse(html);
    var listEl = legado.dom.select(doc, '#section-list');
    var container = listEl || doc;
    var anchors = legado.dom.selectAll(container, 'a');
    var chapters = [];
    var seen = {};
    for (var i = 0; i < anchors.length; i++) {
      var a = anchors[i];
      var href = legado.dom.attr(a, 'href') || '';
      var name = legado.dom.text(a) || '';
      if (!href || !name) continue;
      if (href.indexOf('.html') === -1) continue;
      if (href.indexOf('//') >= 0 && href.indexOf('/book/') === -1) continue;
      var chUrl = absUrl(href, url);
      if (!seen[chUrl]) {
        seen[chUrl] = true;
        chapters.push({ name: name, url: chUrl });
      }
    }
    legado.log('[chapterList] count=' + chapters.length);
    return chapters;
  } catch (e) {
    legado.log('[chapterList] error: ' + (e.message || 'unknown'));
    return [];
  }
}

async function chapterContent(chapterUrl) {
  try {
    var url = absUrl(chapterUrl);
    var html = await legado.http.get(url);
    var doc = legado.dom.parse(html);
    var contentEl = legado.dom.select(doc, '#content');
    if (!contentEl) contentEl = legado.dom.select(doc, '.content');
    if (!contentEl) {
      legado.log('[chapterContent] no content element found');
      return '';
    }
    legado.dom.remove(contentEl, 'script, style');
    var text = legado.dom.text(contentEl);
    text = text
      .replace(/记住网站域名www[^\s]+com/g, '')
      .replace(/天才一秒记住[^\s]+最快更新/g, '')
      .replace(/本章未完[^\n]*/g, '')
      .replace(/请收藏[^\n]*/g, '')
      .replace(/章节报错[^\n]*/g, '')
      .trim();
    legado.log('[chapterContent] len=' + text.length);
    return text;
  } catch (e) {
    legado.log('[chapterContent] error: ' + (e.message || 'unknown'));
    return '';
  }
}

async function search(keyword, page) {
  try {
    if (!keyword) return [];
    var encoded = await legado.urlEncodeCharset(keyword, 'gbk');
    var body = 'searchkey=' + encoded;
    if (page && page > 1) body += '&page=' + page;
    var html = await legado.http.post(
      BASE + '/modules/article/search.php',
      body,
      { 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': BASE + '/' }
    );
    var doc = legado.dom.parse(html);
    var books = parseBooks(doc, '', true);
    legado.log('[search] keyword=' + keyword + ' count=' + books.length);
    return books;
  } catch (e) {
    legado.log('[search] error: ' + (e.message || 'unknown'));
    return [];
  }
}

async function TEST(type) {
  if (type === '__list__') return ['search', 'explore'];
  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 b = await explore(1, '都市言情');
    if (!b || b.length < 1) return { passed: false, message: '发现页为空' };
    return { passed: true, message: '发现页 ' + b.length + ' 条' };
  }
  return { passed: false, message: '未知: ' + type };
}
广告