feat(route): add juejin news (#7969)
* feat(route): add juejin news * feat(route): add juejin news * fix(route): juejin news pubDate * fix: fix utility * refactor: migrate to v2 * fix: typo Co-authored-by: TonyRL <TonyRL@users.noreply.github.com>
This commit is contained in:
parent
8a8dde7432
commit
950bfa61ed
|
|
@ -151,22 +151,6 @@
|
|||
},
|
||||
'algocasts.io': { _name: 'AlgoCasts', '.': [{ title: '视频更新', docs: 'https://docs.rsshub.app/programming.html#algocasts', source: '/episodes', target: '/algocasts' }] },
|
||||
'soulapp.cn': { _name: 'Soul', '.': [{ title: '瞬间更新', docs: 'https://docs.rsshub.app/social-media.html#soul' }] },
|
||||
'juejin.cn': {
|
||||
_name: '掘金',
|
||||
'.': [
|
||||
{ title: '标签', docs: 'https://docs.rsshub.app/programming.html#jue-jin-biao-qian', source: '/tag/:tag', target: '/juejin/tag/:tag' },
|
||||
{ title: '小册', docs: 'https://docs.rsshub.app/programming.html#jue-jin-xiao-ce', source: '/books', target: '/juejin/books' },
|
||||
{
|
||||
title: '沸点',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-fei-dian',
|
||||
source: ['/pins/:type', '/pins/topic/:type'],
|
||||
target: (params) => (params.type !== 'recommended' ? '/juejin/pins/:type' : '/juejin/pins'),
|
||||
},
|
||||
{ title: '专栏', docs: 'https://docs.rsshub.app/programming.html#jue-jin-zhuan-lan', source: ['/user/:id', '/user/:id/posts'], target: '/juejin/posts/:id' },
|
||||
{ title: '收藏集', docs: 'https://docs.rsshub.app/programming.html#jue-jin-shou-cang-ji', source: ['/user/:id', '/user/:id/collections'], target: '/juejin/collections/:id' },
|
||||
{ title: '单个收藏夹', docs: 'https://docs.rsshub.app/programming.html#jue-jin-dan-ge-shou-cang-jia', source: '/collection/:collectionId', target: '/juejin/collection/:collectionId' },
|
||||
],
|
||||
},
|
||||
'anime1.me': {
|
||||
_name: 'Anime1',
|
||||
'.': [
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ GitHub 官方也提供了一些 RSS:
|
|||
|
||||
### 分类
|
||||
|
||||
<Route author="DIYgod" example="/juejin/category/frontend" path="/juejin/category/:category" :paramsDesc="['分类名']">
|
||||
<Route author="DIYgod" example="/juejin/category/frontend" path="/juejin/category/:category" :paramsDesc="['分类名']" radar="1" rssbud="1">
|
||||
|
||||
| 后端 | 前端 | Android | iOS | 人工智能 | 开发工具 | 代码人生 | 阅读 |
|
||||
| ------- | -------- | ------- | --- | ---- | ------- | ------ | ------- |
|
||||
|
|
@ -711,11 +711,11 @@ GitHub 官方也提供了一些 RSS:
|
|||
|
||||
### 标签
|
||||
|
||||
<Route author="isheng5" example="/juejin/tag/架构" path="/juejin/tag/:tag" :paramsDesc="['标签名, 可在标签 URL 中找到']"/>
|
||||
<Route author="isheng5" example="/juejin/tag/架构" path="/juejin/tag/:tag" :paramsDesc="['标签名, 可在标签 URL 中找到']" radar="1" rssbud="1"/>
|
||||
|
||||
### 热门
|
||||
|
||||
<Route author="moaix" example="/juejin/trending/ios/monthly" path="/juejin/trending/:category/:type" :paramsDesc="['分类名', '类型']">
|
||||
<Route author="moaix" example="/juejin/trending/ios/monthly" path="/juejin/trending/:category/:type" :paramsDesc="['分类名', '类型']" radar="1" rssbud="1">
|
||||
|
||||
| category | 标签 |
|
||||
| -------- | ------- |
|
||||
|
|
@ -741,13 +741,13 @@ GitHub 官方也提供了一些 RSS:
|
|||
|
||||
### 小册
|
||||
|
||||
<Route author="xyqfer" example="/juejin/books" path="/juejin/books"/>
|
||||
<Route author="xyqfer" example="/juejin/books" path="/juejin/books" radar="1" rssbud="1"/>
|
||||
|
||||
> 掘金小册需要付费订阅,RSS 仅做更新提醒,不含付费内容.
|
||||
|
||||
### 沸点
|
||||
|
||||
<Route author="xyqfer laampui" example="/juejin/pins/6824710202487472141" :paramsDesc="['默认为 recommend,见下表']" path="/juejin/pins/:type?">
|
||||
<Route author="xyqfer laampui" example="/juejin/pins/6824710202487472141" :paramsDesc="['默认为 recommend,见下表']" path="/juejin/pins/:type?" radar="1" rssbud="1">
|
||||
|
||||
| 推荐 | 热门 | 上班摸鱼 | 内推招聘 | 一图胜千言 | 今天学到了 | 每天一道算法题 | 开发工具推荐 | 树洞一下 |
|
||||
| --------- | --- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
|
||||
|
|
@ -755,21 +755,29 @@ GitHub 官方也提供了一些 RSS:
|
|||
|
||||
</Route>
|
||||
|
||||
### 专栏
|
||||
### 用户专栏
|
||||
|
||||
<Route author="Maecenas" example="/juejin/posts/3051900006845944" path="/juejin/posts/:id" :paramsDesc="['用户 id, 可在用户页 URL 中找到']" radar="1" rssbud="1"/>
|
||||
<Route author="Maecenas" example="/juejin/posts/3051900006845944" path="/juejin/posts/:id" :paramsDesc="['用户 id, 可在用户页 URL 中找到']" radar="1" rssbud="1" radar="1" rssbud="1"/>
|
||||
|
||||
### 收藏集
|
||||
|
||||
<Route author="isQ" example="/juejin/collections/1697301682482439" path="/juejin/collections/:userId" :paramsDesc="['用户唯一标志符, 在浏览器地址栏URL中能够找到']"/>
|
||||
<Route author="isQ" example="/juejin/collections/1697301682482439" path="/juejin/collections/:userId" :paramsDesc="['用户唯一标志符, 在浏览器地址栏URL中能够找到']" radar="1" rssbud="1"/>
|
||||
|
||||
### 单个收藏夹
|
||||
|
||||
<Route author="isQ" example="/juejin/collection/6845243180586123271" path="/juejin/collection/:collectionId" :paramsDesc="['收藏夹唯一标志符, 在浏览器地址栏URL中能够找到']"/>
|
||||
<Route author="isQ" example="/juejin/collection/6845243180586123271" path="/juejin/collection/:collectionId" :paramsDesc="['收藏夹唯一标志符, 在浏览器地址栏URL中能够找到']" radar="1" rssbud="1"/>
|
||||
|
||||
### 分享
|
||||
|
||||
<Route author="qiwihui" example="/juejin/shares/56852b2460b2a099cdc1d133" path="/juejin/shares/:userId" :paramsDesc="['用户 id, 可在用户页 URL 中找到']"/>
|
||||
<Route author="qiwihui" example="/juejin/shares/56852b2460b2a099cdc1d133" path="/juejin/shares/:userId" :paramsDesc="['用户 id, 可在用户页 URL 中找到']" radar="1" rssbud="1"/>
|
||||
|
||||
### 专栏
|
||||
|
||||
<Route author="xiangzy1" example="/juejin/column/6960559453037199391" path="/juejin/column/:id" :paramsDesc="['专栏 id, 可在专栏页 URL 中找到']" radar="1" rssbud="1"/>
|
||||
|
||||
### 资讯
|
||||
|
||||
<Route author="cancergary" example="/juejin/news/739332228916791" path="/juejin/news/:userId" :paramsDesc="['用户 id, 可在用户页 URL 中找到']" radar="1" rssbud="1"/>
|
||||
|
||||
## 开源中国
|
||||
|
||||
|
|
|
|||
|
|
@ -207,47 +207,6 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
},
|
||||
'juejin.cn': {
|
||||
_name: '掘金',
|
||||
'.': [
|
||||
{
|
||||
title: '标签',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-biao-qian',
|
||||
source: '/tag/:tag',
|
||||
target: '/juejin/tag/:tag',
|
||||
},
|
||||
{
|
||||
title: '小册',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-xiao-ce',
|
||||
source: '/books',
|
||||
target: '/juejin/books',
|
||||
},
|
||||
{
|
||||
title: '沸点',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-fei-dian',
|
||||
source: ['/pins/:type', '/pins/topic/:type'],
|
||||
target: (params) => (params.type !== 'recommended' ? '/juejin/pins/:type' : '/juejin/pins'),
|
||||
},
|
||||
{
|
||||
title: '专栏',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-zhuan-lan',
|
||||
source: ['/user/:id', '/user/:id/posts'],
|
||||
target: '/juejin/posts/:id',
|
||||
},
|
||||
{
|
||||
title: '收藏集',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-shou-cang-ji',
|
||||
source: ['/user/:id', '/user/:id/collections'],
|
||||
target: '/juejin/collections/:id',
|
||||
},
|
||||
{
|
||||
title: '单个收藏夹',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-dan-ge-shou-cang-jia',
|
||||
source: '/collection/:collectionId',
|
||||
target: '/juejin/collection/:collectionId',
|
||||
},
|
||||
],
|
||||
},
|
||||
'anime1.me': {
|
||||
_name: 'Anime1',
|
||||
'.': [
|
||||
|
|
|
|||
|
|
@ -68,17 +68,18 @@ router.get('/ncm/artist/:id', lazyloadRouteHandler('./routes/ncm/artist'));
|
|||
router.get('/ncm/djradio/:id', lazyloadRouteHandler('./routes/ncm/djradio'));
|
||||
router.get('/ncm/user/playrecords/:uid/:type?', lazyloadRouteHandler('./routes/ncm/userplayrecords'));
|
||||
|
||||
// 掘金
|
||||
router.get('/juejin/category/:category', lazyloadRouteHandler('./routes/juejin/category'));
|
||||
router.get('/juejin/tag/:tag', lazyloadRouteHandler('./routes/juejin/tag'));
|
||||
router.get('/juejin/trending/:category/:type', lazyloadRouteHandler('./routes/juejin/trending'));
|
||||
router.get('/juejin/books', lazyloadRouteHandler('./routes/juejin/books'));
|
||||
router.get('/juejin/pins/:type?', lazyloadRouteHandler('./routes/juejin/pins'));
|
||||
router.get('/juejin/posts/:id', lazyloadRouteHandler('./routes/juejin/posts'));
|
||||
router.get('/juejin/collections/:userId', lazyloadRouteHandler('./routes/juejin/favorites'));
|
||||
router.get('/juejin/collection/:collectionId', lazyloadRouteHandler('./routes/juejin/collection'));
|
||||
router.get('/juejin/shares/:userId', lazyloadRouteHandler('./routes/juejin/shares'));
|
||||
router.get('/juejin/column/:id', lazyloadRouteHandler('./routes/juejin/column'));
|
||||
// 掘金 migrated to v2
|
||||
// router.get('/juejin/category/:category', lazyloadRouteHandler('./routes/juejin/category'));
|
||||
// router.get('/juejin/tag/:tag', lazyloadRouteHandler('./routes/juejin/tag'));
|
||||
// router.get('/juejin/trending/:category/:type', lazyloadRouteHandler('./routes/juejin/trending'));
|
||||
// router.get('/juejin/books', lazyloadRouteHandler('./routes/juejin/books'));
|
||||
// router.get('/juejin/pins/:type?', lazyloadRouteHandler('./routes/juejin/pins'));
|
||||
// router.get('/juejin/posts/:id', lazyloadRouteHandler('./routes/juejin/posts'));
|
||||
// router.get('/juejin/news/:id', lazyloadRouteHandler('./routes/juejin/news'));
|
||||
// router.get('/juejin/collections/:userId', lazyloadRouteHandler('./routes/juejin/favorites'));
|
||||
// router.get('/juejin/collection/:collectionId', lazyloadRouteHandler('./routes/juejin/collection'));
|
||||
// router.get('/juejin/shares/:userId', lazyloadRouteHandler('./routes/juejin/shares'));
|
||||
// router.get('/juejin/column/:id', lazyloadRouteHandler('./routes/juejin/column'));
|
||||
|
||||
// 自如
|
||||
router.get('/ziroom/room/:city/:iswhole/:room/:keyword', lazyloadRouteHandler('./routes/ziroom/room'));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const response = await got({
|
||||
|
|
@ -17,7 +18,7 @@ module.exports = async (ctx) => {
|
|||
${base_info.summary}<br>
|
||||
<strong>价格:</strong> ${base_info.price / 100}元
|
||||
`,
|
||||
pubDate: new Date(base_info.ctime * 1000).toUTCString(),
|
||||
pubDate: parseDate(base_info.ctime * 1000),
|
||||
guid: base_info.booklet_id,
|
||||
}));
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ module.exports = async (ctx) => {
|
|||
|
||||
let originalData = [];
|
||||
if (response.data.data) {
|
||||
originalData = response.data.data.slice(0, 5);
|
||||
originalData = response.data.data;
|
||||
}
|
||||
const resultItems = await util.ProcessFeed(originalData, ctx.cache);
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
module.exports = {
|
||||
'/books': ['xyqfer'],
|
||||
'/category/:category': ['DIYgod'],
|
||||
'/collection/:collectionId': ['isQ'],
|
||||
'/collections/:userId': ['isQ'],
|
||||
'/column/:id': ['xiangzy1'],
|
||||
'/news/:id': ['CancerGary'],
|
||||
'/pins/:type?': ['xyqfer', 'laampui'],
|
||||
'/posts/:id': ['Maecenas'],
|
||||
'/shares/:userId': ['qiwihui'],
|
||||
'/tag/:tag': ['isheng5'],
|
||||
'/trending/:category/:type': ['moaix'],
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
const got = require('@/utils/got');
|
||||
const util = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { id } = ctx.params;
|
||||
|
||||
const response = await got({
|
||||
method: 'post',
|
||||
url: 'https://api.juejin.cn/content_api/v1/news/list_user',
|
||||
json: {
|
||||
user_id: id,
|
||||
sort_type: 2,
|
||||
},
|
||||
});
|
||||
const { data } = response.data;
|
||||
const username = data[0] && data[0].author_user_info && data[0].author_user_info.user_name;
|
||||
const resultItems = await util.ProcessFeed(data, ctx.cache);
|
||||
|
||||
ctx.state.data = {
|
||||
title: `掘金资讯-${username}`,
|
||||
link: `https://juejin.cn/user/${id}/news`,
|
||||
description: `掘金资讯-${username}`,
|
||||
item: resultItems,
|
||||
};
|
||||
};
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const type = ctx.params.type || 'recommend';
|
||||
const type = ctx.params.type ?? 'recommend';
|
||||
const title = {
|
||||
recommend: '推荐',
|
||||
hot: '热门',
|
||||
|
|
@ -35,7 +36,7 @@ module.exports = async (ctx) => {
|
|||
const title = content;
|
||||
const guid = item.msg_id;
|
||||
const link = `https://juejin.cn/pin/${guid}`;
|
||||
const pubDate = new Date(parseInt(item.msg_Info.ctime) * 1000).toUTCString();
|
||||
const pubDate = parseDate(item.msg_Info.ctime * 1000);
|
||||
const author = item.author_user_info.user_name;
|
||||
const imgs = item.msg_Info.pic_list.reduce((imgs, item) => {
|
||||
imgs += `
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
module.exports = {
|
||||
'juejin.cn': {
|
||||
_name: '掘金',
|
||||
'.': [
|
||||
{
|
||||
title: '标签',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-biao-qian',
|
||||
source: '/tag/:tag',
|
||||
target: '/juejin/tag/:tag',
|
||||
},
|
||||
{
|
||||
title: '小册',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-xiao-ce',
|
||||
source: '/books',
|
||||
target: '/juejin/books',
|
||||
},
|
||||
{
|
||||
title: '沸点',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-fei-dian',
|
||||
source: ['/pins/:type', '/pins/topic/:type'],
|
||||
target: (params) => (params.type !== 'recommended' ? '/juejin/pins/:type' : '/juejin/pins'),
|
||||
},
|
||||
{
|
||||
title: '用户专栏',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-zhuan-lan',
|
||||
source: ['/user/:id', '/user/:id/posts'],
|
||||
target: '/juejin/posts/:id',
|
||||
},
|
||||
{
|
||||
title: '收藏集',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-shou-cang-ji',
|
||||
source: ['/user/:id', '/user/:id/collections'],
|
||||
target: '/juejin/collections/:id',
|
||||
},
|
||||
{
|
||||
title: '单个收藏夹',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin-dan-ge-shou-cang-jia',
|
||||
source: '/collection/:collectionId',
|
||||
target: '/juejin/collection/:collectionId',
|
||||
},
|
||||
{
|
||||
title: '分享',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin',
|
||||
source: ['/user/:userId', '/user/:userId/shares'],
|
||||
target: '/juejin/shares/:userId',
|
||||
},
|
||||
{
|
||||
title: '专栏',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin',
|
||||
source: '/column/:id',
|
||||
target: '/juejin/column/:id',
|
||||
},
|
||||
{
|
||||
title: '资讯',
|
||||
docs: 'https://docs.rsshub.app/programming.html#jue-jin',
|
||||
source: ['/user/:id', '/user/:id/news'],
|
||||
target: '/juejin/news/:userId',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
module.exports = (router) => {
|
||||
router.get('/books', require('./books'));
|
||||
router.get('/category/:category', require('./category'));
|
||||
router.get('/collection/:collectionId', require('./collection'));
|
||||
router.get('/collections/:userId', require('./favorites'));
|
||||
router.get('/column/:id', require('./column'));
|
||||
router.get('/news/:id', require('./news'));
|
||||
router.get('/pins/:type?', require('./pins'));
|
||||
router.get('/posts/:id', require('./posts'));
|
||||
router.get('/shares/:userId', require('./shares'));
|
||||
router.get('/tag/:tag', require('./tag'));
|
||||
router.get('/trending/:category/:type', require('./trending'));
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
const md = require('markdown-it')({
|
||||
html: true,
|
||||
});
|
||||
|
|
@ -15,21 +15,29 @@ async function load(id) {
|
|||
});
|
||||
let description;
|
||||
if (response.data.data) {
|
||||
description = md.render(response.data.data.article_info.mark_content);
|
||||
description = md.render(response.data.data.article_info.mark_content) || response.data.data.article_info.content;
|
||||
}
|
||||
|
||||
return { description };
|
||||
}
|
||||
|
||||
const loadNews = async (link) => {
|
||||
const response = await got(link);
|
||||
const $ = cheerio.load(response.data);
|
||||
$('h1.title, .main-box .message').remove();
|
||||
return { description: $('.main-box .article').html() };
|
||||
};
|
||||
|
||||
const ProcessFeed = (list, caches) =>
|
||||
Promise.all(
|
||||
list.map(async (item) => {
|
||||
const pubDate = timezone(parseDate(parseInt(item.article_info.ctime) * 1000), +8);
|
||||
const link = `https://juejin.cn/post/${item.article_id}`;
|
||||
const isArticle = !!item.article_info;
|
||||
const pubDate = parseDate((isArticle ? item.article_info.ctime : item.content_info.ctime) * 1000);
|
||||
const link = `https://juejin.cn${isArticle ? '/post/' + item.article_id : '/news/' + item.content_id}`;
|
||||
// 列表上提取到的信息
|
||||
const single = {
|
||||
title: item.article_info.title,
|
||||
description: (item.article_info.brief_content || '无描述').replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, ''),
|
||||
title: isArticle ? item.article_info.title : item.content_info.title,
|
||||
description: ((isArticle ? item.article_info.brief_content : item.content_info.brief) || '无描述').replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f]/g, ''),
|
||||
pubDate,
|
||||
author: item.author_user_info.user_name,
|
||||
link,
|
||||
|
|
@ -37,7 +45,7 @@ const ProcessFeed = (list, caches) =>
|
|||
|
||||
// 使用tryGet方法从缓存获取内容。
|
||||
// 当缓存中无法获取到链接内容的时候,则使用load方法加载文章内容。
|
||||
const other = await caches.tryGet(link, () => load(item.article_id));
|
||||
const other = await caches.tryGet(link, () => (isArticle ? load(item.article_id) : loadNews(link)));
|
||||
// 合并解析后的结果集作为该篇文章最终的输出结果
|
||||
return { ...single, ...other };
|
||||
})
|
||||
Loading…
Reference in New Issue