mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-16 21:02:57 +08:00
feat: remove notOperational routes - reading
This commit is contained in:
@@ -144,7 +144,6 @@
|
||||
},
|
||||
],
|
||||
},
|
||||
'zhaishuyuan.com': { _name: '斋书苑', '.': [{ title: '最新章节', docs: 'https://docs.rsshub.app/routes/reading#zhai-shu-yuan', source: ['/book/:id', '/read/:id'], target: '/novel/zhaishuyuan/:id' }] },
|
||||
'hbut.edu.cn': {
|
||||
_name: '湖北工业大学',
|
||||
www: [
|
||||
|
||||
@@ -133,9 +133,6 @@ const calculateValue = () => {
|
||||
bupt: {
|
||||
portal_cookie: envs.BUPT_PORTAL_COOKIE,
|
||||
},
|
||||
chuiniu: {
|
||||
member: envs.CHUINIU_MEMBER,
|
||||
},
|
||||
civitai: {
|
||||
cookie: envs.CIVITAI_COOKIE,
|
||||
},
|
||||
|
||||
@@ -441,17 +441,6 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
'zhaishuyuan.com': {
|
||||
_name: '斋书苑',
|
||||
'.': [
|
||||
{
|
||||
title: '最新章节',
|
||||
docs: 'https://docs.rsshub.app/routes/reading#zhai-shu-yuan',
|
||||
source: ['/book/:id', '/read/:id'],
|
||||
target: '/novel/zhaishuyuan/:id',
|
||||
},
|
||||
],
|
||||
},
|
||||
'hbut.edu.cn': {
|
||||
_name: '湖北工业大学',
|
||||
www: [
|
||||
|
||||
@@ -120,9 +120,6 @@ router.get('/miui/:device/:type?/:region?', lazyloadRouteHandler('./routes/mi/mi
|
||||
// 纵横
|
||||
router.get('/zongheng/chapter/:id', lazyloadRouteHandler('./routes/zongheng/chapter'));
|
||||
|
||||
// 刺猬猫
|
||||
router.get('/ciweimao/chapter/:id', lazyloadRouteHandler('./routes/ciweimao/chapter'));
|
||||
|
||||
// 维基百科 Wikipedia
|
||||
router.get('/wikipedia/mainland', lazyloadRouteHandler('./routes/wikipedia/mainland'));
|
||||
|
||||
@@ -159,10 +156,6 @@ router.get('/mafengwo/ziyouxing/:code', lazyloadRouteHandler('./routes/mafengwo/
|
||||
// router.get('/novel/biquge/:id', lazyloadRouteHandler('./routes/novel/biquge'));
|
||||
// router.get('/novel/biqugeinfo/:id/:limit?', lazyloadRouteHandler('./routes/novel/biqugeinfo'));
|
||||
router.get('/novel/uukanshu/:uid', lazyloadRouteHandler('./routes/novel/uukanshu'));
|
||||
router.get('/novel/wenxuemi/:id1/:id2', lazyloadRouteHandler('./routes/novel/wenxuemi'));
|
||||
router.get('/novel/booksky/:id', lazyloadRouteHandler('./routes/novel/booksky'));
|
||||
router.get('/novel/ptwxz/:id1/:id2', lazyloadRouteHandler('./routes/novel/ptwxz'));
|
||||
router.get('/novel/zhaishuyuan/:id', lazyloadRouteHandler('./routes/novel/zhaishuyuan'));
|
||||
|
||||
// 中国气象网
|
||||
router.get('/weatheralarm/:province?', lazyloadRouteHandler('./routes/weatheralarm'));
|
||||
@@ -936,10 +929,6 @@ router.get('/cfan/news', lazyloadRouteHandler('./routes/cfan/news'));
|
||||
// engadget
|
||||
router.get('/engadget/:lang?', lazyloadRouteHandler('./routes/engadget/home'));
|
||||
|
||||
// 吹牛部落
|
||||
router.get('/chuiniu/column/:id', lazyloadRouteHandler('./routes/chuiniu/column'));
|
||||
router.get('/chuiniu/column_list', lazyloadRouteHandler('./routes/chuiniu/column_list'));
|
||||
|
||||
// leemeng
|
||||
router.get('/leemeng', lazyloadRouteHandler('./routes/blogs/leemeng'));
|
||||
|
||||
@@ -1139,14 +1128,6 @@ router.get('/lastfm/top/:country?', lazyloadRouteHandler('./routes/lastfm/top'))
|
||||
router.get('/piapro/user/:pid', lazyloadRouteHandler('./routes/piapro/user'));
|
||||
router.get('/piapro/public/:type/:tag?/:category?', lazyloadRouteHandler('./routes/piapro/public'));
|
||||
|
||||
// 第一版主
|
||||
router.get('/novel/d1bz/:category/:id', lazyloadRouteHandler('./routes/d1bz/novel'));
|
||||
|
||||
// 爱下电子书
|
||||
router.get('/axdzs/:novel', lazyloadRouteHandler('./routes/novel/axdzs'));
|
||||
// deprecated
|
||||
router.get('/axdzs/:id1/:id2', lazyloadRouteHandler('./routes/novel/axdzs'));
|
||||
|
||||
// HackerOne
|
||||
router.get('/hackerone/hacktivity', lazyloadRouteHandler('./routes/hackerone/hacktivity'));
|
||||
router.get('/hackerone/search/:search', lazyloadRouteHandler('./routes/hackerone/search'));
|
||||
@@ -1162,9 +1143,6 @@ router.get('/p-articles/contributors/:author', lazyloadRouteHandler('./routes/p-
|
||||
router.get('/haohaozhu/whole-house/:keyword?', lazyloadRouteHandler('./routes/haohaozhu/whole-house'));
|
||||
router.get('/haohaozhu/discover/:keyword?', lazyloadRouteHandler('./routes/haohaozhu/discover'));
|
||||
|
||||
// 稻草人书屋
|
||||
router.get('/dcrsw/:name/:count?', lazyloadRouteHandler('./routes/novel/dcrsw'));
|
||||
|
||||
// 魔法纪录
|
||||
router.get('/magireco/announcements', lazyloadRouteHandler('./routes/magireco/announcements'));
|
||||
router.get('/magireco/event_banner', lazyloadRouteHandler('./routes/magireco/event_banner'));
|
||||
@@ -1315,10 +1293,6 @@ router.get('/umass/amherst/ipostories', lazyloadRouteHandler('./routes/umass/amh
|
||||
router.get('/kuai', lazyloadRouteHandler('./routes/kuai/index'));
|
||||
router.get('/kuai/:id', lazyloadRouteHandler('./routes/kuai/id'));
|
||||
|
||||
// 生物帮
|
||||
router.get('/biobio/:id', lazyloadRouteHandler('./routes/biobio/index'));
|
||||
router.get('/biobio/:column/:id', lazyloadRouteHandler('./routes/biobio/others'));
|
||||
|
||||
// 199it
|
||||
router.get('/199it', lazyloadRouteHandler('./routes/199it/index'));
|
||||
router.get('/199it/category/:caty', lazyloadRouteHandler('./routes/199it/category'));
|
||||
@@ -1343,9 +1317,6 @@ router.get('/stork/keyword/:trackID/:displayKey', lazyloadRouteHandler('./routes
|
||||
// arXiv
|
||||
router.get('/arxiv/:query', lazyloadRouteHandler('./routes/arxiv/query'));
|
||||
|
||||
// 生物谷
|
||||
router.get('/shengwugu/:uid?', lazyloadRouteHandler('./routes/shengwugu/index'));
|
||||
|
||||
// 环球律师事务所文章
|
||||
router.get('/law/hq', lazyloadRouteHandler('./routes/law/hq'));
|
||||
|
||||
@@ -1597,9 +1568,6 @@ router.get('/manictime/releases', lazyloadRouteHandler('./routes/manictime/relea
|
||||
// Deutsche Welle 德国之声
|
||||
router.get('/dw/:lang?/:caty?', lazyloadRouteHandler('./routes/dw/index'));
|
||||
|
||||
// Amazon
|
||||
router.get('/amazon/ku/:type?', lazyloadRouteHandler('./routes/amazon/ku'));
|
||||
|
||||
// Citavi 中文网站论坛
|
||||
router.get('/citavi/:caty?', lazyloadRouteHandler('./routes/citavi/index'));
|
||||
|
||||
@@ -1875,9 +1843,6 @@ router.get('/furaffinity/favorites/:username/:nsfw?', lazyloadRouteHandler('./ro
|
||||
router.get('/furaffinity/submission_comments/:id', lazyloadRouteHandler('./routes/furaffinity/submission_comments'));
|
||||
router.get('/furaffinity/journal_comments/:id', lazyloadRouteHandler('./routes/furaffinity/journal_comments'));
|
||||
|
||||
// 博客来
|
||||
router.get('/bookscomtw/newbooks/:category', lazyloadRouteHandler('./routes/bookscomtw/newbooks'));
|
||||
|
||||
// Trakt.tv
|
||||
router.get('/trakt/collection/:username/:type?', lazyloadRouteHandler('./routes/trakt/collection'));
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const config = {
|
||||
this: '2037295071',
|
||||
back: '2330861071',
|
||||
next: '2037296071',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type || 'this';
|
||||
|
||||
const node = config[type];
|
||||
if (!node) {
|
||||
throw Error('Bad type. See <a href="https://docs.rsshub.app/routes/reading#kindle-unlimited-hui-yuan-xian-shi-mian-fei-du-shu-dan">docs</a>');
|
||||
}
|
||||
|
||||
const rootUrl = `https://www.amazon.cn/b?node=${node}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: rootUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const list = $('.apb-browse-searchresults-product .a-spacing-top-small a')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
link: 'https://www.amazon.cn' + item.attr('href'),
|
||||
title: item.text().trim(),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
item.author = content('span.author').text();
|
||||
item.description = content('#ebooks-img-canvas').html() + content('#detailBullets_feature_div').html();
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `KU会员限时免费读 - ${$('title').text().split('-')[1]}`,
|
||||
link: rootUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = `http://www.bio1000.com/${ctx.params.id}`;
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('.excerpt-1').get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.slice(0, 5).map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const time = $('.meta').text();
|
||||
const title = $('header h2 a').attr('title');
|
||||
const partial = $('header h2 a').attr('href');
|
||||
const address = partial;
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const get = cheerio.load(res.data);
|
||||
const contents = get('.article-content').html();
|
||||
const single = {
|
||||
title,
|
||||
pubDate: time,
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: '生物帮',
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,45 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
const { isValidHost } = require('@/utils/valid-host');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
if (!isValidHost(ctx.params.column)) {
|
||||
throw Error('Invalid column');
|
||||
}
|
||||
|
||||
const url = `http://${ctx.params.column}.bio1000.com/${ctx.params.id}`;
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('.excerpt-1').get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.slice(0, 5).map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const time = $('.meta').text();
|
||||
const title = $('header h2 a').attr('title');
|
||||
const partial = $('header h2 a').attr('href');
|
||||
const address = partial;
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const get = cheerio.load(res.data);
|
||||
const contents = get('.article-content').html();
|
||||
const single = {
|
||||
title,
|
||||
pubDate: time,
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: '生物帮',
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
module.exports = async (ctx) => {
|
||||
const url = `https://www.books.com.tw/web/${ctx.params.category}/`;
|
||||
const { data } = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
const $ = cheerio.load(data);
|
||||
const list = $('div.mod_a div.wrap div.item');
|
||||
const items = list
|
||||
.map((i, item) => {
|
||||
item = $(item);
|
||||
const title = item.find('h4').text().trim();
|
||||
let imgLink = item.find('a img.cover').attr('src').trim();
|
||||
imgLink = imgLink.slice(imgLink.indexOf('https', 1), imgLink.indexOf('.jpg') + 4);
|
||||
const link = item.find('a').attr('href');
|
||||
const desc = item.find('div.txt_cont p').text().trim();
|
||||
const author = item.find('li.info>a').text();
|
||||
const publisher = item.find('li.info span>a').text();
|
||||
const pubInfo = item.find('li.info').text();
|
||||
let price = item.find('ul.price li.set2 strong');
|
||||
price = price.length === 1 ? parseInt(price.text().trim()) : parseInt(price.eq(0).text() > 10 ? ((price.eq(1).text() * 100) / price.eq(0).text()).toFixed() : ((price.eq(1).text() * 10) / price.eq(0).text()).toFixed());
|
||||
return {
|
||||
title,
|
||||
description: `${desc}<br><img src="${imgLink}" alt="${title}"><br>NT$${price}元<br>${pubInfo}`,
|
||||
link: link.slice(0, link.indexOf('?')),
|
||||
author: `${author} / ${publisher}`,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: URL,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const config = require('@/config').value;
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'http://chuiniu.duanshu.com';
|
||||
const column_id = ctx.params.id;
|
||||
|
||||
let response = await got({
|
||||
method: 'get',
|
||||
url: 'http://oss-web.duanshu.com/shop/chuiniu-duanshu-com/config.json',
|
||||
headers: {
|
||||
Origin: url,
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
const shop_id = response.data.shop_id;
|
||||
|
||||
response = await got({
|
||||
method: 'get',
|
||||
url: `http://api.duanshu.com/h5/content/free/column/detail/${column_id}?shop_id=${shop_id}`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
'x-platform': 'h5',
|
||||
},
|
||||
});
|
||||
const title = response.data.response.data.title;
|
||||
const description = response.data.response.data.brief;
|
||||
|
||||
response = await got({
|
||||
method: 'get',
|
||||
url: `http://api.duanshu.com/h5/content/column/contents?page=1&count=10&column_id=${column_id}&shop_id=${shop_id}`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
const list = response.data.response.data;
|
||||
|
||||
const out = await Promise.all(
|
||||
list.map(async (item) => {
|
||||
const title = item.title;
|
||||
const brief = item.brief;
|
||||
const up_time = item.up_time;
|
||||
const content_id = item.content_id;
|
||||
const item_link = `http://chuiniu.duanshu.com/#/brief/article/${content_id}`;
|
||||
|
||||
const cache = await ctx.cache.get(item_link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const member = config.chuiniu.member;
|
||||
let content;
|
||||
if (member === undefined) {
|
||||
content = brief + '<br>...<br>正文内容需会员登录后查看';
|
||||
} else {
|
||||
try {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `http://api.duanshu.com/h5/content/detail/${content_id}?shop_id=${shop_id}`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
'x-member': member,
|
||||
},
|
||||
});
|
||||
content = response.data.response.data.content;
|
||||
} catch (error) {
|
||||
content = brief + '<br>...<br>正文内容需会员登录后查看';
|
||||
}
|
||||
}
|
||||
|
||||
const single = {
|
||||
pubDate: new Date(up_time).toUTCString(),
|
||||
link: item_link,
|
||||
title,
|
||||
description: content,
|
||||
};
|
||||
|
||||
ctx.cache.set(item_link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
description,
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = 'http://chuiniu.duanshu.com/#/list/column';
|
||||
|
||||
let response = await got({
|
||||
method: 'get',
|
||||
url: 'http://api.duanshu.com/fairy/api/v1/shop/identifier/',
|
||||
headers: {
|
||||
Origin: url,
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
const shop_id = response.data.shop_id;
|
||||
|
||||
response = await got({
|
||||
method: 'get',
|
||||
url: `http://api.duanshu.com/h5/content/column/lists?page=1&count=12&shop_id=${shop_id}`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
const list = response.data.response.data;
|
||||
|
||||
const out = list.map((item) => ({
|
||||
link: `http://chuiniu.duanshu.com/#/brief/column/${item.column_id}`,
|
||||
title: item.title,
|
||||
description: item.brief,
|
||||
}));
|
||||
|
||||
ctx.state.data = {
|
||||
title: '吹牛部落专栏列表',
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const selector = cheerio.load((await got.get(`https://www.ciweimao.com/book/${id}`)).data);
|
||||
const name = selector('.book-info h3.title').text();
|
||||
const description = selector('.book-intro').html();
|
||||
|
||||
const response = await got({
|
||||
method: 'post',
|
||||
url: `https://www.ciweimao.com/chapter/get_chapter_list_in_chapter_detail`,
|
||||
form: {
|
||||
book_id: id,
|
||||
chapter_id: 0,
|
||||
orderby: 0,
|
||||
},
|
||||
});
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const item = $('.book-chapter-box>ul>li>a')
|
||||
.map((index, ele) => ({
|
||||
title: $(ele).text(),
|
||||
link: $(ele).attr('href'),
|
||||
}))
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: `刺猬猫 ${name}`,
|
||||
link: `http://www.ciweimao.com/book/${id}`,
|
||||
description,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -1,72 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
// function changeStr(str, index, changeStr) {
|
||||
// return str.substr(0, index) + changeStr + str.substr(index + changeStr.length);
|
||||
// }
|
||||
//
|
||||
// function find(str, cha, num) {
|
||||
// let x = str.indexOf(cha);
|
||||
// for (let i = 0; i < num; i++) {
|
||||
// x = str.indexOf(cha, x + 1);
|
||||
// }
|
||||
// return x;
|
||||
// }
|
||||
const gbk2utf8 = (s) => iconv.decode(s, 'gbk');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category.toLowerCase();
|
||||
const id = ctx.params.id.toLowerCase();
|
||||
const baseUrl = 'http://www.dybz9.net';
|
||||
const novelUrl = `${baseUrl}/${category}/${id}/`;
|
||||
|
||||
const response = await got.get(novelUrl, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
// const response = await got.get(novelUrl);
|
||||
|
||||
const $ = cheerio.load(gbk2utf8(new Buffer.from(response.data)));
|
||||
|
||||
const lists = $('.container .chapter-list .bd ul li').slice(0, 3);
|
||||
const chapter_item = lists
|
||||
.find('a')
|
||||
.map((_, e) => ({
|
||||
title: e.children[0].data,
|
||||
link: baseUrl + e.attribs.href,
|
||||
}))
|
||||
.get();
|
||||
const title = chapter_item.title;
|
||||
|
||||
const items = await Promise.all(
|
||||
chapter_item.map(async (item) => {
|
||||
const cache = await ctx.cache.get(item.link);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
|
||||
const response = await got.get(item.link, {
|
||||
responseType: 'buffer',
|
||||
});
|
||||
|
||||
const responseHtml = iconv.decode(response.data, 'GBK');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
|
||||
const description = $('.page-content').html();
|
||||
|
||||
const single = {
|
||||
title: item.title,
|
||||
description,
|
||||
link: item.link,
|
||||
};
|
||||
ctx.cache.set(item.link, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: novelUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const baseUrl = 'https://www.aixdzs.com';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
if (ctx.params.id2) {
|
||||
const redirect = await got.head(`https://read.aixdzs.com/${ctx.params.id1}/${ctx.params.id2}/`, { followRedirect: false });
|
||||
const redirectUrl = redirect.headers.location;
|
||||
const novel = redirectUrl.substring(1 + redirectUrl.lastIndexOf('/'));
|
||||
|
||||
ctx.status = 301;
|
||||
ctx.redirect(`/axdzs/${novel}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const novel = ctx.params.novel;
|
||||
const novelUrl = `${baseUrl}/novel/${novel}/`;
|
||||
const response = await got.get(novelUrl);
|
||||
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data);
|
||||
|
||||
const title = $('h1').text();
|
||||
const description = $('meta[name="description"]').attr('content');
|
||||
const lastChapter = $('.chapter').last().children();
|
||||
const secondChapter = $('.chapter').last().prev().children();
|
||||
let lastChapterUrl = lastChapter.attr('href');
|
||||
let secondChapterUrl = secondChapter.attr('href');
|
||||
if (lastChapterUrl.startsWith('/')) {
|
||||
lastChapterUrl = baseUrl + lastChapterUrl;
|
||||
secondChapterUrl = baseUrl + secondChapterUrl;
|
||||
}
|
||||
const lastChapterContent = await ctx.cache.tryGet(lastChapterUrl, async () => {
|
||||
const res = await got.get(lastChapterUrl);
|
||||
const $ = cheerio.load(res.data, { decodeEntities: false });
|
||||
return $('.content').html();
|
||||
});
|
||||
// 以下需要判断最新章节是否已填充内容
|
||||
let chapterTitle, chapterUrl, chapterContent;
|
||||
// 判断新章节内是否存在无内容的提示信息,如存在则请求上一章节数据
|
||||
if (lastChapterContent.indexOf('鍦ㄦ洿鏂颁腑锛岃绋嶅悗鍒锋') === -1) {
|
||||
chapterTitle = lastChapter.text();
|
||||
chapterUrl = lastChapterUrl;
|
||||
chapterContent = lastChapterContent;
|
||||
} else {
|
||||
chapterTitle = secondChapter.text();
|
||||
chapterUrl = secondChapterUrl;
|
||||
chapterContent = await ctx.cache.tryGet(secondChapterUrl, async () => {
|
||||
const secondChapter = await got.get(secondChapterUrl);
|
||||
const $ = cheerio.load(secondChapter.data, { decodeEntities: false });
|
||||
return $('.content').html();
|
||||
});
|
||||
}
|
||||
ctx.state.data = {
|
||||
title: `爱下电子书-${title}`,
|
||||
description,
|
||||
link: novelUrl,
|
||||
item: [
|
||||
{
|
||||
title: chapterTitle,
|
||||
link: chapterUrl,
|
||||
description: chapterContent,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
const baseUrl = 'http://booksky.so/BookDetail.aspx?Level=1&bid=';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `${baseUrl}${id}`,
|
||||
headers: {
|
||||
Host: 'booksky.so',
|
||||
Referer: 'http://booksky.so/',
|
||||
},
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const responseHtml = iconv.decode(response.data, 'GBK');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
|
||||
const list = $('tr[class=b]').attr('height', '25');
|
||||
|
||||
const title = $('font').attr('color', 'red').text();
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: `${baseUrl}${id}`,
|
||||
description: '',
|
||||
item:
|
||||
list &&
|
||||
list
|
||||
.map((index, item) => {
|
||||
item = $(item);
|
||||
return {
|
||||
title: item.find('.s').text(),
|
||||
description: item.find('.t').eq(1).text(),
|
||||
pubDate: new Date(item.find('.t').eq(2).text()).toUTCString(),
|
||||
link: `http://booksky.so/${item.find('.s').children('a').attr('href')}`,
|
||||
};
|
||||
})
|
||||
.get(),
|
||||
};
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const baseUrl = 'https://www.daocaorenshuwu.com';
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const name = ctx.params.name;
|
||||
const count = ctx.params.count || 3;
|
||||
const novelUrl = `${baseUrl}/book/${name}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: novelUrl,
|
||||
});
|
||||
|
||||
const data = response.data;
|
||||
const $ = cheerio.load(data);
|
||||
|
||||
const title = $('h1.book-name').children().text();
|
||||
const description = $('div.book-detail').text();
|
||||
const chapters = $('.col-md-6').slice(0, count).get();
|
||||
const results = await Promise.all(
|
||||
chapters.map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
|
||||
const chapterTitle = $('a').text();
|
||||
const chapterUrl = 'https:' + $('a').attr('href');
|
||||
const chapterContent = await ctx.cache.tryGet(chapterUrl, async () => {
|
||||
let result = '';
|
||||
let temp = chapterUrl;
|
||||
while (temp !== '') {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const chapter = await got.get(temp);
|
||||
const $ = cheerio.load(chapter.data);
|
||||
$('div.cont-text > script').remove();
|
||||
result += $('div.cont-text').html();
|
||||
// 如果有下一页则访问下一页
|
||||
if ($('a:contains("下一页")').length > 0) {
|
||||
temp = baseUrl + $('a:contains("下一页")').last().attr('href');
|
||||
} else {
|
||||
temp = '';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return Promise.resolve({
|
||||
title: chapterTitle,
|
||||
link: chapterUrl,
|
||||
description: chapterContent,
|
||||
});
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: `稻草人书屋-${title}`,
|
||||
description,
|
||||
link: novelUrl,
|
||||
item: results,
|
||||
};
|
||||
};
|
||||
@@ -1,76 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
const baseUrl = 'https://www.ptwxz.com/bookinfo/';
|
||||
const timezone = require('@/utils/timezone');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
// 获取小说的最新章节列表
|
||||
module.exports = async (ctx) => {
|
||||
// 小说id
|
||||
const id1 = ctx.params.id1;
|
||||
const id2 = ctx.params.id2;
|
||||
const id = id1 + '/' + id2;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `${baseUrl}${id}.html`,
|
||||
headers: {
|
||||
Referer: `${baseUrl}${id}.html`,
|
||||
},
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const responseHtml = iconv.decode(response.data, 'gbk');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
|
||||
const title = $('span>h1').text();
|
||||
|
||||
const chapter_item = $('#content li a')
|
||||
.map((_, item) => {
|
||||
item = $(item);
|
||||
const date = item.attr('title').match(/更新时间:(.*)/)[1]; // "10-04 00:17"
|
||||
return {
|
||||
title: item.text(),
|
||||
link: item.attr('href'),
|
||||
pubDate: timezone(parseDate(date, 'MM-DD HH:mm'), +8),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
const items = await Promise.all(
|
||||
chapter_item.map((item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://www.ptwxz.com/${item.link}`,
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const responseHtml = iconv.decode(response.data, 'GBK');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
// remove all unwanted elements
|
||||
// TODO: cleaner solution to rip text from body
|
||||
$('div').remove();
|
||||
$('h1').remove();
|
||||
$('table').remove();
|
||||
$('center').remove();
|
||||
$('table').remove();
|
||||
$('script').remove();
|
||||
const description = $('body').html();
|
||||
const single = {
|
||||
title: item.title,
|
||||
description,
|
||||
link: item.link,
|
||||
pubDate: item.pubDate,
|
||||
};
|
||||
return single;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: `${baseUrl}${id}.html`,
|
||||
description: '',
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
const mbaseUrl = 'https://m.wenxuemi.com/files/article/html';
|
||||
const baseUrl = 'https://www.wenxuemi.com';
|
||||
|
||||
// 获取小说的最新章节列表
|
||||
module.exports = async (ctx) => {
|
||||
const id1 = ctx.params.id1; // 小说id
|
||||
const id2 = ctx.params.id2;
|
||||
const id = '/' + id1 + '/' + id2;
|
||||
const got_ins = got.extend({
|
||||
headers: {
|
||||
Referer: `${mbaseUrl}${id}/`,
|
||||
},
|
||||
responseType: 'buffer',
|
||||
});
|
||||
const response = await got_ins.get(`${mbaseUrl}${id}/`);
|
||||
const responseHtml = iconv.decode(response.data, 'GBK');
|
||||
const $ = cheerio.load(responseHtml);
|
||||
|
||||
const title = $('h2', '.block_txt2').find('a').text();
|
||||
const description = $('.intro_info').text();
|
||||
const cover_url = $('img', '.block_img2').attr('src');
|
||||
const list = $('li', '.chapter').slice(0, 5);
|
||||
|
||||
const resultItems = await Promise.all(
|
||||
list.toArray().map(async (item) => {
|
||||
const $item = $(item);
|
||||
|
||||
const link = baseUrl + $item.find('a').attr('href');
|
||||
let resultItem = {};
|
||||
const value = await ctx.cache.get(link);
|
||||
if (value) {
|
||||
resultItem = JSON.parse(value);
|
||||
} else {
|
||||
const articleHtml = await got_ins.get(link);
|
||||
const article = iconv.decode(articleHtml.data, 'GBK');
|
||||
const $1 = cheerio.load(article);
|
||||
const res = $1('div#content');
|
||||
|
||||
resultItem = {
|
||||
title: $item.text(),
|
||||
description: res.html(),
|
||||
link,
|
||||
};
|
||||
if (res.text().includes('正在手打中') === false) {
|
||||
ctx.cache.set(link, JSON.stringify(resultItem));
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(resultItem);
|
||||
})
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: `${baseUrl}/files/article/html${id}/`,
|
||||
image: cover_url,
|
||||
description,
|
||||
item: resultItems,
|
||||
};
|
||||
};
|
||||
@@ -1,84 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const iconv = require('iconv-lite');
|
||||
|
||||
const encodeMap = {
|
||||
$$$: '7',
|
||||
$$$$: 'f',
|
||||
$$$_: 'e',
|
||||
$$_: '6',
|
||||
$$_$: 'd',
|
||||
$$__: 'c',
|
||||
$_$: '5',
|
||||
$_$$: 'b',
|
||||
$_$_: 'a',
|
||||
$__: '4',
|
||||
$__$: '9',
|
||||
$___: '8',
|
||||
_: 'u',
|
||||
_$$: '3',
|
||||
_$_: '2',
|
||||
__$: '1',
|
||||
___: '0',
|
||||
};
|
||||
const tokenPattern = /[A-Z]\.([$_]+)|(\/?\\+)/g;
|
||||
const contentPattern = /\\74\\160\\76[0-9a-fu/\\]+?\\74\/\\160\\76/g;
|
||||
const regex16 = /\\u([\d\w]{4})/gi;
|
||||
const regex8 = /\\([\d]{1,4})/gi;
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const url = 'https://www.zhaishuyuan.com';
|
||||
const link = `${url}/book/${id}`;
|
||||
let extendedGot = got.extend({ headers: { Referer: url }, responseType: 'buffer' });
|
||||
const response = await extendedGot.get(link);
|
||||
const html = iconv.decode(response.data, 'gb2312');
|
||||
const $ = cheerio.load(html);
|
||||
const title = $('.booktitle > h1').text();
|
||||
const description = $('#bookintro > p').text();
|
||||
const image = $('#bookimg > img').attr('src');
|
||||
const list = $('#newlist > ul > li')
|
||||
.find('a')
|
||||
.map((_, { attribs: { title, href } }) => ({ title, link: `${url}${href}` }))
|
||||
.get();
|
||||
extendedGot = got.extend({ headers: { Referer: link }, responseType: 'buffer' });
|
||||
const item = await Promise.all(
|
||||
list.map(({ title, link }) =>
|
||||
ctx.cache.tryGet(link, async () => {
|
||||
const response = await extendedGot.get(link);
|
||||
const html = iconv.decode(response.data, 'gb2312');
|
||||
const $ = cheerio.load(html);
|
||||
const content = $('#content');
|
||||
|
||||
const encoded = $('#content > div');
|
||||
if (encoded) {
|
||||
// 提取编码后的正文内容进行复原
|
||||
const rawText = html;
|
||||
let rawContent = '';
|
||||
for (const match of rawText.matchAll(tokenPattern)) {
|
||||
if (match[1] in encodeMap) {
|
||||
rawContent += encodeMap[match[1]];
|
||||
}
|
||||
if (match[2]) {
|
||||
rawContent += match[2].replace('\\\\\\\\', '\\').replace('\\\\', '\\');
|
||||
}
|
||||
}
|
||||
const decodedContentArr = [];
|
||||
for (const contentPar of rawContent.matchAll(contentPattern)) {
|
||||
const decodedStr = contentPar[0].replace(regex16, (match, grp) => String.fromCharCode(parseInt(grp, 16))).replace(regex8, (match, grp) => String.fromCharCode(parseInt(grp, 8)));
|
||||
decodedContentArr.push(decodedStr);
|
||||
}
|
||||
encoded.before(decodedContentArr);
|
||||
encoded.remove();
|
||||
}
|
||||
|
||||
const description = content.html();
|
||||
const spanList = $('.title > span');
|
||||
const author = spanList.eq(0).find('a').text();
|
||||
const pubDate = spanList.eq(2).text();
|
||||
return { title, link, description, author, pubDate };
|
||||
})
|
||||
)
|
||||
);
|
||||
ctx.state.data = { title, link, description, image, item };
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
const cheerio = require('cheerio');
|
||||
const got = require('@/utils/got');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const url = `http://news.bioon.com/${ctx.params.uid}`;
|
||||
|
||||
const res = await got.get(url);
|
||||
const $ = cheerio.load(res.data);
|
||||
const list = $('.cntx').get();
|
||||
|
||||
const out = await Promise.all(
|
||||
list.slice(0, 3).map(async (item) => {
|
||||
const $ = cheerio.load(item);
|
||||
const title = $('.cntx h4 a').text();
|
||||
const partial = $('.cntx h4 a').attr('href');
|
||||
const address = partial;
|
||||
const time = $('.fl huise').text();
|
||||
const cache = await ctx.cache.get(address);
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
}
|
||||
const res = await got.get(address);
|
||||
const get = cheerio.load(res.data);
|
||||
const contents = get('.text3').html();
|
||||
const single = {
|
||||
title,
|
||||
pubDate: time,
|
||||
description: contents,
|
||||
link: address,
|
||||
guid: address,
|
||||
};
|
||||
ctx.cache.set(address, JSON.stringify(single));
|
||||
return Promise.resolve(single);
|
||||
})
|
||||
);
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: url,
|
||||
item: out,
|
||||
};
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const limit = parseInt(ctx.query.limit) || 5;
|
||||
const work_url = `https://kakuyomu.jp/works/${id}`;
|
||||
const $ = cheerio.load(await get(work_url));
|
||||
|
||||
const work_title = $('#workTitle').text();
|
||||
const introduction = $('#introduction').text();
|
||||
|
||||
const episode_list = $('a.widget-toc-episode-episodeTitle')
|
||||
.map((_, episode) => {
|
||||
const $_episode = $(episode);
|
||||
return {
|
||||
title: $_episode.find('span').text(),
|
||||
link: $_episode.attr('href'),
|
||||
pubDate: parseDate($_episode.find('time').attr('datetime')),
|
||||
};
|
||||
})
|
||||
.toArray()
|
||||
.sort((a, b) => (a.pubDate <= b.pubDate ? 1 : -1))
|
||||
.slice(0, limit);
|
||||
|
||||
const item_list = await Promise.all(
|
||||
episode_list.map((episode) =>
|
||||
ctx.cache.tryGet(episode.link, async () => {
|
||||
episode.link = `https://kakuyomu.jp${episode.link}`;
|
||||
const content = cheerio.load(await get(episode.link));
|
||||
episode.description = content('.widget-episodeBody').html();
|
||||
return episode;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: work_title,
|
||||
link: work_url,
|
||||
description: introduction,
|
||||
language: 'ja',
|
||||
item: item_list,
|
||||
};
|
||||
};
|
||||
|
||||
const get = async (url) => {
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
});
|
||||
|
||||
return response.data;
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
'/episode/:id': ['huangliangshusheng'],
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
module.exports = {
|
||||
'kakuyomu.jp': {
|
||||
_name: 'kakuyomu',
|
||||
'.': [
|
||||
{
|
||||
title: '章节更新',
|
||||
docs: 'https://docs.rsshub.app/routes/reading#kakuyomu-zhang-jie-geng-xin',
|
||||
source: ['/works/:id'],
|
||||
target: '/kakuyomu/episode/:id',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = (router) => router.get('/episode/:id', require('./episode.js'));
|
||||
@@ -1,87 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const timezone = require('@/utils/timezone');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const category = ctx.params.category ?? 'shouding';
|
||||
const type = ctx.params.type ?? (category === 'shouding' ? '' : '1');
|
||||
const isHistory = /t|y/i.test(ctx.params.is_history ?? 'false');
|
||||
|
||||
const today = new Date();
|
||||
today.setTime(new Date().getTime() - 24 * 60 * 60 * 1000);
|
||||
const yesterday = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}`;
|
||||
|
||||
const rootUrl = 'https://www.qidiantu.com';
|
||||
const currentUrl = `${rootUrl}/${category === 'shouding' ? `${category}/` : `bang/${category}/${type}/${isHistory ? '' : yesterday}`}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
$('a[role="button"]').remove();
|
||||
|
||||
let items = $(isHistory ? 'ul li a' : 'tbody tr')
|
||||
.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 25)
|
||||
.toArray()
|
||||
.map((item) => {
|
||||
item = $(item);
|
||||
|
||||
return isHistory
|
||||
? {
|
||||
title: item.text(),
|
||||
link: `${rootUrl}${item.attr('href')}`,
|
||||
}
|
||||
: {
|
||||
author: item.find('td').eq(3).text(),
|
||||
title: item.find('td[value]').first().text(),
|
||||
link: `${rootUrl}${item.find('td a').first().attr('href').replace(/\/d$/, '')}`,
|
||||
category: item
|
||||
.find(`td${category === 'shouding' ? '[value]' : ''}`)
|
||||
.eq(1)
|
||||
.text(),
|
||||
};
|
||||
});
|
||||
|
||||
items = await Promise.all(
|
||||
items.map((item) =>
|
||||
ctx.cache.tryGet(isHistory ? item.link : `${item.link}-${yesterday}`, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
content('#demo').next().remove();
|
||||
|
||||
if (isHistory) {
|
||||
item.description = content('.table-responsive').html();
|
||||
item.pubDate = parseDate(item.link.split('/').pop());
|
||||
} else {
|
||||
item.description = content('.media').html() + content('.panel-body').html();
|
||||
item.pubDate = timezone(
|
||||
parseDate(
|
||||
content('tbody tr')
|
||||
.last()
|
||||
.text()
|
||||
.match(/刷新时间:(\d{4}-\d{2}-\d{2} \d{2}:\d{2})/)[1]
|
||||
),
|
||||
+8
|
||||
);
|
||||
}
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `${$('.panel-heading').text()} - 起点图`,
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = {
|
||||
'/:category?/:type?/:is_history?': ['nczitzk'],
|
||||
'/shouding': ['nczitzk'],
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
module.exports = {
|
||||
'qidiantu.com': {
|
||||
_name: '起点图',
|
||||
'.': [
|
||||
{
|
||||
title: '首订',
|
||||
docs: 'https://docs.rsshub.app/routes/reading#qi-dian-tu-shou-ding',
|
||||
source: ['/shouding', '/'],
|
||||
target: '/qidiantu/shouding',
|
||||
},
|
||||
{
|
||||
title: '榜单',
|
||||
docs: 'https://docs.rsshub.app/routes/reading#qi-dian-tu-bang-dan',
|
||||
source: ['/bang/:category/:type', '/'],
|
||||
target: '/qidiantu/:category?/:type?/:is_history?',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function (router) {
|
||||
router.get('/:category?/:type?/:is_history?', require('./index'));
|
||||
};
|
||||
@@ -515,16 +515,6 @@ In addition, we have prepared a Node.js script to help you use proxies to create
|
||||
3. 找到 `https://bbs.pku.edu.cn/v2/home.php` 请求
|
||||
4. 找到请求头中的 Cookie
|
||||
|
||||
### 吹牛部落
|
||||
|
||||
用于栏目
|
||||
|
||||
- `CHUINIU_MEMBER`: 吹牛部落登录后的 x-member,获取方式
|
||||
1. 登陆后点开文章正文
|
||||
2. 打开控制台,刷新
|
||||
3. 找到 `http://api.duanshu.com/h5/content/detail` 开头的请求
|
||||
4. 找到请求头中的 x-member
|
||||
|
||||
### 滴答清单
|
||||
|
||||
- `DIDA365_USERNAME`: 滴答清单用户名
|
||||
|
||||
@@ -38,24 +38,6 @@
|
||||
|
||||
<Route author="EthanWng97" example="/inoreader/rss/1005137674/user-favorites" path="/inoreader/rss/:user/:tag" paramsDesc={['user id, the interger after user/ in the example URL','tag, the string after tag/ in the example URL']} />
|
||||
|
||||
## kakuyomu {#kakuyomu}
|
||||
|
||||
### episode {#kakuyomu-episode}
|
||||
|
||||
<Route author="huangliangshusheng" example="/kakuyomu/episode/1177354054883783581" path="/kakuyomu/episode/:id" paramsDesc={['Novel id, can be found in URL']} notOperational="1">
|
||||
Eg: [https://kakuyomu.jp/works/1177354054883783581](https://kakuyomu.jp/works/1177354054883783581)
|
||||
</Route>
|
||||
|
||||
## Kindle Unlimited {#kindle-unlimited}
|
||||
|
||||
### 会员限时免费读书单 {#kindle-unlimited-hui-yuan-xian-shi-mian-fei-du-shu-dan}
|
||||
|
||||
<Route author="nczitzk" example="/amazon/ku/this" path="/amazon/ku/:type?" paramsDesc={['书单类型,见下表']} notOperational="1">
|
||||
| 本月书单 | 好评返场 | 次月预告 |
|
||||
| -------- | -------- | -------- |
|
||||
| this | back | next |
|
||||
</Route>
|
||||
|
||||
## Literotica {#literotica}
|
||||
|
||||
### New Stories {#literotica-new-stories}
|
||||
@@ -162,12 +144,6 @@
|
||||
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|
||||
</Route>
|
||||
|
||||
## 爱下电子书 {#ai-xia-dian-zi-shu}
|
||||
|
||||
### 最新章节 {#ai-xia-dian-zi-shu-zui-xin-zhang-jie}
|
||||
|
||||
<Route author="JeasonLau Maecenas" example="/axdzs/诡秘之主" path="/axdzs/:novel" paramsDesc={['小说的中文名, 可在对应小说页 URL 中找到']} />
|
||||
|
||||
## 笔趣阁 {#bi-qu-ge}
|
||||
|
||||
:::tip
|
||||
@@ -216,12 +192,6 @@
|
||||
:::
|
||||
</Route>
|
||||
|
||||
## 博客来 {#bo-ke-lai}
|
||||
|
||||
### 新书出版 {#bo-ke-lai-xin-shu-chu-ban}
|
||||
|
||||
<Route author="CokeMine" example="/bookscomtw/newbooks/books_nbtopm_15" path="/bookscomtw/newbooks/:category" paramsDesc={['书籍类型 category, 可在对应博客来新书页 URL 中找到']} notOperational="1" />
|
||||
|
||||
## 超星 {#chao-xing}
|
||||
|
||||
### 期刊 {#chao-xing-qi-kan}
|
||||
@@ -242,26 +212,6 @@
|
||||
:::
|
||||
</Route>
|
||||
|
||||
## 吹牛部落 {#chui-niu-bu-luo}
|
||||
|
||||
### 栏目 {#chui-niu-bu-luo-lan-mu}
|
||||
|
||||
<Route author="LogicJake" example="/chuiniu/column/0b1c4cf6e7f24e8da11e37882de73704" path="/chuiniu/column/:id" paramsDesc={['栏目 id, 可在对应栏目页 URL 中找到']} notOperational="1">
|
||||
:::warning
|
||||
正文内容需要用户登录后的 x-member 值,详情见部署页面的配置模块。若无相关配置或 x-member 失效,则只显示文章摘要。
|
||||
:::
|
||||
</Route>
|
||||
|
||||
### 专栏列表 {#chui-niu-bu-luo-zhuan-lan-lie-biao}
|
||||
|
||||
<Route author="LogicJake" example="/chuiniu/column_list" path="/chuiniu/column_list" notOperational="1" />
|
||||
|
||||
## 刺猬猫 {#ci-wei-mao}
|
||||
|
||||
### 章节 {#ci-wei-mao-zhang-jie}
|
||||
|
||||
<Route author="Netrvin" example="/ciweimao/chapter/100045750" path="/ciweimao/chapter/:id" paramsDesc={['小说 id, 可在对应小说页 URL 中找到']} notOperational="1" />
|
||||
|
||||
## 单向空间 {#dan-xiang-kong-jian}
|
||||
|
||||
### 单读 {#dan-xiang-kong-jian-dan-du}
|
||||
@@ -272,22 +222,6 @@
|
||||
| 0 | 1 | 2 | 3 | 4 | 6 |
|
||||
</Route>
|
||||
|
||||
## 稻草人书屋 {#dao-cao-ren-shu-wu}
|
||||
|
||||
### 章节更新 {#dao-cao-ren-shu-wu-zhang-jie-geng-xin}
|
||||
|
||||
<Route author="JeasonLau" example="/dcrsw/zhongjidouluo/2" path="/dcrsw/:name/:count?" paramsDesc={['小说名,可在对应小说页URL中找到', '显示的章节数,缺省为`3`']} notOperational="1">
|
||||
:::warning
|
||||
count 的取值范围为 1-12,为防止请求次数过多,推荐设置为 5 以下。
|
||||
:::
|
||||
</Route>
|
||||
|
||||
## 第一版主 {#di-yi-ban-zhu}
|
||||
|
||||
### 小说 {#di-yi-ban-zhu-xiao-shuo}
|
||||
|
||||
<Route author="x1a0xv4n" example="/novel/d1bz/2/2608_6" path="/novel/d1bz/:category/:id" paramsDesc={['小说分类,可在对应小说页 URL 中找到,例如`2`', '小说id,可在对应小说页 URL 中找到,例如`2608_6`']} notOperational="1" />
|
||||
|
||||
## 东立出版 {#dong-li-chu-ban}
|
||||
|
||||
### NEWS 资讯 {#dong-li-chu-ban-news-zi-xun}
|
||||
@@ -339,28 +273,12 @@
|
||||
|
||||
<Route author="nczitzk" example="/kongfz/shop/238901/1" path="/kongfz/shop/:id/:cat?" paramsDesc={['店铺 id, 可在对应店铺页 URL 中找到', '分类 id,可在对应分类页 URL 中找到,默认为店铺最新上架']} />
|
||||
|
||||
## 快眼看书 {#kuai-yan-kan-shu}
|
||||
|
||||
### 小说更新 {#kuai-yan-kan-shu-xiao-shuo-geng-xin}
|
||||
|
||||
<Route author="squkw" example="/novel/booksky/98619" path="/novel/booksky/:id" paramsDesc={['小说 id, 可在对应小说页 URL 中找到, 例如 `98619`']} notOperational="1">
|
||||
举例网址:`http://booksky.so/BookDetail.aspx?Level=1&bid=98619`
|
||||
</Route>
|
||||
|
||||
## 哩哔轻小说 {#li-bi-qing-xiao-shuo}
|
||||
|
||||
### 小说更新 {#li-bi-qing-xiao-shuo-xiao-shuo-geng-xin}
|
||||
|
||||
<Route author="misakicoca" path="/linovelib/novel/:id" example="/linovelib/novel/2547" paramsDesc={['小说 id,对应书架开始阅读 URL 中找到']} anticrawler="1" />
|
||||
|
||||
## 飘天文学 {#piao-tian-wen-xue}
|
||||
|
||||
### 章节 {#piao-tian-wen-xue-zhang-jie}
|
||||
|
||||
<Route author="LJason77" example="/novel/ptwxz/10/10272" path="/novel/ptwxz/:id1/:id2" paramsDesc={['小说网站链接倒数第二部分的数字, 可在对应小说页 URL 中找到, 例如 `10`', '小说网站链接最后的数字, 可在对应小说页 URL 中找到, 例如 `10272`']} notOperational="1">
|
||||
举例网址:`https://www.ptwxz.com/bookinfo/10/10272.html`
|
||||
</Route>
|
||||
|
||||
## 起点 {#qi-dian}
|
||||
|
||||
### 章节 {#qi-dian-zhang-jie}
|
||||
@@ -383,24 +301,6 @@
|
||||
|
||||
<Route author="miles170" example="/qidian/author/9639927" path="/qidian/author/:id" paramsDesc={['作者 id, 可在作者页面 URL 找到']} />
|
||||
|
||||
## 起点图 {#qi-dian-tu}
|
||||
|
||||
### 首订 {#qi-dian-tu-shou-ding}
|
||||
|
||||
<Route author="nczitzk" example="/qidiantu/shouding" path="/qidiantu/shouding" notOperational="1" />
|
||||
|
||||
### 榜单 {#qi-dian-tu-bang-dan}
|
||||
|
||||
<Route author="nczitzk" example="/qidiantu" path="/qidiantu/:category?/:type?/:is_history?" paramsDesc={['分类', '类型', '是否查看历史榜单,填写 true/yes 表示是,默认否']} notOperational="1">
|
||||
:::tip
|
||||
参数 **是否查看历史榜单** 设置为 `true` `yes` `t` `y` 等值后,RSS 会返回历史榜单。
|
||||
|
||||
如 [`/qidiantu/1/1/t`](https://rsshub.app/qidiantu/1/1/t) 将会返回 [起点首页 - 封推 的历史推荐记录](https://www.qidiantu.com/bang/1/1/) 的结果。
|
||||
|
||||
而 [`/qidiantu/1/1`](https://rsshub.app/qidiantu/1/1) 将会返回最新一期 [收藏增长 (起点首页 - 封推)](https://www.qidiantu.com/bang/1/1/2021-12-14) 的结果(编写文档时最新一期为 2021-12-14)。
|
||||
:::
|
||||
</Route>
|
||||
|
||||
## 青空文庫 {#qing-kong-wen-ku}
|
||||
|
||||
### 青空文庫新着リスト {#qing-kong-wen-ku-qing-kong-wen-ku-xin-zhe-%E3%83%AA%E3%82%B9%E3%83%88}
|
||||
@@ -437,31 +337,6 @@
|
||||
|
||||
<Route author="eternasuno" example="/yomujp/n1" path="/yomujp/:level?" paramsDesc={['等级,n1~n6,为空默认全部']} />
|
||||
|
||||
## 生物帮 {#sheng-wu-bang}
|
||||
|
||||
### 所有栏目 {#sheng-wu-bang-suo-you-lan-mu}
|
||||
|
||||
<Route author="xfangbao" example="/biobio/nature/cell-reports" path="/biobio/:column/:id" paramsDesc={['', '']} notOperational="1" />
|
||||
|
||||
具体栏目编号,去网站上看标签
|
||||
|
||||
| 网址 | 对应路由 |
|
||||
| ------------------------------------------------ | ----------------------------------- |
|
||||
| `http://science.bio1000.com/ecology-environment` | /biobio/science/ecology-environment |
|
||||
| `http://www.bio1000.com/gnjz` | /biobio/gnjz |
|
||||
|
||||
## 生物谷 {#sheng-wu-gu}
|
||||
|
||||
### 所有栏目 {#sheng-wu-gu-suo-you-lan-mu}
|
||||
|
||||
<Route author="xfangbao" example="/shengwugu/biology" path="/shengwugu/:uid/" paramsDesc={['分栏代码, 可在 URL 找到']} notOperational="1" />
|
||||
|
||||
具体栏目编号,去网站上看标签
|
||||
|
||||
| 网址 | 对应路由 |
|
||||
| ------------------------------- | ------------------ |
|
||||
| `http://news.bioon.com/biology` | /shengwugu/biology |
|
||||
|
||||
## 书伴 {#shu-ban}
|
||||
|
||||
### 分类 {#shu-ban-fen-lei}
|
||||
@@ -472,14 +347,6 @@
|
||||
| weekly | skills | books | news | essay |
|
||||
</Route>
|
||||
|
||||
## 文学迷 {#wen-xue-mi}
|
||||
|
||||
### 小说更新 {#wen-xue-mi-xiao-shuo-geng-xin}
|
||||
|
||||
<Route author="lengthmin" example="/novel/wenxuemi/6/6144" path="/novel/wenxuemi/:id1/:id2" paramsDesc={['小说网站链接倒数第二部分的数字, 可在对应小说页 URL 中找到, 例如 `6`', '小说网站链接最后的数字, 可在对应小说页 URL 中找到, 例如 `6144`']} notOperational="1">
|
||||
举例网址:`https://www.wenxuemi.com/files/article/html/6/6144/`
|
||||
</Route>
|
||||
|
||||
## 虛詞 {#xu-ci}
|
||||
|
||||
### 版块 {#xu-ci-ban-kuai}
|
||||
@@ -490,14 +357,6 @@
|
||||
|
||||
<Route author="LogicJake" example="/p-articles/contributors/朗天" path="/p-articles/contributors/:author" paramsDesc={['作者 id, 可在作者页面 URL 找到']} />
|
||||
|
||||
## 斋书苑 {#zhai-shu-yuan}
|
||||
|
||||
### 最新章节 {#zhai-shu-yuan-zui-xin-zhang-jie}
|
||||
|
||||
<Route author="suiyuran" example="/novel/zhaishuyuan/17858" path="/novel/zhaishuyuan/:id" paramsDesc={['小说 id, 可在对应小说页 URL 中找到, 例如 `17858`']} radar="1" notOperational="1">
|
||||
举例网址:`https://www.zhaishuyuan.com/book/17858`
|
||||
</Route>
|
||||
|
||||
## 纵横 {#zong-heng}
|
||||
|
||||
### 章节 {#zong-heng-zhang-jie}
|
||||
|
||||
@@ -499,16 +499,6 @@ RSSHub 支持使用访问密钥 / 码,允许清单和拒绝清单三种方式
|
||||
3. 找到 `https://bbs.pku.edu.cn/v2/home.php` 请求
|
||||
4. 找到请求头中的 Cookie
|
||||
|
||||
### 吹牛部落
|
||||
|
||||
用于栏目
|
||||
|
||||
- `CHUINIU_MEMBER`: 吹牛部落登录后的 x-member,获取方式
|
||||
1. 登陆后点开文章正文
|
||||
2. 打开控制台,刷新
|
||||
3. 找到 `http://api.duanshu.com/h5/content/detail` 开头的请求
|
||||
4. 找到请求头中的 x-member
|
||||
|
||||
### 滴答清单
|
||||
|
||||
- `DIDA365_USERNAME`: 滴答清单用户名
|
||||
|
||||
Reference in New Issue
Block a user