Skip to content

Commit

Permalink
nhentai: added simple mode (DIYgod#1191)
Browse files Browse the repository at this point in the history
* nhentai: added simple mode

* nhentai: detail limit & deleted console.log
  • Loading branch information
MegrezZhu authored and DIYgod committed Nov 23, 2018
1 parent 526f47f commit b50f40a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 60 deletions.
6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,8 +1019,8 @@ GitHub 官方也提供了一些 RSS:

### 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/language%3Ajapanese+-scat+-yaoi+-guro+-%22mosaic+censorship%22" path="/nhentai/search/:keyword" :paramsDesc="['用于搜索的关键词。可在原网站搜索后复制 q= 后面的内容,也可直接输入,但空格等特殊符号是否会转换取决于浏览器和阅读器的实现。用法详见[官网](https://nhentai.net/info/)']" />
<route name="分类筛选" author="MegrezZhu" example="/nhentai/language/chinese" path="/nhentai/:key/:keyword/:mode?" :paramsDesc="['筛选条件,可选: parody, character, tag, artist, group, language, category','筛选值', '模式,`simple`为仅封面,`detail`会包括本子每一页,但对服务器负载大。默认为`simple`']" />
<route name="高级搜索" author="MegrezZhu" example="/nhentai/search/language%3Ajapanese+-scat+-yaoi+-guro+-%22mosaic+censorship%22" path="/nhentai/search/:keyword/:mode?" :paramsDesc="['用于搜索的关键词。可在原网站搜索后复制 q= 后面的内容,也可直接输入,但空格等特殊符号是否会转换取决于浏览器和阅读器的实现。用法详见[官网](https://nhentai.net/info/)', '模式,`simple`为仅封面,`detail`会包括本子每一页,但对服务器负载大。默认为`simple`']" />

## 二次元

Expand Down Expand Up @@ -1563,7 +1563,7 @@ category 列表:
注意: `qttz``xwdt` 在原网站等价.

</route>

### 华南理工大学

<route name="教务处新闻动态" author="KeNorizon" example="/scut/jwc/1" path="/scut/jwc/:category?" :paramsDesc="['新闻动态分类, 可选, 默认为 `1`']">
Expand Down
4 changes: 2 additions & 2 deletions router.js
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,8 @@ router.get('/youku/channel/:channelId/:embed?', require('./routes/youku/channel'
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'));
router.get('/nhentai/search/:keyword/:mode?', require('./routes/nhentai/search'));
router.get('/nhentai/:key/:keyword/:mode?', require('./routes/nhentai/other'));

// 龙腾网
router.get('/ltaaa/:type?', require('./routes/ltaaa/main'));
Expand Down
11 changes: 6 additions & 5 deletions routes/nhentai/other.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
const { getList, getDetailWithCache } = require('./util');
const { getSimple, getDetails } = require('./util');

const supportedKeys = ['parody', 'character', 'tag', 'artist', 'group', 'language', 'category'];

module.exports = async (ctx) => {
const { keyword, key } = ctx.params;
const { keyword, key, mode } = ctx.params;
const isSimple = mode !== 'detail';

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)));
const simples = await getSimple(`https://nhentai.net/${key}/${keyword.toLowerCase().replace(' ', '-')}`);

ctx.state.data = {
title: `nHentai - ${key} - ${keyword}`,
link: 'https://nhentai.net',
description: 'hentai',
item: details,
item: isSimple ? simples : await getDetails(ctx.cache, simples),
};
};
11 changes: 6 additions & 5 deletions routes/nhentai/search.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const { getList, getDetailWithCache } = require('./util');
const { getSimple, getDetails } = 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)));
const { keyword, mode } = ctx.params;
const isSimple = mode !== 'detail';

const simples = await getSimple(`https://nhentai.net/search/?q=${keyword}`);

ctx.state.data = {
title: `nHentai - search - ${keyword}`,
link: 'https://nhentai.net',
description: 'hentai',
item: details,
item: isSimple ? simples : await getDetails(ctx.cache, simples),
};
};
74 changes: 29 additions & 45 deletions routes/nhentai/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,50 @@ const { resolve } = require('url');
const cheerio = require('cheerio');
const axios = require('../../utils/axios');

exports.getList = async (url) => {
exports.getSimple = async (url) => {
const { data } = await axios.get(url);
const $ = cheerio.load(data);

return $('.gallery a.cover')
.map((_, ele) => createResult($, ele))
.get();
.map((_, ele) => parseSimpleDetail($(ele)))
.toArray();
};

exports.getDetail = async (url) => {
const { data } = await axios.get(url);
const MAX_DETAIL = 5;
exports.getDetails = async (cache, simples) => Promise.all(simples.slice(0, MAX_DETAIL).map((simple) => cache.tryGet(simple.link, () => getDetail(simple), 24 * 60 * 60)));

const parseSimpleDetail = ($ele) => {
const link = resolve('https://nhentai.net', $ele.attr('href'));
const thumb = $ele.children('img');
const thumbSrc = thumb.attr('data-src') || thumb.attr('src');
const highResoThumbSrc = thumbSrc.replace('thumb', '1').replace('t.nhentai.net', 'i.nhentai.net');
return {
title: $ele.children('.caption').text(),
link,
pubDate: new Date().toUTCString(), // 要获得准确时间需要对每个本子都请求一遍,很麻烦
description: `<img referrerpolicy="no-referrer" src="${highResoThumbSrc}" />`,
};
};

const getDetail = async (simple) => {
const { link } = simple;
const { data } = await axios.get(link);
const $ = cheerio.load(data);

// thumb to high-quality
let galleryThumbs = $('.gallerythumb img')
const galleryImgs = $('.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'));
.get()
.map((src) => src.replace(/(.+)(\d+)t\.(.+)/, (_, p1, p2, p3) => `${p1}${p2}.${p3}`)) // thumb to high-quality
.map((src) => src.replace('t.nhentai.net', 'i.nhentai.net'));

const renderImg = (src) => `<img referrerpolicy="no-referrer" src="${src}" /><br />`;
return {
...simple,
title: $('div#info > h2').text() || $('div#info > h1').text(),
pubDate: new Date($('time').attr('datetime')).toUTCString(),
guid: `full:${url}`,
description: `
<h1>${galleryThumbs.length} pages</h1>
${galleryThumbs.map(renderImg).join('')}
<h1>${galleryImgs.length} pages</h1>
${galleryImgs.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')}" />`,
};
}

0 comments on commit b50f40a

Please sign in to comment.