mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
fix(route):雪球 基金净值数据来源调整为蛋卷基金 (#9489)
* 雪球基金净值更新调整为蛋卷基金 * Update docs/finance.md Co-authored-by: Tony <TonyRL@users.noreply.github.com> * Update docs/finance.md Co-authored-by: Tony <TonyRL@users.noreply.github.com> * refactor: migrate to v2 * fix: parseDate * fix: fund unnecessary String() * feat: add radar * fix: stock comments template * style: add a linebreak * docs: fund example path
This commit is contained in:
+6
-2
@@ -289,9 +289,9 @@ pageClass: routes
|
||||
|
||||
<Route author="hillerliao" example="/xueqiu/user_stock/1247347556" path="/xueqiu/user_stock/:id" :paramsDesc="['用户 id, 可在用户主页 URL 中找到']"/>
|
||||
|
||||
### 基金净值更新
|
||||
### 蛋卷基金净值更新
|
||||
|
||||
<Route author="HenryQW" example="/xueqiu/fund/040008" path="/xueqiu/fund/:id" :paramsDesc="['基金代码, 可在基金主页 URL 中找到. 此路由的数据为场外基金 (`F`开头)']"/>
|
||||
<Route author="HenryQW NathanDai" example="/xueqiu/fund/040008" path="/xueqiu/fund/:id" :paramsDesc="['基金代码, 可在基金主页 URL 中找到. 此路由的数据为场外基金 (`F`开头)']"/>
|
||||
|
||||
### 组合最新调仓信息
|
||||
|
||||
@@ -311,6 +311,10 @@ pageClass: routes
|
||||
|
||||
<Route author="zytomorrow" example="/xueqiu/stock_comments/SZ002626" path="/xueqiu/stock_comments/:id/:titleLength?" :paramsDesc="['股票代码(需要带上交易所)', '标题长度']"/>
|
||||
|
||||
### 热帖
|
||||
|
||||
<Route author="hillerliao" example="/xueqiu/hots" path="/xueqiu/hots"/>
|
||||
|
||||
## 有知有行
|
||||
|
||||
### 有知文章
|
||||
|
||||
@@ -1257,10 +1257,6 @@ rule
|
||||
|
||||
<Route author="kt286" example="/weibo/oasis/user/1990895721" path="/weibo/oasis/user/:userid" :paramsDesc="['用户 id, 可在用户主页 URL 中找到']" anticrawler="1"/>
|
||||
|
||||
### 热帖
|
||||
|
||||
<Route author="hillerliao" example="/xueqiu/hots" path="/xueqiu/hots"/>
|
||||
|
||||
## 悟空问答
|
||||
|
||||
### 用户动态
|
||||
|
||||
+9
-9
@@ -377,15 +377,15 @@ router.get('/egsea/flash', lazyloadRouteHandler('./routes/egsea/flash'));
|
||||
// 选股宝
|
||||
router.get('/xuangubao/subject/:subject_id', lazyloadRouteHandler('./routes/xuangubao/subject'));
|
||||
|
||||
// 雪球
|
||||
router.get('/xueqiu/user/:id/:type?', lazyloadRouteHandler('./routes/xueqiu/user'));
|
||||
router.get('/xueqiu/favorite/:id', lazyloadRouteHandler('./routes/xueqiu/favorite'));
|
||||
router.get('/xueqiu/user_stock/:id', lazyloadRouteHandler('./routes/xueqiu/user_stock'));
|
||||
router.get('/xueqiu/fund/:id', lazyloadRouteHandler('./routes/xueqiu/fund'));
|
||||
router.get('/xueqiu/stock_info/:id/:type?', lazyloadRouteHandler('./routes/xueqiu/stock_info'));
|
||||
router.get('/xueqiu/snb/:id', lazyloadRouteHandler('./routes/xueqiu/snb'));
|
||||
router.get('/xueqiu/hots', lazyloadRouteHandler('./routes/xueqiu/hots'));
|
||||
router.get('/xueqiu/stock_comments/:id/:titleLength?', lazyloadRouteHandler('./routes/xueqiu/stock_comments'));
|
||||
// 雪球 migrated to v2
|
||||
// router.get('/xueqiu/user/:id/:type?', lazyloadRouteHandler('./routes/xueqiu/user'));
|
||||
// router.get('/xueqiu/favorite/:id', lazyloadRouteHandler('./routes/xueqiu/favorite'));
|
||||
// router.get('/xueqiu/user_stock/:id', lazyloadRouteHandler('./routes/xueqiu/user_stock'));
|
||||
// router.get('/xueqiu/fund/:id', lazyloadRouteHandler('./routes/xueqiu/fund'));
|
||||
// router.get('/xueqiu/stock_info/:id/:type?', lazyloadRouteHandler('./routes/xueqiu/stock_info'));
|
||||
// router.get('/xueqiu/snb/:id', lazyloadRouteHandler('./routes/xueqiu/snb'));
|
||||
// router.get('/xueqiu/hots', lazyloadRouteHandler('./routes/xueqiu/hots'));
|
||||
// router.get('/xueqiu/stock_comments/:id/:titleLength?', lazyloadRouteHandler('./routes/xueqiu/stock_comments'));
|
||||
|
||||
// Greasy Fork
|
||||
router.get('/greasyfork/:language/:domain?', lazyloadRouteHandler('./routes/greasyfork/scripts'));
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const guid = `xueqiu/fund ${ctx.params.id}`;
|
||||
const cache = await ctx.cache.get(guid);
|
||||
|
||||
if (cache) {
|
||||
return Promise.resolve(JSON.parse(cache));
|
||||
} else {
|
||||
const url = `https://xueqiu.com/S/F${ctx.params.id}`;
|
||||
|
||||
let fundName = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
headers: {
|
||||
Referer: 'https://xueqiu.com/',
|
||||
},
|
||||
});
|
||||
|
||||
const $ = cheerio.load(fundName.data);
|
||||
fundName = $('.stock-name').text();
|
||||
const fundNameShort = fundName.slice(0, -10);
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: `https://fund.xueqiu.com/dj/open/fund/growth/${ctx.params.id}?day=7`,
|
||||
headers: {
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
|
||||
const data = response.data.data.fund_nav_growth.pop();
|
||||
const yesterday = response.data.data.fund_nav_growth.pop();
|
||||
|
||||
let description = `${fundNameShort} <br> 最新净值 ${data.nav} <br> 今日`;
|
||||
let title = `${fundNameShort} ${data.date.substring(5)} `;
|
||||
|
||||
const value = (parseFloat(data.nav) - parseFloat(yesterday.nav)).toFixed(4);
|
||||
|
||||
if (value > 0) {
|
||||
description += '涨幅';
|
||||
title += `📈 ${data.percentage}%`;
|
||||
} else if (value < 0) {
|
||||
description += '跌幅';
|
||||
title += `📉 ${data.percentage}%`;
|
||||
} else if (value === '0.0000') {
|
||||
description += '无波动';
|
||||
title += '持平';
|
||||
}
|
||||
|
||||
description += ` ${data.percentage}%(¥${value})`;
|
||||
|
||||
const single = {
|
||||
title,
|
||||
description,
|
||||
pubDate: new Date().toUTCString(),
|
||||
guid: `${guid} ${data.date}`,
|
||||
link: url,
|
||||
};
|
||||
|
||||
ctx.state.data = {
|
||||
title: fundName,
|
||||
link: url,
|
||||
description: `${fundName} 净值更新`,
|
||||
item: [single],
|
||||
};
|
||||
|
||||
ctx.cache.set(guid, JSON.stringify(ctx.state.data));
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
const got = require('@/utils/got');
|
||||
const queryString = require('query-string');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
@@ -30,7 +31,7 @@ module.exports = async (ctx) => {
|
||||
item: data.map((item) => ({
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
pubDate: parseDate(item.created_at),
|
||||
link: `https://xueqiu.com${item.target}`,
|
||||
})),
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const timezone = require('@/utils/timezone');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const guid = ctx.params.id;
|
||||
const appUrl = `https://danjuanapp.com/funding/${guid}`;
|
||||
const url = `https://danjuanapp.com/djapi/fund/${guid}`;
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url,
|
||||
headers: {
|
||||
Referer: appUrl,
|
||||
},
|
||||
});
|
||||
const fd_full_name = response.data.data.fd_full_name;
|
||||
const fd_name = response.data.data.fd_name;
|
||||
const fd_code = response.data.data.fd_code;
|
||||
const unit_nav = response.data.data.fund_derived.unit_nav;
|
||||
const nav_grtd = response.data.data.fund_derived.nav_grtd;
|
||||
const end_date = response.data.data.fund_derived.end_date;
|
||||
|
||||
let description = `基金代码 ${fd_code} <br> 今日净值(${end_date}) ¥${unit_nav} `;
|
||||
let title = fd_full_name;
|
||||
|
||||
if (nav_grtd > 0) {
|
||||
description += `<br> 日涨跌 ${nav_grtd}%`;
|
||||
title += `📈 ${nav_grtd}%`;
|
||||
} else if (nav_grtd < 0) {
|
||||
description += `<br> 日跌跌 ${nav_grtd}%`;
|
||||
title += `📉 ${nav_grtd}%`;
|
||||
} else if (nav_grtd === '0.0000') {
|
||||
description += '无波动';
|
||||
title += '持平';
|
||||
}
|
||||
|
||||
const single = {
|
||||
title,
|
||||
description,
|
||||
pubDate: timezone(parseDate(end_date), +8),
|
||||
link: appUrl,
|
||||
};
|
||||
|
||||
ctx.state.data = {
|
||||
title: fd_name,
|
||||
link: appUrl,
|
||||
description,
|
||||
item: [single],
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
const got = require('@/utils/got');
|
||||
const queryString = require('query-string');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const res1 = await got({
|
||||
@@ -35,7 +36,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: item.title ? item.title : description.replace(/<[^>]+>/g, ''),
|
||||
description: item.text,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
pubDate: parseDate(item.created_at),
|
||||
link: `https://xueqiu.com${item.target}`,
|
||||
author: item.user.screen_name,
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
module.exports = {
|
||||
'danjuanapp.com': {
|
||||
_name: '雪球',
|
||||
'.': [
|
||||
{
|
||||
title: '蛋卷基金净值更新',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/funding/:id'],
|
||||
target: '/xueqiu/funding/:id',
|
||||
},
|
||||
],
|
||||
},
|
||||
'xueqiu.com': {
|
||||
_name: '雪球',
|
||||
'.': [
|
||||
{
|
||||
title: '用户动态',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/u/:id'],
|
||||
target: '/xueqiu/user/:id',
|
||||
},
|
||||
{
|
||||
title: '用户收藏动态',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/u/:id'],
|
||||
target: '/xueqiu/favorite/:id',
|
||||
},
|
||||
{
|
||||
title: '用户自选动态',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/u/:id'],
|
||||
target: '/xueqiu/user_stock/:id',
|
||||
},
|
||||
{
|
||||
title: '组合最新调仓信息',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/p/:id'],
|
||||
target: '/xueqiu/snb/:id',
|
||||
},
|
||||
{
|
||||
title: '股票信息',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/S/:id'],
|
||||
target: '/xueqiu/stock_info/:id',
|
||||
},
|
||||
{
|
||||
title: '股票评论',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/S/:id'],
|
||||
target: '/xueqiu/stock_comments/:id',
|
||||
},
|
||||
{
|
||||
title: '热帖',
|
||||
docs: 'https://docs.rsshub.app/finance.html#xue-qiu',
|
||||
source: ['/'],
|
||||
target: '/xueqiu/hots',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
module.exports = (router) => {
|
||||
router.get('/favorite/:id', require('./favorite'));
|
||||
router.get('/fund/:id', require('./fund'));
|
||||
router.get('/hots', require('./hots'));
|
||||
router.get('/snb/:id', require('./snb'));
|
||||
router.get('/stock_comments/:id/:titleLength?', require('./stock_comments'));
|
||||
router.get('/stock_info/:id/:type?', require('./stock_info'));
|
||||
router.get('/user/:id/:type?', require('./user'));
|
||||
router.get('/user_stock/:id', require('./user_stock'));
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
const got = require('@/utils/got');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
@@ -28,7 +29,7 @@ module.exports = async (ctx) => {
|
||||
const single = {
|
||||
title,
|
||||
description,
|
||||
pubDate: new Date(time).toUTCString(),
|
||||
pubDate: parseDate(time),
|
||||
link: url,
|
||||
guid: `xueqiu::snb::${id}::${time}`,
|
||||
};
|
||||
@@ -1,28 +1,12 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const template = require('art-template');
|
||||
const { art } = require('@/utils/render');
|
||||
const path = require('path');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
const description_template = `
|
||||
<a href='https://xueqiu.com/u/{{item.user.id}}'>
|
||||
<div style="font-weight: bold;">{{item.user.screen_name}}:</div>
|
||||
</a>
|
||||
<hr/>
|
||||
{{item.text}}
|
||||
<br/>
|
||||
{{if item.retweeted_status}}
|
||||
<hr style="border:1 dashed #987cb9" />
|
||||
{{item.retweeted_status.text}}
|
||||
{{else}}
|
||||
<hr/>
|
||||
{{/if}}
|
||||
<div style="text-align:right">
|
||||
----来源于:{{item.source}}
|
||||
</div>`;
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
const titleLength = ctx.params.titleLength || 30;
|
||||
const titleLength = ctx.params.titleLength ? parseInt(ctx.params.titleLength) : 30;
|
||||
|
||||
const res = await got({
|
||||
method: 'get',
|
||||
@@ -49,7 +33,7 @@ module.exports = async (ctx) => {
|
||||
if (item.quote_cards) {
|
||||
link = item.quote_cards[0].target_url;
|
||||
}
|
||||
const description = template.render(description_template, { item });
|
||||
const description = art(path.join(__dirname, 'templates/comments_description.art'), { item });
|
||||
return {
|
||||
title: item.title !== '' ? item.title : item.text.replace(/<[^>]+>/g, '').slice(0, titleLength),
|
||||
description,
|
||||
@@ -1,6 +1,7 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const queryString = require('query-string');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
@@ -63,7 +64,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: item.title !== '' ? item.title : item.description.replace(/<[^>]+>/g, ''),
|
||||
description: item.description,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
pubDate: parseDate(item.created_at),
|
||||
link,
|
||||
};
|
||||
}),
|
||||
@@ -0,0 +1,10 @@
|
||||
<a href='https://xueqiu.com/u/{{ item.user.id }}'><div style="font-weight: bold;">{{ item.user.screen_name }}:</div></a>
|
||||
<hr/>
|
||||
{{@ item.text }}
|
||||
<br/>
|
||||
{{ if item.retweeted_status }}
|
||||
<hr style="border:1 dashed #987cb9" />{{@ item.retweeted_status.text }}
|
||||
{{ else }}
|
||||
<hr/>
|
||||
{{ /if }}
|
||||
<div style="text-align:right"> ----来源于:{{ item.source }}</div>
|
||||
@@ -1,5 +1,6 @@
|
||||
const got = require('@/utils/got');
|
||||
const queryString = require('query-string');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
@@ -44,7 +45,7 @@ module.exports = async (ctx) => {
|
||||
return {
|
||||
title: item.title ? item.title : description.replace(/<[^>]+>/g, ''),
|
||||
description,
|
||||
pubDate: new Date(item.created_at).toUTCString(),
|
||||
pubDate: parseDate(item.created_at),
|
||||
link: `https://xueqiu.com${item.target}`,
|
||||
};
|
||||
}),
|
||||
@@ -1,5 +1,6 @@
|
||||
const got = require('@/utils/got');
|
||||
const queryString = require('query-string');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const id = ctx.params.id;
|
||||
@@ -39,8 +40,8 @@ module.exports = async (ctx) => {
|
||||
description: `@${screen_name} 的雪球自选动态`,
|
||||
item: data.map((item) => ({
|
||||
title: `@${screen_name} 关注了股票 ${item.name}`,
|
||||
description: `@${screen_name} 在${new Date(item.created).toLocaleString()} 关注了 ${item.name}(${item.exchange}:${item.symbol})。`,
|
||||
pubDate: new Date(item.created).toUTCString(),
|
||||
description: `@${screen_name} 在${parseDate(item.created).toLocaleString()} 关注了 ${item.name}(${item.exchange}:${item.symbol})。`,
|
||||
pubDate: parseDate(item.created),
|
||||
link: `https://xueqiu.com/s/${item.symbol}`,
|
||||
})),
|
||||
};
|
||||
Reference in New Issue
Block a user