Skip to content

发现页 (explore)

explore() 是可选函数,用于提供分类浏览入口。不实现此函数时,发现页自动跳过该书源。

函数签名

js
async function explore(page, category) → Promise<string[] | ExploreCategory[] | BookItem[] | { type: 'html', html: string }>
参数类型说明
pagenumber页码,从 1 开始
categorystring分类名、分类 URL,或 'GETALL' 表示获取所有分类

返回值

调用场景返回类型说明
category === 'GETALL'string[] | ExploreCategory[]分类数组;推荐返回对象数组以区分同名分类
指定分类名或 URLBookItem[]该分类下的书籍列表
特殊分类(如"设置"){ type: 'html', html: '...' }HTML 交互页面

BookItem 的完整字段规则见 BookItem。发现页元数据字段与搜索页一致。

ExploreCategory 结构如下:

ts
interface ExploreCategory {
  /** 前端显示的分类名称 */
  name: string;
  /** 实际传回 explore(page, category) 的稳定分类值,可为 URL、ID 或筛选参数 */
  url: string;
  /** 可选。移动端分类入口宽度提示,桌面端暂不使用 */
  style?: {
    layout_flexGrow?: number;
    layout_flexBasisPercent?: number; // 1=100%,0.4=40%,0.25=25%
  };
}

为兼容旧书源,GETALL 仍可返回 string[]。如果存在多个同名入口,应返回 { name, url } 对象数组;前端显示 name,加载时传 url,因此同名分类不会互相覆盖。

基本示例

js
async function explore(page, category) {
  // 返回分类列表
  if (category === 'GETALL') {
    return ['玄幻', '仙侠', '都市', '历史', '科幻'];
  }

  // 返回指定分类下的书籍
  legado.log('[explore] category=' + category + ' page=' + page);
  var html = await legado.http.get(BASE + '/category/' + encodeURIComponent(category) + '?page=' + page);
  var doc = legado.dom.parse(html);
  var items = legado.dom.selectAll(doc, '.book-item');
  var books = [];

  for (var i = 0; i < items.length; i++) {
    books.push({
      name: legado.dom.selectText(items[i], '.title'),
      author: legado.dom.selectText(items[i], '.author'),
      bookUrl: legado.dom.selectAttr(items[i], 'a', 'href'),
      coverUrl: legado.dom.selectAttr(items[i], 'img', 'src'),
      kind: category,
      latestChapter: legado.dom.selectText(items[i], '.latest a'),
      latestChapterUrl: legado.dom.selectAttr(items[i], '.latest a', 'href'),
      wordCount: legado.dom.selectText(items[i], '.words'),
      updateTime: legado.dom.selectText(items[i], '.updated'),
      status: legado.dom.selectText(items[i], '.status')
    });
  }

  legado.dom.free(doc);
  return books;
}

同名分类与移动端宽度

旧阅读的发现入口常用 标题::URL::宽度 或 FlexBox JSON 描述分类布局。新书源可以直接返回对象数组:

js
async function explore(page, category) {
  var cats = [
    { name: '畅销榜', url: BASE + '/api/rank?tid=75&rid=1&page={{page}}', style: { layout_flexGrow: 1, layout_flexBasisPercent: 1 } },
    { name: '古代', url: BASE + '/api/rank?tid=3&rid=1&page={{page}}', style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.25 } },
    { name: '古代', url: BASE + '/api/rank?tid=3&rid=2&page={{page}}', style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.25 } }
  ];

  if (category === 'GETALL') {
    return cats;
  }

  var selected = cats.find(function(cat) {
    return cat.url === category || cat.name === category;
  });
  if (!selected) return [];

  var resp = await legado.http.get(selected.url.replace('{{page}}', page));
  // ... 解析逻辑
}

移动端会尽量按 style.layout_flexBasisPercent 还原旧阅读 FlexBox 宽度,例如 1 为整行、0.4 为 40%、0.25 为 25%。桌面端当前忽略这个布局提示,仍按普通标签自然排列。

发现页只返回当前分类页已经提供的元数据;不要为了补齐字数、章节数、状态或更新时间在 explore() 中逐本请求详情页。

JSON API 发现页

js
var CATEGORIES = {
  '玄幻': 1, '仙侠': 2, '都市': 3, '历史': 4
};

async function explore(page, category) {
  if (category === 'GETALL') {
    return Object.keys(CATEGORIES);
  }

  var catId = CATEGORIES[category];
  var resp = await legado.http.get(BASE + '/api/list?cid=' + catId + '&page=' + page);
  var json = JSON.parse(resp);

  return json.data.list.map(function(book) {
    return {
      name: book.title,
      bookUrl: BASE + '/book/' + book.id,
      author: book.author,
      coverUrl: book.cover,
      kind: category,
      latestChapter: book.lastChapter,
      wordCount: book.wordCountText,
      chapterCount: book.chapterCount,
      updateTime: book.updateTime,
      status: book.status
    };
  });
}

排行榜 + 分类混合

js
async function explore(page, category) {
  if (category === 'GETALL') {
    return ['总人气排行', '月排行榜', '周排行榜', '玄幻', '仙侠', '都市'];
  }

  var url;
  switch (category) {
    case '总人气排行': url = BASE + '/top/allvisit/' + page + '.htm'; break;
    case '月排行榜':   url = BASE + '/top/monthvisit/' + page + '.htm'; break;
    case '周排行榜':   url = BASE + '/top/weekvisit/' + page + '.htm'; break;
    default:          url = BASE + '/sort/' + category + '/' + page + '.htm'; break;
  }

  var html = await legado.http.get(url);
  // ... 解析逻辑
}

HTML 交互发现页

explore() 还支持返回 HTML 交互页面,用于实现高级的用户交互(如设置面板、筛选器)。详见 进阶 → HTML 交互发现页

基于 MIT 许可发布