| 特写 | 记事 | 大写 | 好读 | 看客 |
| ----- | ----- | ----- | ----- | ----- |
diff --git a/docs/study.md b/docs/study.md
index bb6ed7389..707b3a01f 100644
--- a/docs/study.md
+++ b/docs/study.md
@@ -472,10 +472,6 @@ path="/ctfhub/upcoming/:limit?"
-### 最新课程
-
-
-
## 下厨房
### 用户作品
diff --git a/lib/radar-rules.js b/lib/radar-rules.js
index bc8324a08..e59134e44 100644
--- a/lib/radar-rules.js
+++ b/lib/radar-rules.js
@@ -397,28 +397,6 @@ module.exports = {
},
'163.com': {
_name: '网易',
- ds: [
- {
- title: '大神',
- docs: 'https://docs.rsshub.app/game.html#wang-yi-da-shen',
- source: '/user/:id',
- target: '/netease/ds/:id',
- },
- ],
- open: [
- {
- title: '公开课 - 精品课程',
- docs: 'https://docs.rsshub.app/study.html#wang-yi-gong-kai-ke',
- source: '/',
- target: '/open163/vip',
- },
- {
- title: '公开课 - 最新课程',
- docs: 'https://docs.rsshub.app/study.html#wang-yi-gong-kai-ke',
- source: '/',
- target: '/open163/latest',
- },
- ],
music: [
{
title: '云音乐 - 用户歌单',
diff --git a/lib/router.js b/lib/router.js
index 0911642e1..0641a8b14 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -2894,18 +2894,18 @@ router.get('/futunn/highlights', lazyloadRouteHandler('./routes/futunn/highlight
// 网易新闻
// router.get('/netease/news/rank/:category?/:type?/:time?', lazyloadRouteHandler('./routes/netease/news/rank'));
-router.get('/netease/news/special/:type?', lazyloadRouteHandler('./routes/netease/news/special'));
+// router.get('/netease/news/special/:type?', lazyloadRouteHandler('./routes/netease/news/special'));
// 网易 - 网易号
-router.get('/netease/dy/:id', lazyloadRouteHandler('./routes/netease/dy'));
-router.get('/netease/dy2/:id', lazyloadRouteHandler('./routes/netease/dy2'));
+// router.get('/netease/dy/:id', lazyloadRouteHandler('./routes/netease/dy'));
+// router.get('/netease/dy2/:id', lazyloadRouteHandler('./routes/netease/dy2'));
// 网易大神
-router.get('/netease/ds/:id', lazyloadRouteHandler('./routes/netease/ds'));
+// router.get('/netease/ds/:id', lazyloadRouteHandler('./routes/netease/ds'));
// 网易公开课
-router.get('/open163/vip', lazyloadRouteHandler('./routes/netease/open/vip'));
-router.get('/open163/latest', lazyloadRouteHandler('./routes/netease/open/latest'));
+// router.get('/open163/vip', lazyloadRouteHandler('./routes/netease/open/vip'));
+// router.get('/open163/latest', lazyloadRouteHandler('./routes/netease/open/latest'));
// Boston.com
router.get('/boston/:tag?', lazyloadRouteHandler('./routes/boston/index'));
diff --git a/lib/routes/netease/ds.js b/lib/routes/netease/ds.js
deleted file mode 100644
index c5ea468e1..000000000
--- a/lib/routes/netease/ds.js
+++ /dev/null
@@ -1,41 +0,0 @@
-const url = require('url');
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const date = require('@/utils/date');
-
-const root_url = 'https://ds.163.com/';
-
-module.exports = async (ctx) => {
- const id = ctx.params.id;
- if (!id) {
- throw Error('Bad parameter. See https://docs.rsshub.app/game.html#wang-yi-da-shen');
- }
-
- const current_url = url.resolve(root_url, '/user/' + id);
- const response = await got({
- method: 'get',
- url: current_url,
- });
-
- const $ = cheerio.load(response.data);
- const list = $('main.user-page__main div.feed-card')
- .map((_, item) => {
- item = $(item);
- const a = item.find('a.feed-card__link-hide');
- const desc = item.find('div.feed-card__body');
- const title = desc.find('div.feed-text').text();
- return {
- title,
- link: a.attr('href'),
- description: desc.html(),
- pubDate: date(item.find('time.userbar__time').text().trim()),
- };
- })
- .get();
-
- ctx.state.data = {
- title: $('title').text(),
- link: current_url,
- item: list,
- };
-};
diff --git a/lib/routes/netease/dy.js b/lib/routes/netease/dy.js
deleted file mode 100644
index da60a8472..000000000
--- a/lib/routes/netease/dy.js
+++ /dev/null
@@ -1,54 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const date = require('@/utils/date');
-const iconv = require('iconv-lite');
-
-module.exports = async (ctx) => {
- const { id } = ctx.params;
-
- const response = await got.get(`http://dy.163.com/v2/article/list.do?pageNo=1&wemediaId=${id}&size=10`);
- const charset = response.headers['content-type'].split('=')[1];
- const list = response.data.data.list;
- let author, link;
-
- const items = await Promise.all(
- list.map(async (e) => {
- if (e.docid) {
- e.link = 'http://dy.163.com/v2/article/detail/' + e.docid + '.html';
- }
-
- author = e.source ? e.source : '';
-
- const html = await ctx.cache.tryGet(e.link, async () =>
- iconv.decode(
- (
- await got.get(e.link, {
- responseType: 'buffer',
- })
- ).data,
- charset
- )
- );
- const $ = cheerio.load(html, { decodeEntities: false });
-
- const article = $('.post_body');
-
- const single = {
- title: e.title,
- link: e.link,
- description: article.html(),
- pubDate: date(e.ptime, 8),
- author: e.source,
- };
-
- return Promise.resolve(single);
- })
- );
-
- ctx.state.data = {
- title: `网易号 - ${author}`,
- link,
- description: '',
- item: items,
- };
-};
diff --git a/lib/routes/netease/dy2.js b/lib/routes/netease/dy2.js
deleted file mode 100644
index 059db7c9a..000000000
--- a/lib/routes/netease/dy2.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const iconv = require('iconv-lite');
-const { parseDate } = require('@/utils/parse-date');
-
-module.exports = async (ctx) => {
- const { id } = ctx.params;
- const limit = ctx.query.limit || 5;
- const url = `https://www.163.com/dy/media/${id}.html`;
-
- const response = await got(url, { responseType: 'buffer' });
-
- const charset = response.headers['content-type'].split('=')[1];
- const data = iconv.decode(response.data, charset);
- const $ = cheerio.load(data, { decodeEntities: false });
-
- const list = $('.media_articles ul li')
- .slice(0, limit)
- .map((_, item) => {
- item = $(item);
- const a = item.find('h2.media_article_title a');
- return {
- title: a.text(),
- link: a.attr('href'),
- pubDate: parseDate(item.find('.media_article_date').text()),
- };
- })
- .get();
-
- const items = await Promise.all(
- list.map(async (item) => {
- const itemData = await ctx.cache.tryGet(item.link, () =>
- got(item.link, {
- responseType: 'buffer',
- }).then((it) => it.data)
- );
- const content = cheerio.load(itemData, { decodeEntities: false });
- const postBody = content('.post_body');
- postBody.find('p, br, section').each((_, elem) => elem.attribs && Object.keys(elem.attribs).forEach((attr) => content(elem).removeAttr(attr)));
- postBody
- .parent()
- .find('*')
- .contents()
- .filter((_, elem) => elem.type === 'comment')
- .remove();
- return {
- title: item.title,
- link: item.link,
- description: postBody.html(),
- pubDate: item.pubDate,
- };
- })
- );
-
- ctx.state.data = {
- title: $('.media_info h1').text(),
- link: url,
- description: $('.media_degist').text(),
- item: items,
- author: $('.media_name').text(),
- };
-};
diff --git a/lib/routes/netease/open/latest.js b/lib/routes/netease/open/latest.js
deleted file mode 100644
index e324efc77..000000000
--- a/lib/routes/netease/open/latest.js
+++ /dev/null
@@ -1,68 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
- const list_response = await got.get('https://c.open.163.com/open/getLatestMovies.do?callback=');
-
- const list = JSON.parse(list_response.data.match(/\((.*?)\)/)[1]) || [];
-
- const parseContent = (htmlString) => {
- const $ = cheerio.load(htmlString);
-
- const author = $('.m-courseinfo__side ul > li:nth-child(2)');
-
- const images = $('img');
- for (let k = 0; k < images.length; k++) {
- const testRealURL = $(images[k])
- .attr('src')
- .match(/\?url=([^&]+)/);
- if (testRealURL) {
- $(images[k]).replaceWith(`
`);
- }
- }
-
- const content = $('.m-courseinfo__side');
- $('.i-container__title').remove();
-
- return {
- author: author.text().trim(),
- description: content.html(),
- pubDate: new Date(),
- };
- };
-
- const out = await Promise.all(
- list.map(async (item) => {
- const link = item.url;
-
- const cache = await ctx.cache.get(link);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const rssitem = {
- title: item.title,
- link,
- };
-
- try {
- const response = await got.get(link);
- const result = parseContent(response.data);
-
- rssitem.author = result.author;
- rssitem.description = result.description;
- rssitem.pubDate = result.pubDate;
- } catch (err) {
- return Promise.resolve('');
- }
- ctx.cache.set(link, JSON.stringify(rssitem));
- return Promise.resolve(rssitem);
- })
- );
-
- ctx.state.data = {
- title: '网易公开课 - 最新课程',
- link: 'https://open.163.com/',
- item: out.filter((item) => item !== ''),
- };
-};
diff --git a/lib/routes/netease/open/vip.js b/lib/routes/netease/open/vip.js
deleted file mode 100644
index 7f6122d66..000000000
--- a/lib/routes/netease/open/vip.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-
-module.exports = async (ctx) => {
- const url = 'https://vip.open.163.com';
-
- const list_response = await got.get(url);
- const $ = cheerio.load(list_response.data);
-
- const list = $('.CourseListItem_ListItem')
- .map((index, ele) => {
- $('.CourseListItem_oriPrice', ele).remove();
- const price = $('.CourseListItem_price', ele).text().trim();
- return {
- title: price + ' - ' + $('.CourseListItem_title', ele).text(),
- link: url + $(ele).attr('href'),
- };
- })
- .get();
-
- const item = await Promise.all(
- list.slice(0, 10).map((item) =>
- ctx.cache.tryGet(item.link, async () => {
- const res = await got.get(item.link);
- const s = cheerio.load(res.data);
- s('img').css('max-width', '100%');
- const toc = s('.CourseCommonDetail_contentItem').eq(1).html();
- item.description = `${toc}` + s('.CourseCommonDetail_contentItem').first().html() + `
`;
- return item;
- })
- )
- );
-
- ctx.state.data = {
- title: '网易公开课 - 精品课程',
- link: url,
- item,
- };
-};
diff --git a/lib/v2/163/ds.js b/lib/v2/163/ds.js
new file mode 100644
index 000000000..62597b0c3
--- /dev/null
+++ b/lib/v2/163/ds.js
@@ -0,0 +1,33 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+const root_url = 'https://inf.ds.163.com';
+
+module.exports = async (ctx) => {
+ const id = ctx.params.id;
+
+ const current_url = `${root_url}/v1/web/feed/basic/getSomeOneFeeds?feedTypes=1,2,3,4,6,7,10,11&someOneUid=${id}`;
+ const response = await got({
+ method: 'get',
+ url: current_url,
+ });
+ const data = response.data.result.feeds;
+
+ const list = data.map((feed) => ({
+ title: JSON.parse(feed.content).body.text,
+ link: `https://ds.163.com/feed/${feed.id}`,
+ description: art(path.resolve(__dirname, 'templates/ds.art'), {
+ text: JSON.parse(feed.content).body.text,
+ medias: JSON.parse(feed.content).body.media,
+ }),
+ pubDate: parseDate(feed.updateTime),
+ }));
+
+ ctx.state.data = {
+ title: `${response.data.result.userInfos[0].user.nick} 的动态`,
+ link: `https://ds.163.com/user/${id}`,
+ item: list,
+ };
+};
diff --git a/lib/v2/163/dy.js b/lib/v2/163/dy.js
new file mode 100644
index 000000000..a99467a7e
--- /dev/null
+++ b/lib/v2/163/dy.js
@@ -0,0 +1,29 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+const { parseDyArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+
+ const response = await got(`https://dy.163.com/v2/article/list.do?pageNo=1&wemediaId=${id}&size=10`);
+ const charset = response.headers['content-type'].split('=')[1];
+
+ const list = response.data.data.list.map((e) => ({
+ title: e.title,
+ link: 'https://www.163.com/dy/article/' + e.docid + '.html',
+ pubDate: timezone(parseDate(e.ptime), 8),
+ author: e.source,
+ imgsrc: e.imgsrc,
+ }));
+
+ const items = await Promise.all(list.map((e) => parseDyArticle(charset, e, ctx.cache.tryGet)));
+
+ ctx.state.data = {
+ title: `网易号 - ${list[0].author}`,
+ link: items[0].feedLink,
+ description: items[0].feedDescription,
+ image: items[0].feedImage,
+ item: items,
+ };
+};
diff --git a/lib/v2/163/dy2.js b/lib/v2/163/dy2.js
new file mode 100644
index 000000000..61724026e
--- /dev/null
+++ b/lib/v2/163/dy2.js
@@ -0,0 +1,42 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const iconv = require('iconv-lite');
+const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
+const { parseDyArticle } = require('./utils');
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+ const limit = ctx.query.limit ?? 30;
+ const url = `https://www.163.com/dy/media/${id}.html`;
+
+ const response = await got(url, { responseType: 'buffer' });
+
+ const charset = response.headers['content-type'].split('=')[1];
+ const data = iconv.decode(response.data, charset);
+ const $ = cheerio.load(data);
+
+ const list = $('.tab_content ul li')
+ .slice(0, limit)
+ .toArray()
+ .map((item) => {
+ item = $(item);
+ return {
+ title: item.find('h4 a').text(),
+ link: item.find('a').first().attr('href'),
+ pubDate: timezone(parseDate(item.find('.time').text()), 8),
+ imgsrc: item.find('a img').attr('src'),
+ };
+ });
+
+ const items = await Promise.all(list.map((item) => parseDyArticle(charset, item, ctx.cache.tryGet)));
+
+ ctx.state.data = {
+ title: `${$('head title').text()} - 网易号`,
+ link: url,
+ description: $('.icon_line.desc').text(),
+ image: $('.head_img').attr('src'),
+ item: items,
+ author: $('h2').text(),
+ };
+};
diff --git a/lib/v2/netease/exclusive.js b/lib/v2/163/exclusive.js
similarity index 100%
rename from lib/v2/netease/exclusive.js
rename to lib/v2/163/exclusive.js
diff --git a/lib/v2/netease/maintainer.js b/lib/v2/163/maintainer.js
similarity index 54%
rename from lib/v2/netease/maintainer.js
rename to lib/v2/163/maintainer.js
index 8b73669a8..c5168ec4b 100644
--- a/lib/v2/netease/maintainer.js
+++ b/lib/v2/163/maintainer.js
@@ -1,6 +1,11 @@
module.exports = {
'/exclusive/:id?': ['nczitzk'],
+ '/ds/:id': ['luyuhuang'],
+ '/dy/:id': ['HendricksZheng'],
+ '/dy2/:id': ['mjysci'],
+ '/news/rank/:category?/:type?/:time?': ['nczitzk'],
+ '/news/special/:type?': ['nczitzk'],
+ '/open/vip': ['hoilc'],
'/renjian/:category?': ['nczitzk'],
'/today/:need_content?': ['nczitzk'],
- '/news/rank/:category?/:type?/:time?': ['nczitzk'],
};
diff --git a/lib/v2/netease/rank.js b/lib/v2/163/news/rank.js
similarity index 77%
rename from lib/v2/netease/rank.js
rename to lib/v2/163/news/rank.js
index 2c51fcc3d..442ecda9e 100644
--- a/lib/v2/netease/rank.js
+++ b/lib/v2/163/news/rank.js
@@ -3,7 +3,7 @@ const cheerio = require('cheerio');
const iconv = require('iconv-lite');
const { parseDate } = require('@/utils/parse-date');
-const rootUrl = 'http://news.163.com';
+const rootUrl = 'https://news.163.com';
const config = {
whole: {
@@ -23,7 +23,7 @@ const config = {
title: '体育',
},
money: {
- link: 'http://money.163.com/special/002526BH/rank.html',
+ link: 'https://money.163.com/special/002526BH/rank.html',
title: '财经',
},
tech: {
@@ -99,21 +99,27 @@ module.exports = async (ctx) => {
const list = $('div.tabContents')
.eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : type === 'click' ? 0 : 2))
.find('table tbody tr td a')
- .map((_, item) => {
+ .toArray()
+ .map((item) => {
item = $(item);
return {
link: item.attr('href'),
};
- })
- .get();
+ });
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
try {
- const category = item.link.split('.163.com')[0].split('//').pop().split('.').pop();
- const link = `https://3g.163.com/${category}/article/${item.link.split('/').pop()}`;
+ let link;
+ if (category === 'auto' || category === 'house' || category === 'travel') {
+ const category = item.link.split('.163.com')[0].split('//').pop().split('.').pop();
+ link = `https://3g.163.com/${category}/article/${item.link.split('/').pop()}`;
+ } else {
+ const pathname = new URL(item.link).pathname;
+ link = `https://3g.163.com${pathname}`;
+ }
const detailResponse = await got({
method: 'get',
@@ -121,16 +127,19 @@ module.exports = async (ctx) => {
});
const content = cheerio.load(detailResponse.data);
- content('.bot_word').remove();
+ content('.bot_word, .js-open-app, .s-img').remove();
content('video').each(function () {
content(this).attr('src', content(this).attr('data-src'));
});
+ content('.article-body .image-lazy').each((_, elem) => {
+ elem.attribs.src = elem.attribs['data-src'] ? elem.attribs['data-src'] : elem.attribs.src;
+ });
item.title = content('meta[property="og:title"]').attr('content').replace('_手机网易网', '');
item.pubDate = parseDate(content('meta[property="og:release_date"]').attr('content'));
- item.description = content('.content').html();
+ item.description = content('.article-body').html();
} catch (err) {
- return Promise.resolve('');
+ return '';
}
return item;
@@ -138,17 +147,9 @@ module.exports = async (ctx) => {
)
);
- for (let i = 0; i < items.length; i++) {
- if (items[i] === undefined) {
- items.splice(i, 1);
- } else if (items[i].title === undefined) {
- items.splice(i, 1);
- }
- }
-
ctx.state.data = {
title: `网易新闻${timeRange[time].title}${type === 'click' ? '点击' : '跟帖'}榜 - ${cfg.title}`,
link: currentUrl,
- item: items,
+ item: items.filter((item) => item),
};
};
diff --git a/lib/routes/netease/news/special.js b/lib/v2/163/news/special.js
similarity index 80%
rename from lib/routes/netease/news/special.js
rename to lib/v2/163/news/special.js
index a5fc44e43..093423ec2 100644
--- a/lib/routes/netease/news/special.js
+++ b/lib/v2/163/news/special.js
@@ -1,5 +1,5 @@
const got = require('@/utils/got');
-const date = require('@/utils/date');
+const { parseDate } = require('@/utils/parse-date');
const cheerio = require('cheerio');
const typeMap = {
1: '轻松一刻',
@@ -73,8 +73,8 @@ module.exports = async (ctx) => {
default:
break;
}
- const url = `https://3g.163.com/touch/reconstruct/article/list/${type}/0-10.html`;
- const response = await got.get(url);
+ const url = `https://3g.163.com/touch/reconstruct/article/list/${type}/0-20.html`;
+ const response = await got(url);
const data = response.data;
const matches = data.replace(/\s/g, '').match(/artiList\((.*?)\]\}\)/);
const articlelist0 = matches[1].replace(/".*?wangning/, '"articles') + ']}';
@@ -82,11 +82,8 @@ module.exports = async (ctx) => {
const articles = articlelist.articles;
const items = await Promise.all(
- articles.map(async (article) => {
- const title = article.title;
+ articles.map((article) => {
let url = article.url;
- const time0 = article.ptime;
- const time = time0.slice(0, 10) + ' ' + time0.slice(10);
if (url === null || article.skipType === 'video') {
const skipurl = article.skipURL;
const vid = skipurl.match(/vid=(.*?)$/);
@@ -94,20 +91,16 @@ module.exports = async (ctx) => {
url = `https://3g.163.com/exclusive/video/${vid[1]}.html`;
}
}
- const content = await ctx.cache.tryGet(url, async () => {
- const article_response = await got.get(url);
+ return ctx.cache.tryGet(url, async () => {
+ const article_response = await got(url);
const $ = cheerio.load(article_response.data);
- return $('div[class="content"]').html() ? $('div[class="content"]').html() : $('div[class="video"]').html();
- });
+ article.link = url;
+ article.description = $('.article-body').html() ? $('.article-body').html() : $('div[class="video"]').html();
+ article.pubDate = parseDate(article.ptime);
- const list = {
- title,
- link: url,
- description: content,
- pubDate: date(time),
- };
- return Promise.resolve(list);
+ return article;
+ });
})
);
diff --git a/lib/v2/163/open/vip.js b/lib/v2/163/open/vip.js
new file mode 100644
index 000000000..6cbdfd406
--- /dev/null
+++ b/lib/v2/163/open/vip.js
@@ -0,0 +1,63 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+module.exports = async (ctx) => {
+ const url = 'https://vip.open.163.com';
+
+ const list_response = await got(url);
+ const $ = cheerio.load(list_response.data);
+ const initialState = JSON.parse(
+ $('script')
+ .text()
+ .match(/window\.__INITIAL_STATE__=(.*);\(function\(\)\{var/)[1]
+ );
+
+ const list = Object.values(initialState.courseindex.myModules).flatMap((mod) =>
+ mod.contents.map((item) => ({
+ title: `${item.title} - ${item.subtitle}`,
+ author: item.authorName,
+ pubDate: parseDate(item.publishTime, 'x'),
+ link: `${url}/courses/${item.courseUid}/`,
+ courseUid: item.courseUid,
+ category: mod.name,
+ }))
+ );
+
+ const items = await Promise.all(
+ list.map((item) =>
+ ctx.cache.tryGet(item.link, async () => {
+ const {
+ data: { data },
+ } = await got.post(`${url}/open/trade/pc/course/getCourseInfo.do`, {
+ form: {
+ courseUid: item.courseUid,
+ version: 1,
+ },
+ });
+
+ const $ = cheerio.load(data.courseInfo.description, null, false);
+ $('img').each((_, img) => {
+ img.attribs.src = img.attribs.src.split('?')[0];
+ delete img.attribs.width;
+ });
+
+ item.category = [item.category, data.courseInfo.firstClassifyName, data.courseInfo.secondClassifyName];
+ item.description = art(path.join(__dirname, '../templates/open.art'), {
+ data,
+ description: $.html(),
+ });
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: '网易公开课 - 精品课程',
+ link: url,
+ item: items,
+ };
+};
diff --git a/lib/v2/163/radar.js b/lib/v2/163/radar.js
new file mode 100644
index 000000000..8e5880e56
--- /dev/null
+++ b/lib/v2/163/radar.js
@@ -0,0 +1,69 @@
+const dy2 = {
+ title: '网易号(通用)',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-hao',
+ source: ['/dy/media/:id', '/news/sub/:id'],
+ target: (params) => `/163/dy2/${params.id.replace('.html', '')}`,
+};
+
+module.exports = {
+ '163.com': {
+ _name: '网易',
+ '.': [dy2],
+ '3g': [
+ dy2,
+ {
+ title: '独家栏目',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-du-jia-lan-mu',
+ source: ['/touch/exclusive/sub/:id'],
+ target: '/163/exclusive/:id?',
+ },
+ ],
+ 'c.m': [dy2],
+ ds: [
+ {
+ title: '大神',
+ docs: 'https://docs.rsshub.app/game.html#wang-yi-da-shen',
+ source: '/user/:id',
+ target: '/163/ds/:id',
+ },
+ ],
+ m: [
+ {
+ title: '今日关注',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-jin-ri-guan-zhu',
+ source: ['/'],
+ target: '/163/today',
+ },
+ ],
+ news: [
+ {
+ title: '排行榜',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-pai-hang-bang',
+ },
+ ],
+ renjian: [
+ {
+ title: '人间',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-ren-jian',
+ source: ['/:category', '/'],
+ target: '/163/renjian/:category?',
+ },
+ ],
+ 'vip.open': [
+ {
+ title: '公开课 精品课程',
+ docs: 'https://docs.rsshub.app/study.html#wang-yi-gong-kai-ke',
+ source: ['/'],
+ target: '/163/open/vip',
+ },
+ ],
+ 'wp.m': [
+ {
+ title: '今日关注',
+ docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen',
+ source: ['/163/html/newsapp/todayFocus/index.html', '/'],
+ target: '/163/today',
+ },
+ ],
+ },
+};
diff --git a/lib/v2/netease/renjian.js b/lib/v2/163/renjian.js
similarity index 77%
rename from lib/v2/netease/renjian.js
rename to lib/v2/163/renjian.js
index 3f5f78b28..41be6770a 100644
--- a/lib/v2/netease/renjian.js
+++ b/lib/v2/163/renjian.js
@@ -2,6 +2,7 @@ const got = require('@/utils/got');
const cheerio = require('cheerio');
const iconv = require('iconv-lite');
const { parseDate } = require('@/utils/parse-date');
+const timezone = require('@/utils/timezone');
const titles = {
texie: '特写',
@@ -14,8 +15,8 @@ const titles = {
module.exports = async (ctx) => {
const category = ctx.params.category ?? 'texie';
- const rootUrl = 'http://renjian.163.com';
- const currentUrl = `${rootUrl}/special/renjian_${category}`;
+ const rootUrl = 'https://renjian.163.com';
+ const currentUrl = `${rootUrl}/special/renjian_${category}/`;
const response = await got({
method: 'get',
@@ -30,21 +31,21 @@ module.exports = async (ctx) => {
const urls = data.match(/url:"(.*)",/g);
if (urls) {
- items = urls.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 15).map((item) => ({
+ items = urls.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 50).map((item) => ({
link: item.match(/url:"(.*)",/)[1],
}));
} else {
const $ = cheerio.load(data);
items = $('.article h3 a')
- .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 15)
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 50)
+ .toArray()
.map((_, item) => {
item = $(item);
return {
link: item.attr('href'),
};
- })
- .get();
+ });
}
items = await Promise.all(
@@ -57,9 +58,11 @@ module.exports = async (ctx) => {
const content = cheerio.load(detailResponse.data);
item.title = content('h1').text();
- item.author = content('.author_txt name').text();
+ item.author = content('script')
+ .text()
+ .match(/renjian_author = '(.*)'/)[1];
item.description = content('#endText').html() ?? content('#content').html();
- item.pubDate = parseDate(content('.pub_time').text() ?? content('.post_info').text().split('来源:')[0].trim());
+ item.pubDate = timezone(parseDate(content('.pub_time').text() ?? content('.post_info').text().split('来源:')[0].trim()), 8);
return item;
})
diff --git a/lib/v2/netease/router.js b/lib/v2/163/router.js
similarity index 51%
rename from lib/v2/netease/router.js
rename to lib/v2/163/router.js
index f93652a8c..b23f3a7f2 100644
--- a/lib/v2/netease/router.js
+++ b/lib/v2/163/router.js
@@ -1,6 +1,11 @@
module.exports = function (router) {
router.get('/exclusive/:id?', require('./exclusive'));
+ router.get('/ds/:id', require('./ds'));
+ router.get('/dy/:id', require('./dy'));
+ router.get('/dy2/:id', require('./dy2'));
+ router.get('/news/rank/:category?/:type?/:time?', require('./news/rank'));
+ router.get('/news/special/:type?', require('./news/special'));
+ router.get('/open/vip', require('./open/vip'));
router.get('/renjian/:category?', require('./renjian'));
router.get('/today/:need_content?', require('./today'));
- router.get('/news/rank/:category?/:type?/:time?', require('./rank'));
};
diff --git a/lib/v2/163/templates/ds.art b/lib/v2/163/templates/ds.art
new file mode 100644
index 000000000..8a493d218
--- /dev/null
+++ b/lib/v2/163/templates/ds.art
@@ -0,0 +1,7 @@
+{{ text }}
+
+{{ each medias }}
+ {{ if $value.mimeType.indexOf('image') > -1 }}
+
+ {{ /if }}
+{{ /each }}
diff --git a/lib/v2/163/templates/dy.art b/lib/v2/163/templates/dy.art
new file mode 100644
index 000000000..c78f313c9
--- /dev/null
+++ b/lib/v2/163/templates/dy.art
@@ -0,0 +1,6 @@
+{{ if imgsrc }}
+
+{{ /if }}
+{{ if postBody }}
+{{@ postBody }}
+{{ /if }}
diff --git a/lib/v2/netease/templates/exclusive.art b/lib/v2/163/templates/exclusive.art
similarity index 100%
rename from lib/v2/netease/templates/exclusive.art
rename to lib/v2/163/templates/exclusive.art
diff --git a/lib/v2/163/templates/open.art b/lib/v2/163/templates/open.art
new file mode 100644
index 000000000..b6fae699d
--- /dev/null
+++ b/lib/v2/163/templates/open.art
@@ -0,0 +1,12 @@
+{{ set chapterList = data.movieChapterList.length ? data.movieChapterList : data.audioChapterList; }}
+{{ if chapterList }}
+
+{{ each chapterList chapter chapterIndex }}
+
第{{ chapterIndex + 1 }}章 {{ chapter.title }}
+ {{ each chapter.contentList content contentIndex }}
+ {{ contentIndex + 1 }} {{ content.title }}
+ {{ /each }}
+{{ /each }}
+
+{{ /if }}
+{{@ description }}
diff --git a/lib/v2/netease/today.js b/lib/v2/163/today.js
similarity index 91%
rename from lib/v2/netease/today.js
rename to lib/v2/163/today.js
index b14f008b5..7b15609db 100644
--- a/lib/v2/netease/today.js
+++ b/lib/v2/163/today.js
@@ -35,8 +35,8 @@ module.exports = async (ctx) => {
content('.bot_word').remove();
- content('figure[data-echo]').each(function () {
- content(this).html(`
`);
+ content('img').each((_, img) => {
+ img.attribs.src = img.attribs['data-src'] ? img.attribs['data-src'] : img.attribs.src;
});
item.description = content('.content, article').html();
diff --git a/lib/v2/163/utils.js b/lib/v2/163/utils.js
new file mode 100644
index 000000000..d952bc736
--- /dev/null
+++ b/lib/v2/163/utils.js
@@ -0,0 +1,40 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const iconv = require('iconv-lite');
+const { art } = require('@/utils/render');
+const path = require('path');
+
+const parseDyArticle = (charset, item, tryGet) =>
+ tryGet(item.link, async () => {
+ const response = await got(item.link, {
+ responseType: 'buffer',
+ });
+
+ const html = iconv.decode(response.data, charset);
+ const $ = cheerio.load(html);
+
+ $('.post_main img').each((_, i) => {
+ if (!i.attribs.src) {
+ return;
+ }
+ const url = new URL(i.attribs.src);
+ if (url.host === 'nimg.ws.126.net') {
+ i.attribs.src = url.searchParams.get('url');
+ }
+ });
+
+ item.description = art(path.join(__dirname, 'templates/dy.art'), {
+ imgsrc: item.imgsrc?.split('?')[0],
+ postBody: $('.post_body').html(),
+ });
+
+ item.feedLink = $('.post_wemedia_name a').attr('href');
+ item.feedDescription = $('.post_wemedia_title').text();
+ item.feedImage = $('.post_wemedia_avatar img').attr('src');
+
+ return item;
+ });
+
+module.exports = {
+ parseDyArticle,
+};
diff --git a/lib/v2/netease/radar.js b/lib/v2/netease/radar.js
deleted file mode 100644
index 41ea928b5..000000000
--- a/lib/v2/netease/radar.js
+++ /dev/null
@@ -1,37 +0,0 @@
-module.exports = {
- '163.com': {
- _name: '网易',
- '': [
- {
- title: '独家栏目',
- docs: 'https://docs.rsshub.app/new-media.html#wang-yi-du-jia-lan-mu',
- source: ['/'],
- target: '/netease/exclusive/:id?',
- },
- ],
- renjian: [
- {
- title: '人间',
- docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-ren-jian',
- source: ['/:category', '/'],
- target: '/netease/renjian/:category?',
- },
- ],
- news: [
- {
- title: '排行榜',
- docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-pai-hang-bang',
- source: ['/:category', '/'],
- target: '/netease/news/rank/:category?/:type?/:time?',
- },
- ],
- m: [
- {
- title: '今日关注',
- docs: 'https://docs.rsshub.app/new-media.html#wang-yi-xin-wen-jin-ri-guan-zhu',
- source: ['/'],
- target: '/netease/today/:need_content?',
- },
- ],
- },
-};