diff --git a/docs/picture.md b/docs/picture.md
index 5de6f009f..1c60f18a9 100644
--- a/docs/picture.md
+++ b/docs/picture.md
@@ -48,6 +48,10 @@ pageClass: routes
+### 标签
+
+
+
## Asian to lick
### 首页
diff --git a/lib/router.js b/lib/router.js
index 35b4dfc00..9bdb1fac0 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -3465,9 +3465,10 @@ router.get('/dedao/:caty?', lazyloadRouteHandler('./routes/dedao/index'));
// 未名新闻
router.get('/mitbbs/:caty?', lazyloadRouteHandler('./routes/mitbbs/index'));
-// 8kcos
-router.get('/8kcos/', lazyloadRouteHandler('./routes/8kcos/latest'));
-router.get('/8kcos/cat/:cat*', lazyloadRouteHandler('./routes/8kcos/cat'));
+// 8kcos migrated to v2
+// router.get('/8kcos/', lazyloadRouteHandler('./routes/8kcos/latest'));
+// router.get('/8kcos/cat/:cat*', lazyloadRouteHandler('./routes/8kcos/cat'));
+// router.get('/8kcos/tag/:tag', lazyloadRouteHandler('./routes/8kcos/tag'));
// 贾真的电商108将
router.get('/jiazhen108', lazyloadRouteHandler('./routes/jiazhen108/index'));
diff --git a/lib/routes/8kcos/article.js b/lib/routes/8kcos/article.js
deleted file mode 100644
index 5ddbfe7a1..000000000
--- a/lib/routes/8kcos/article.js
+++ /dev/null
@@ -1,17 +0,0 @@
-const Cheerio = require('cheerio');
-const got = require('got');
-async function loadArticle(link) {
- const resp = await got(link);
- const article = Cheerio.load(resp.body);
- const title = article('.entry-title').text();
- const entry_children = article('div.entry-content').children().toArray();
- const imgs = Cheerio.load(entry_children.shift()).text(); // 去除懒加载代码减少返回体积
- const txt = Cheerio.load(entry_children).html();
- return {
- title,
- description: imgs.concat(txt),
- pubDate: article('time')[0].attribs.datetime.replace('>', ''),
- link,
- };
-}
-module.exports = loadArticle;
diff --git a/lib/routes/8kcos/cat.js b/lib/routes/8kcos/cat.js
deleted file mode 100644
index 2bae82c6e..000000000
--- a/lib/routes/8kcos/cat.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const got = require('got');
-const Cheerio = require('cheerio');
-const { SUB_NAME_PREFIX, SUB_URL } = require('./const');
-const loadArticle = require('./article');
-module.exports = async (ctx) => {
- const { cat = '8kasianidol' } = ctx.params;
- const url = `${SUB_URL}category/${cat}/`;
- const resp = await got(url);
- const $ = Cheerio.load(resp.body);
- ctx.state.data = resp.body
- ? {
- title: `${SUB_NAME_PREFIX}-${$('#wrap > div > div > div > div.sec-panel-head > h1 > span').text()}`,
- link: url,
- item: await Promise.all(
- Cheerio.load(resp.body)('#wrap > div > div > div > ul > li.item')
- .map((_, e) => {
- const { href } = Cheerio.load(e)('h2 > a')[0].attribs;
- return ctx.cache.tryGet(href, () => loadArticle(href));
- })
- .toArray()
- ),
- }
- : {
- title: `${SUB_NAME_PREFIX}-${cat}`,
- link: url,
- item: [{ title: '获取失败' }],
- };
-};
diff --git a/lib/routes/8kcos/latest.js b/lib/routes/8kcos/latest.js
deleted file mode 100644
index 3cd73d2b3..000000000
--- a/lib/routes/8kcos/latest.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const got = require('got');
-const Cheerio = require('cheerio');
-const { SUB_NAME_PREFIX, SUB_URL } = require('./const');
-const loadArticle = require('./article');
-const url = SUB_URL;
-
-module.exports = async (ctx) => {
- const response = await got(url);
- ctx.state.data = {
- title: `${SUB_NAME_PREFIX}-最新`,
- link: url,
- item: response.body
- ? await Promise.all(
- Cheerio.load(response.body)('#wrap > div > div > div > ul > li.item')
- .map((_, e) => {
- const { href } = Cheerio.load(e)('div > h2 > a')[0].attribs;
- return ctx.cache.tryGet(href, () => loadArticle(href));
- })
- .toArray()
- )
- : [
- {
- title: '获取失败!',
- },
- ],
- };
-};
diff --git a/lib/v2/8kcos/article.js b/lib/v2/8kcos/article.js
new file mode 100644
index 000000000..b341bf780
--- /dev/null
+++ b/lib/v2/8kcos/article.js
@@ -0,0 +1,24 @@
+const Cheerio = require('cheerio');
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+async function loadArticle(link) {
+ const resp = await got(link);
+ const article = Cheerio.load(resp.body);
+ const entryChildren = article('div.entry-content').children();
+ const imgs = entryChildren
+ .find('noscript')
+ .toArray()
+ .map((e) => e.children[0].data);
+ const txt = entryChildren
+ .slice(2)
+ .toArray()
+ .map((e) => Cheerio.load(e).html());
+ return {
+ title: article('.entry-title').text(),
+ description: imgs.concat(txt).join(''),
+ pubDate: parseDate(article('time')[0].attribs.datetime),
+ link,
+ };
+}
+module.exports = loadArticle;
diff --git a/lib/v2/8kcos/cat.js b/lib/v2/8kcos/cat.js
new file mode 100644
index 000000000..493b00dd1
--- /dev/null
+++ b/lib/v2/8kcos/cat.js
@@ -0,0 +1,22 @@
+const got = require('@/utils/got');
+const Cheerio = require('cheerio');
+const { SUB_NAME_PREFIX, SUB_URL } = require('./const');
+const loadArticle = require('./article');
+module.exports = async (ctx) => {
+ const limit = parseInt(ctx.query.limit);
+ const { cat = '8kasianidol' } = ctx.params;
+ const url = `${SUB_URL}category/${cat}/`;
+ const resp = await got(url);
+ const $ = Cheerio.load(resp.body);
+ const itemRaw = $('li.item').toArray();
+ ctx.state.data = {
+ title: `${SUB_NAME_PREFIX}-${$('span[property=name]:not(.hide)').text()}`,
+ link: url,
+ item: await Promise.all(
+ (limit ? itemRaw.slice(0, limit) : itemRaw).map((e) => {
+ const { href } = Cheerio.load(e)('h2 > a')[0].attribs;
+ return ctx.cache.tryGet(href, () => loadArticle(href));
+ })
+ ),
+ };
+};
diff --git a/lib/routes/8kcos/const.js b/lib/v2/8kcos/const.js
similarity index 100%
rename from lib/routes/8kcos/const.js
rename to lib/v2/8kcos/const.js
diff --git a/lib/v2/8kcos/latest.js b/lib/v2/8kcos/latest.js
new file mode 100644
index 000000000..897d83f1f
--- /dev/null
+++ b/lib/v2/8kcos/latest.js
@@ -0,0 +1,23 @@
+const got = require('@/utils/got');
+const Cheerio = require('cheerio');
+const { SUB_NAME_PREFIX, SUB_URL } = require('./const');
+const loadArticle = require('./article');
+const url = SUB_URL;
+
+module.exports = async (ctx) => {
+ const limit = parseInt(ctx.query.limit);
+ const response = await got(url);
+ const itemRaw = Cheerio.load(response.body)('ul.post-loop li.item').toArray();
+ ctx.state.data = {
+ title: `${SUB_NAME_PREFIX}-最新`,
+ link: url,
+ item:
+ response.body &&
+ (await Promise.all(
+ (limit ? itemRaw.slice(0, limit) : itemRaw).map((e) => {
+ const { href } = Cheerio.load(e)('h2 > a')[0].attribs;
+ return ctx.cache.tryGet(href, () => loadArticle(href));
+ })
+ )),
+ };
+};
diff --git a/lib/v2/8kcos/maintainer.js b/lib/v2/8kcos/maintainer.js
new file mode 100644
index 000000000..8e811c657
--- /dev/null
+++ b/lib/v2/8kcos/maintainer.js
@@ -0,0 +1,5 @@
+module.exports = {
+ '/': ['KotoriK'],
+ '/cat/:cat*': ['KotoriK'],
+ '/tag/:tag': ['KotoriK'],
+};
diff --git a/lib/v2/8kcos/radar.js b/lib/v2/8kcos/radar.js
new file mode 100644
index 000000000..3e78d8884
--- /dev/null
+++ b/lib/v2/8kcos/radar.js
@@ -0,0 +1,25 @@
+module.exports = {
+ '8kcosplay.com': {
+ _name: '8KCosplay',
+ '.': [
+ {
+ title: '最新',
+ docs: 'https://docs.rsshub.app/picture.html#_8kcosplay',
+ source: ['/'],
+ target: '/8kcos',
+ },
+ {
+ title: '分类',
+ docs: 'https://docs.rsshub.app/picture.html#_8kcosplay',
+ source: ['/category/:cat*'],
+ target: (params, url) => `/8kcos/cat/${new URL(url).pathname}`,
+ },
+ {
+ title: '标签',
+ docs: 'https://docs.rsshub.app/picture.html#_8kcosplay',
+ source: ['/tag/:tag'],
+ target: '/8kcos/tag/:tag',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/8kcos/router.js b/lib/v2/8kcos/router.js
new file mode 100644
index 000000000..91843ccbd
--- /dev/null
+++ b/lib/v2/8kcos/router.js
@@ -0,0 +1,5 @@
+module.exports = (router) => {
+ router.get('/', require('./latest'));
+ router.get('/cat/:cat*', require('./cat'));
+ router.get('/tag/:tag', require('./tag'));
+};
diff --git a/lib/v2/8kcos/tag.js b/lib/v2/8kcos/tag.js
new file mode 100644
index 000000000..f8a3e4a6e
--- /dev/null
+++ b/lib/v2/8kcos/tag.js
@@ -0,0 +1,23 @@
+const got = require('@/utils/got');
+const Cheerio = require('cheerio');
+const { SUB_NAME_PREFIX, SUB_URL } = require('./const');
+const loadArticle = require('./article');
+module.exports = async (ctx) => {
+ const limit = parseInt(ctx.query.limit);
+ const { tag } = ctx.params;
+ const url = `${SUB_URL}tag/${tag}/`;
+ const resp = await got(url);
+ const $ = Cheerio.load(resp.body);
+ const itemRaw = $('li.item').toArray();
+
+ ctx.state.data = {
+ title: `${SUB_NAME_PREFIX}-${$('span[property=name]:not(.hide)').text()}`,
+ link: url,
+ item: await Promise.all(
+ (limit ? itemRaw.slice(0, limit) : itemRaw).map((e) => {
+ const { href } = Cheerio.load(e)('h2 > a')[0].attribs;
+ return ctx.cache.tryGet(href, () => loadArticle(href));
+ })
+ ),
+ };
+};