From 6f8f2ce0a5cab52b1f0099faf66717e52f6c0b73 Mon Sep 17 00:00:00 2001 From: Ethan Shen Date: Sun, 13 Feb 2022 21:39:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(route):=20add=20=E8=AF=81=E5=88=B8?= =?UTF-8?q?=E6=97=B6=E6=8A=A5=E7=BD=91=E8=82=A1=E5=B8=82=20(#9077)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(route): add 证券时报网股市 * fix: remove breadcrumbs * fix typo --- docs/finance.md | 44 +++++++++++------- lib/router.js | 6 +-- lib/routes/stcn/data.js | 84 ----------------------------------- lib/routes/stcn/kuaixun.js | 91 -------------------------------------- lib/routes/stcn/news.js | 85 ----------------------------------- lib/v2/stcn/index.js | 71 +++++++++++++++++++++++++++++ lib/v2/stcn/maintainer.js | 6 +++ lib/v2/stcn/radar.js | 31 +++++++++++++ lib/v2/stcn/router.js | 3 ++ 9 files changed, 141 insertions(+), 280 deletions(-) delete mode 100644 lib/routes/stcn/data.js delete mode 100644 lib/routes/stcn/kuaixun.js delete mode 100644 lib/routes/stcn/news.js create mode 100644 lib/v2/stcn/index.js create mode 100644 lib/v2/stcn/maintainer.js create mode 100644 lib/v2/stcn/radar.js create mode 100644 lib/v2/stcn/router.js diff --git a/docs/finance.md b/docs/finance.md index 92b25bb5e2..38d249f7ab 100644 --- a/docs/finance.md +++ b/docs/finance.md @@ -289,21 +289,11 @@ pageClass: routes ### 要闻 - + -| 要闻 | 滚动 | 深度 | 评论 | -| ---- | ---- | ---- | ---- | -| news | gd | sd | pl | - - - -### 数据 - - - -| 数据 | 机器人新闻 | -| ---- | ---------- | -| data | jqrxw | +| 要闻 | 滚动 | 深度 | 评论 | +| ------- | ---- | ----- | ----- | +| xw/news | gd | xw/sd | xw/pl | @@ -311,9 +301,29 @@ pageClass: routes -| 快讯 | e 公司 | 研报 | 时事 | 财经 | -| ---- | ------ | ---- | ---- | ---- | -| | egs | yb | ss | cj | +| 快讯 | e 公司 | 研报 | 时事 | 财经 | 券中社 | +| ---- | ------ | ---- | ---- | ---- | ------ | +| | egs | yb | ss | cj | qzs | + + + +### 股市 + + + +| 股市 | 股市动态 | 独家解读 | +| ---- | -------- | -------- | +| | gsdt | djjd | + + + +### 数据 + + + +| 数据 | 机器人新闻 | 独家数据 | +| ---- | ---------- | -------- | +| | jqrxw | djsj | diff --git a/lib/router.js b/lib/router.js index 54d6845606..16312dd531 100644 --- a/lib/router.js +++ b/lib/router.js @@ -3410,9 +3410,9 @@ router.get('/allnow/user/:id', lazyloadRouteHandler('./routes/allnow/user')); router.get('/allnow', lazyloadRouteHandler('./routes/allnow/index')); // 证券时报网 -router.get('/stcn/news/:id?', lazyloadRouteHandler('./routes/stcn/news')); -router.get('/stcn/data/:id?', lazyloadRouteHandler('./routes/stcn/data')); -router.get('/stcn/kuaixun/:id?', lazyloadRouteHandler('./routes/stcn/kuaixun')); +// router.get('/stcn/news/:id?', lazyloadRouteHandler('./routes/stcn/news')); +// router.get('/stcn/data/:id?', lazyloadRouteHandler('./routes/stcn/data')); +// router.get('/stcn/kuaixun/:id?', lazyloadRouteHandler('./routes/stcn/kuaixun')); // dev.to router.get('/dev.to/top/:period', lazyloadRouteHandler('./routes/dev.to/top')); diff --git a/lib/routes/stcn/data.js b/lib/routes/stcn/data.js deleted file mode 100644 index 5a38fb77e0..0000000000 --- a/lib/routes/stcn/data.js +++ /dev/null @@ -1,84 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -const config = { - data: { - link: 'https://data.stcn.com', - title: '数据', - }, - jqrxw: { - link: 'https://data.stcn.com/jqrxw', - title: '机器人新闻', - }, -}; - -module.exports = async (ctx) => { - ctx.params.id = ctx.params.id || 'data'; - - const cfg = config[ctx.params.id]; - - const rootUrl = 'https://data.stcn.com'; - const currentUrl = cfg.link; - const response = await got({ - method: 'get', - url: currentUrl, - }); - - let query = 'dt a'; - if (ctx.params.id === 'jqrxw') { - query = '#news_list2 li a[title]'; - } - - const $ = cheerio.load(response.data); - const list = $(query) - .slice(0, 20) - .map((_, item) => { - item = $(item); - let link = item.attr('href'); - if (link.indexOf('..') === 0) { - link = `${rootUrl}${link.replace('..', '')}`; - } else if (link.indexOf('.') === 0) { - link = `${rootUrl}${link.replace('.', '')}`; - } - return { - link, - }; - }) - .get(); - - const items = await Promise.all( - list.map((item) => - ctx.cache.tryGet(item.link, async () => { - const detailResponse = await got({ - method: 'get', - url: item.link, - }); - const content = cheerio.load(detailResponse.data); - - let info = content('div.info'); - - if (info.html() === null) { - info = content('h2 span'); - info.find('i').remove(); - } else { - info.find('span').remove(); - } - item.pubDate = new Date(info.text().split('来源')[0].trim()).toUTCString(); - - const title = content('h2'); - title.find('span').remove(); - - item.title = title.text().replace('点击排行榜', ''); - item.description = content('#ctrlfscont').html() || content('.text').html(); - - return item; - }) - ) - ); - - ctx.state.data = { - title: '证券时报网 - ' + cfg.title, - link: currentUrl, - item: items, - }; -}; diff --git a/lib/routes/stcn/kuaixun.js b/lib/routes/stcn/kuaixun.js deleted file mode 100644 index f104474e4b..0000000000 --- a/lib/routes/stcn/kuaixun.js +++ /dev/null @@ -1,91 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -const rootUrl = 'https://kuaixun.stcn.com'; - -const config = { - '': { - link: rootUrl, - title: '快讯', - }, - egs: { - link: `${rootUrl}/egs/`, - title: 'e公司', - }, - yb: { - link: `${rootUrl}/yb/`, - title: '研报', - }, - ss: { - link: `${rootUrl}/ss/`, - title: '时事', - }, - cj: { - link: `${rootUrl}/cj/`, - title: '财经', - }, -}; - -module.exports = async (ctx) => { - ctx.params.id = ctx.params.id || ''; - - const cfg = config[ctx.params.id]; - - const currentUrl = cfg.link; - const response = await got({ - method: 'get', - url: currentUrl, - }); - - const $ = cheerio.load(response.data); - - const list = $('#news_list2 li a') - .slice(0, 20) - .map((_, item) => { - item = $(item); - let link = item.attr('href'); - if (link.indexOf('.') === 0) { - link = `${currentUrl}${link.replace('.', '')}`; - } - return { - link, - }; - }) - .get(); - - const items = await Promise.all( - list.map((item) => - ctx.cache.tryGet(item.link, async () => { - const detailResponse = await got({ - method: 'get', - url: item.link, - }); - const content = cheerio.load(detailResponse.data); - - let info = content('div.info'); - - if (info.html() === null) { - info = content('h2 span'); - info.find('i').remove(); - } else { - info.find('span').remove(); - } - item.pubDate = new Date(info.text().split('来源')[0].trim()).toUTCString(); - - const title = content('h2'); - title.find('span').remove(); - - item.title = title.text().replace('为你推荐', ''); - item.description = content('#ctrlfscont').html() || content('.text').html(); - - return item; - }) - ) - ); - - ctx.state.data = { - title: '证券时报网 - ' + cfg.title, - link: currentUrl, - item: items, - }; -}; diff --git a/lib/routes/stcn/news.js b/lib/routes/stcn/news.js deleted file mode 100644 index 6d818d1534..0000000000 --- a/lib/routes/stcn/news.js +++ /dev/null @@ -1,85 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -const config = { - news: { - link: 'https://news.stcn.com/news', - title: '要闻', - }, - gd: { - link: 'https://www.stcn.com/gd', - title: '滚动', - }, - sd: { - link: 'https://www.stcn.com/sd', - title: '深度', - }, - pl: { - link: 'https://www.stcn.com/pl', - title: '评论', - }, -}; - -module.exports = async (ctx) => { - ctx.params.id = ctx.params.id || 'news'; - - const cfg = config[ctx.params.id]; - const currentUrl = cfg.link; - const response = await got({ - method: 'get', - url: currentUrl, - }); - - let query = '.tit a'; - if (ctx.params.id === 'gd') { - query = 'li a[title]'; - } - - const $ = cheerio.load(response.data); - const list = $(query) - .slice(0, 20) - .map((_, item) => { - item = $(item); - let link = item.attr('href'); - if (link.indexOf('.') === 0) { - link = `${currentUrl}${link.replace('.', '')}`; - } - return { - title: item.text(), - link, - }; - }) - .get(); - - const items = await Promise.all( - list.map((item) => - ctx.cache.tryGet(item.link, async () => { - const detailResponse = await got({ - method: 'get', - url: item.link, - }); - const content = cheerio.load(detailResponse.data); - - let info = content('div.info'); - - if (info.html() === null) { - info = content('h2 span'); - info.find('i').remove(); - } else { - info.find('span').remove(); - } - item.pubDate = new Date(info.text().split('来源')[0].trim()).toUTCString(); - - item.description = content('#ctrlfscont').html() || content('.text').html(); - - return item; - }) - ) - ); - - ctx.state.data = { - title: '证券时报网 - ' + cfg.title, - link: currentUrl, - item: items, - }; -}; diff --git a/lib/v2/stcn/index.js b/lib/v2/stcn/index.js new file mode 100644 index 0000000000..03d8fe7bb9 --- /dev/null +++ b/lib/v2/stcn/index.js @@ -0,0 +1,71 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const timezone = require('@/utils/timezone'); +const { parseDate } = require('@/utils/parse-date'); + +const shortcuts = { + 'news/news': 'xw/news', + 'news/gd': 'gd', + 'news/sd': 'xw/sd', + 'news/pl': 'xw/pl', + 'data/data': 'data', +}; + +module.exports = async (ctx) => { + let path = ctx.path.replace(/\//, ''); + if (shortcuts.hasOwnProperty(path)) { + path = shortcuts[path]; + } + + const rootUrl = 'https://www.stcn.com'; + const currentUrl = `${rootUrl}/${path || 'xw/news'}`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const match = response.data.match(/var curr_channel_id = "(light_\d+)";/); + const $ = cheerio.load(response.data); + + $('.website, .websit').remove(); + + let items = $('.box_left, .box_left2, .left2') + .find('a[title]') + .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 20) + .toArray() + .map((item) => { + item = $(item); + + return { + title: item.text(), + link: item.attr('href').replace(/^\.\./, currentUrl.split('/').slice(0, -1).join('/')).replace(/^\./, currentUrl), + }; + }); + + items = await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.link, async () => { + const detailResponse = await got({ + method: 'get', + url: item.link, + }); + + const content = cheerio.load(detailResponse.data); + + item.description = content('.txt_con').html(); + item.author = content('meta[name="author"]').attr('content'); + item.category = content('meta[name="keywords"]').attr('content').split(';'); + item.pubDate = timezone(parseDate(detailResponse.data.match(/publishdate = '(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})';/)[1]), +8); + + return item; + }) + ) + ); + + ctx.state.data = { + title: `${(match ? $('#' + match[1]).text() : '') || $('.cur').text()} - 证券时报网`, + link: currentUrl, + item: items, + }; +}; diff --git a/lib/v2/stcn/maintainer.js b/lib/v2/stcn/maintainer.js new file mode 100644 index 0000000000..30e113c7a3 --- /dev/null +++ b/lib/v2/stcn/maintainer.js @@ -0,0 +1,6 @@ +module.exports = { + '/data/:id?': ['nczitzk'], + '/kuaixun/:id?': ['nczitzk'], + '/stock/:id?': ['nczitzk'], + '/:id?': ['nczitzk'], +}; diff --git a/lib/v2/stcn/radar.js b/lib/v2/stcn/radar.js new file mode 100644 index 0000000000..c920b536ff --- /dev/null +++ b/lib/v2/stcn/radar.js @@ -0,0 +1,31 @@ +module.exports = { + 'stcn.com': { + _name: '证券时报网', + '.': [ + { + title: '要闻', + docs: 'https://docs.rsshub.app/finance.html#zheng-quan-shi-bao-wang-yao-wen', + source: ['/xw/:id', '/gd', '/'], + target: (params, url) => `/stcn${new URL(url).pathname}`, + }, + { + title: '快讯', + docs: 'https://docs.rsshub.app/finance.html#zheng-quan-shi-bao-wang-kuai-xun', + source: ['/kuaixun/:id', '/kuaixun', '/'], + target: (params, url) => `/stcn${new URL(url).pathname}`, + }, + { + title: '股市', + docs: 'https://docs.rsshub.app/finance.html#zheng-quan-shi-bao-wang-gu-shi', + source: ['/stock/:id', '/stock', '/'], + target: (params, url) => `/stcn${new URL(url).pathname}`, + }, + { + title: '数据', + docs: 'https://docs.rsshub.app/finance.html#zheng-quan-shi-bao-wang-shu-ju', + source: ['/data/:id', '/data', '/'], + target: (params, url) => `/stcn${new URL(url).pathname}`, + }, + ], + }, +}; diff --git a/lib/v2/stcn/router.js b/lib/v2/stcn/router.js new file mode 100644 index 0000000000..28f05970b9 --- /dev/null +++ b/lib/v2/stcn/router.js @@ -0,0 +1,3 @@ +module.exports = function (router) { + router.get(/([\w\d/-]+)?/, require('./index')); +};