mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-19 06:38:55 +08:00
增加:nhentai (#983)
This commit is contained in:
@@ -2079,3 +2079,8 @@ IATA 国际航空运输协会机场代码, 参见[维基百科 国际航空运
|
|||||||
### 油价
|
### 油价
|
||||||
|
|
||||||
<route name="今日油价" author="xyqfer" example="/oilprice/shanghai" path="/oilprice/:area" :paramsDesc="['地区拼音,详见[成品油价格网](http://oil.usd-cny.com/)']"/>
|
<route name="今日油价" author="xyqfer" example="/oilprice/shanghai" path="/oilprice/:area" :paramsDesc="['地区拼音,详见[成品油价格网](http://oil.usd-cny.com/)']"/>
|
||||||
|
|
||||||
|
### nHentai
|
||||||
|
|
||||||
|
<route name="分类筛选" author="MegrezZhu" example="/nhentai/language/chinese" path="/nhentai/:key/:keyword" :paramsDesc="['筛选条件,可选: parody, character, tag, artist, group, language, category','筛选值']" />
|
||||||
|
<route name="高级搜索" author="MegrezZhu" example="/nhentai/search/translated" path="/nhentai/search/:keyword" :paramsDesc="['用于搜索的关键词,用法详见[官网](https://nhentai.net/info/)']" />
|
||||||
|
|||||||
@@ -706,4 +706,8 @@ router.get('/youku/channel/:channelId/:embed?', require('./routes/youku/channel'
|
|||||||
// 油价
|
// 油价
|
||||||
router.get('/oilprice/:area', require('./routes/oilprice'));
|
router.get('/oilprice/:area', require('./routes/oilprice'));
|
||||||
|
|
||||||
|
// nHentai
|
||||||
|
router.get('/nhentai/search/:keyword', require('./routes/nhentai/search'));
|
||||||
|
router.get('/nhentai/:key/:keyword', require('./routes/nhentai/other'));
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
23
routes/nhentai/other.js
Normal file
23
routes/nhentai/other.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const { getList, getDetailWithCache } = require('./util');
|
||||||
|
|
||||||
|
const supportedKeys = ['parody', 'character', 'tag', 'artist', 'group', 'language', 'category'];
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const { keyword, key } = ctx.params;
|
||||||
|
if (supportedKeys.indexOf(key) === -1) {
|
||||||
|
ctx.state.data = {
|
||||||
|
title: 'nHentai - unsupported',
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = await getList(`https://nhentai.net/${key}/${keyword.toLowerCase().replace(' ', '-')}`);
|
||||||
|
const details = await Promise.all(list.map(getDetailWithCache.bind(null, ctx.cache)));
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: `nHentai - ${key} - ${keyword}`,
|
||||||
|
link: 'https://nhentai.net',
|
||||||
|
description: 'hentai',
|
||||||
|
item: details,
|
||||||
|
};
|
||||||
|
};
|
||||||
14
routes/nhentai/search.js
Normal file
14
routes/nhentai/search.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { getList, getDetailWithCache } = require('./util');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const { keyword } = ctx.params;
|
||||||
|
const list = await getList(`https://nhentai.net/search/?q=${keyword}`);
|
||||||
|
const details = await Promise.all(list.map(getDetailWithCache.bind(null, ctx.cache)));
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: `nHentai - search - ${keyword}`,
|
||||||
|
link: 'https://nhentai.net',
|
||||||
|
description: 'hentai',
|
||||||
|
item: details,
|
||||||
|
};
|
||||||
|
};
|
||||||
66
routes/nhentai/util.js
Normal file
66
routes/nhentai/util.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const { resolve } = require('url');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const axios = require('../../utils/axios');
|
||||||
|
|
||||||
|
exports.getList = async (url) => {
|
||||||
|
const { data } = await axios.get(url);
|
||||||
|
const $ = cheerio.load(data);
|
||||||
|
|
||||||
|
return $('.gallery a.cover')
|
||||||
|
.map((_, ele) => createResult($, ele))
|
||||||
|
.get();
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getDetail = async (url) => {
|
||||||
|
const { data } = await axios.get(url);
|
||||||
|
const $ = cheerio.load(data);
|
||||||
|
|
||||||
|
// thumb to high-quality
|
||||||
|
let galleryThumbs = $('.gallerythumb img')
|
||||||
|
.map((_, ele) => resolve('https://nhentai.net', $(ele).attr('data-src')))
|
||||||
|
.get();
|
||||||
|
galleryThumbs = galleryThumbs.map((src) => src.replace(/(.+)(\d+)t\.(.+)/, (_, p1, p2, p3) => `${p1}${p2}.${p3}`));
|
||||||
|
galleryThumbs = galleryThumbs.map((src) => src.replace('t.nhentai.net', 'i.nhentai.net'));
|
||||||
|
|
||||||
|
const renderImg = (src) => `<img referrerpolicy="no-referrer" src="${src}" />`;
|
||||||
|
return {
|
||||||
|
pubDate: new Date($('time').attr('datetime')).toUTCString(),
|
||||||
|
guid: `full:${url}`,
|
||||||
|
description: `
|
||||||
|
<h1>${galleryThumbs.length} pages</h1>
|
||||||
|
${galleryThumbs.map(renderImg).join('')}
|
||||||
|
`.trim(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getDetailWithCache = async (cache, info) => {
|
||||||
|
const cached = await cache.get(`full:${info.link}`);
|
||||||
|
if (cached) {
|
||||||
|
return {
|
||||||
|
...info,
|
||||||
|
...cached,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const detail = await exports.getDetail(info.link);
|
||||||
|
cache.set(`full:${info.link}`, detail);
|
||||||
|
return {
|
||||||
|
...info,
|
||||||
|
...detail,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function createResult($, ele) {
|
||||||
|
const link = resolve('https://nhentai.net', $(ele).attr('href'));
|
||||||
|
const thumbImg = $(ele).children('img');
|
||||||
|
const thumbSrc = thumbImg.attr('data-src') || thumbImg.attr('src');
|
||||||
|
return {
|
||||||
|
title: $(ele)
|
||||||
|
.children('.caption')
|
||||||
|
.text(),
|
||||||
|
link,
|
||||||
|
guid: link,
|
||||||
|
pubDate: new Date().toUTCString(), // 要获得准确时间需要对每个本子都请求一遍,很麻烦
|
||||||
|
description: `<img referrerpolicy="no-referrer" src="${thumbSrc.replace('thumb', 'cover')}" />`,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user