From b50f40ab7f41874d712678f78c5b9dcde183c705 Mon Sep 17 00:00:00 2001 From: Zhu Chu Date: Fri, 23 Nov 2018 16:56:22 +0800 Subject: [PATCH] nhentai: added simple mode (#1191) * nhentai: added simple mode * nhentai: detail limit & deleted console.log --- docs/README.md | 6 ++-- router.js | 4 +-- routes/nhentai/other.js | 11 +++--- routes/nhentai/search.js | 11 +++--- routes/nhentai/util.js | 74 ++++++++++++++++------------------------ 5 files changed, 46 insertions(+), 60 deletions(-) diff --git a/docs/README.md b/docs/README.md index c783064b5..6ec0e42a4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1019,8 +1019,8 @@ GitHub 官方也提供了一些 RSS: ### nHentai - - + + ## 二次元 @@ -1563,7 +1563,7 @@ category 列表: 注意: `qttz` 与 `xwdt` 在原网站等价. - + ### 华南理工大学 diff --git a/router.js b/router.js index 484fc4a74..0e46ba908 100644 --- a/router.js +++ b/router.js @@ -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')); diff --git a/routes/nhentai/other.js b/routes/nhentai/other.js index 8f31514b4..4a9cd777a 100644 --- a/routes/nhentai/other.js +++ b/routes/nhentai/other.js @@ -1,9 +1,11 @@ -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', @@ -11,13 +13,12 @@ module.exports = async (ctx) => { 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), }; }; diff --git a/routes/nhentai/search.js b/routes/nhentai/search.js index 86430dc83..40e4915d0 100644 --- a/routes/nhentai/search.js +++ b/routes/nhentai/search.js @@ -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), }; }; diff --git a/routes/nhentai/util.js b/routes/nhentai/util.js index b359a54e0..70cdb45ab 100644 --- a/routes/nhentai/util.js +++ b/routes/nhentai/util.js @@ -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: ``, + }; +}; + +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) => `
`; return { + ...simple, title: $('div#info > h2').text() || $('div#info > h1').text(), pubDate: new Date($('time').attr('datetime')).toUTCString(), - guid: `full:${url}`, description: ` -

${galleryThumbs.length} pages

- ${galleryThumbs.map(renderImg).join('')} +

${galleryImgs.length} pages

+ ${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: ``, - }; -}