mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-08-29 01:53:47 +08:00
fix(route): change to use api get data and refactor to v2 (#11809)
* fix(route): change to use api get data and refactor to v2 * fix(route): remove unreachable condition * refactor: change route path feat!: remove `/open163/latest` since `https://c.open.163.com/open/getLatestMovies.do` is broken * fix: radar ---------
This commit is contained in:
@@ -166,11 +166,6 @@
|
||||
'xiaomi.cn': { _name: '小米社区', www: [{ title: '圈子', docs: 'https://docs.rsshub.app/bbs.html#xiao-mi-she-qu', source: '/board/:boardId', target: '/mi/bbs/board/:boardId' }] },
|
||||
'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: '云音乐 - 用户歌单',
|
||||
|
||||
+1
-1
@@ -759,7 +759,7 @@ Example:`https://www.iyingdi.com/tz/people/55547` ,id 是 `55547`
|
||||
|
||||
### 用户发帖
|
||||
|
||||
<Route author="luyuhuang" example="/netease/ds/63dfbaf4117741daaf73404601165843" path="/netease/ds/:id" :paramsDesc="['用户ID']"/>
|
||||
<Route author="luyuhuang" example="/163/ds/63dfbaf4117741daaf73404601165843" path="/163/ds/:id" :paramsDesc="['用户ID']"/>
|
||||
|
||||
## 小黑盒
|
||||
|
||||
|
||||
+8
-8
@@ -3792,7 +3792,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 栏目
|
||||
|
||||
<Route author="nczitzk" example="/netease/exclusive/qsyk" path="/netease/exclusive/:id?" :paramsDesc="['栏目, 默认为首页']">
|
||||
<Route author="nczitzk" example="/163/exclusive/qsyk" path="/163/exclusive/:id?" :paramsDesc="['栏目, 默认为首页']">
|
||||
|
||||
| 分类 | 编号 |
|
||||
| ---- | ---- |
|
||||
@@ -3819,7 +3819,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 更新
|
||||
|
||||
<Route author="HendricksZheng" example="/netease/dy/W4983108759592548559" path="/netease/dy/:id" :paramsDesc="['网易号 ID', '见如下说明']">
|
||||
<Route author="HendricksZheng" example="/163/dy/W4983108759592548559" path="/163/dy/:id" :paramsDesc="['网易号 ID', '见如下说明']">
|
||||
|
||||
1. 在[网易号搜索页面](https://dy.163.com/v2/media/tosearch.html) 搜索想要订阅的网易号。
|
||||
2. 打开网易号的任意文章。
|
||||
@@ -3827,9 +3827,9 @@ column 为 third 时可选的 category:
|
||||
|
||||
</Route>
|
||||
|
||||
## 网易号(通用)
|
||||
### 网易号(通用)
|
||||
|
||||
<Route author="mjysci" example="/netease/dy2/T1555591616739" path="/netease/dy2/:id" :paramsDesc="['id,该网易号主页网址最后一项html的文件名']" anticrawler="1"/>
|
||||
<Route author="mjysci" example="/163/dy2/T1555591616739" path="/163/dy2/:id" :paramsDesc="['id,该网易号主页网址最后一项html的文件名']" anticrawler="1"/>
|
||||
|
||||
优先使用方法一,若是网易号搜索页面搜不到的小众网易号(文章页面不含`data-wemediaid`)则可使用此法。
|
||||
触发反爬会只抓取到标题,建议自建。
|
||||
@@ -3844,7 +3844,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 今日关注
|
||||
|
||||
<Route author="nczitzk" example="/netease/today" path="/netease/today/:need_content?" :paramsDesc="['需要获取全文,填写 true/yes 表示需要,默认需要']">
|
||||
<Route author="nczitzk" example="/163/today" path="/163/today/:need_content?" :paramsDesc="['需要获取全文,填写 true/yes 表示需要,默认需要']">
|
||||
|
||||
::: tip 提示
|
||||
|
||||
@@ -3856,7 +3856,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 排行榜
|
||||
|
||||
<Route author="nczitzk" example="/netease/news/rank/whole/click/day" path="/netease/news/rank/:category?/:type?/:time?" :paramsDesc="['新闻分类,参见下表,默认为“全站”','排行榜类型,“点击榜”对应`click`,“跟贴榜”对应`follow`,默认为“点击榜”','统计时间,“1小时”对应`hour`,“24小时”对应`day`,“本周”对应`week`,“本月”对应`month`,默认为“24小时”']">
|
||||
<Route author="nczitzk" example="/163/news/rank/whole/click/day" path="/163/news/rank/:category?/:type?/:time?" :paramsDesc="['新闻分类,参见下表,默认为“全站”','排行榜类型,“点击榜”对应`click`,“跟贴榜”对应`follow`,默认为“点击榜”','统计时间,“1小时”对应`hour`,“24小时”对应`day`,“本周”对应`week`,“本月”对应`month`,默认为“24小时”']">
|
||||
|
||||
::: tip 提示
|
||||
|
||||
@@ -3878,7 +3878,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 专栏
|
||||
|
||||
<Route author="Solist-X" example="/netease/news/special/1" path="/netease/news/special/:type?" :paramsDesc="['栏目']">
|
||||
<Route author="Solist-X" example="/163/news/special/1" path="/163/news/special/:type?" :paramsDesc="['栏目']">
|
||||
|
||||
| 轻松一刻 | 槽值 | 人间 | 大国小民 | 三三有梗 | 数读 | 看客 | 下划线 | 谈心社 | 哒哒 | 胖编怪聊 | 曲一刀 | 今日之声 | 浪潮 | 沸点 |
|
||||
| ---- | -- | -- | ---- | ---- | -- | -- | --- | --- | -- | ---- | --- | ---- | -- | -- |
|
||||
@@ -3888,7 +3888,7 @@ column 为 third 时可选的 category:
|
||||
|
||||
### 人间
|
||||
|
||||
<Route author="nczitzk" example="/netease/renjian/texie" path="/netease/renjian/:category?" :paramsDesc="['分类,见下表,默认为特写']">
|
||||
<Route author="nczitzk" example="/163/renjian/texie" path="/163/renjian/:category?" :paramsDesc="['分类,见下表,默认为特写']">
|
||||
|
||||
| 特写 | 记事 | 大写 | 好读 | 看客 |
|
||||
| ----- | ----- | ----- | ----- | ----- |
|
||||
|
||||
@@ -472,10 +472,6 @@ path="/ctfhub/upcoming/:limit?"
|
||||
|
||||
<Route author="hoilc" example="/open163/vip" path="/open163/vip" radar="1" rssbud="1"/>
|
||||
|
||||
### 最新课程
|
||||
|
||||
<Route author="hoilc" example="/open163/latest" path="/open163/latest" radar="1" rssbud="1"/>
|
||||
|
||||
## 下厨房
|
||||
|
||||
### 用户作品
|
||||
|
||||
@@ -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: '云音乐 - 用户歌单',
|
||||
|
||||
+6
-6
@@ -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'));
|
||||
|
||||
@@ -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 <a href="https://docs.rsshub.app/game.html#wang-yi-da-shen">https://docs.rsshub.app/game.html#wang-yi-da-shen</a>');
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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(),
|
||||
};
|
||||
};
|
||||
@@ -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(`<img src="${testRealURL[1]}" />`);
|
||||
}
|
||||
}
|
||||
|
||||
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 !== ''),
|
||||
};
|
||||
};
|
||||
@@ -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 = `<div style="text-align: center;">${toc}` + s('.CourseCommonDetail_contentItem').first().html() + `</div>`;
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: '网易公开课 - 精品课程',
|
||||
link: url,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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(),
|
||||
};
|
||||
};
|
||||
@@ -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'],
|
||||
};
|
||||
@@ -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),
|
||||
};
|
||||
};
|
||||
@@ -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;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -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;
|
||||
})
|
||||
@@ -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'));
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
{{ text }}
|
||||
|
||||
{{ each medias }}
|
||||
{{ if $value.mimeType.indexOf('image') > -1 }}
|
||||
<img src="{{$value.url}}">
|
||||
{{ /if }}
|
||||
{{ /each }}
|
||||
@@ -0,0 +1,6 @@
|
||||
{{ if imgsrc }}
|
||||
<img src="{{ imgsrc }}"><br>
|
||||
{{ /if }}
|
||||
{{ if postBody }}
|
||||
{{@ postBody }}
|
||||
{{ /if }}
|
||||
@@ -0,0 +1,12 @@
|
||||
{{ set chapterList = data.movieChapterList.length ? data.movieChapterList : data.audioChapterList; }}
|
||||
{{ if chapterList }}
|
||||
<div class="toc">
|
||||
{{ each chapterList chapter chapterIndex }}
|
||||
<h3>第{{ chapterIndex + 1 }}章 {{ chapter.title }}</h3>
|
||||
{{ each chapter.contentList content contentIndex }}
|
||||
<h4>{{ contentIndex + 1 }} {{ content.title }}</h4>
|
||||
{{ /each }}
|
||||
{{ /each }}
|
||||
</div>
|
||||
{{ /if }}
|
||||
{{@ description }}
|
||||
@@ -35,8 +35,8 @@ module.exports = async (ctx) => {
|
||||
|
||||
content('.bot_word').remove();
|
||||
|
||||
content('figure[data-echo]').each(function () {
|
||||
content(this).html(`<img src="${content(this).attr('data-echo')}">`);
|
||||
content('img').each((_, img) => {
|
||||
img.attribs.src = img.attribs['data-src'] ? img.attribs['data-src'] : img.attribs.src;
|
||||
});
|
||||
|
||||
item.description = content('.content, article').html();
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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?',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user