From d3980819812f57cd827ea605b7b2ad31f77a217b Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 11 May 2023 15:37:19 +0100 Subject: [PATCH] feat(route): sina us stock and rollnews (#12493) * refactor: migrate to v2 * refactor: generic rollnews * docs: merge docs * refactor: discovery use common utilities * refactor: china finance use utilities * refactor: csj use utils * feat: us stock * feat: add radar * docs: mention default value * docs: fix build --- docs/finance.md | 6 -- docs/new-media.md | 56 ++++++++++++++- docs/traditional-media.md | 30 -------- lib/router.js | 10 +-- lib/routes/sina/chuangshiji.js | 38 ---------- lib/routes/sina/discovery.js | 52 -------------- lib/routes/sina/finance.js | 37 ---------- lib/routes/sina/rollnews.js | 41 ----------- lib/routes/sina/sports.js | 54 -------------- lib/v2/sina/chuangshiji.js | 17 +++++ lib/v2/sina/discovery.js | 32 +++++++++ lib/v2/sina/finance/china.js | 25 +++++++ lib/v2/sina/finance/stock/usstock.js | 37 ++++++++++ lib/v2/sina/maintainer.js | 8 +++ lib/v2/sina/radar.js | 49 +++++++++++++ lib/v2/sina/rollnews.js | 31 ++++++++ lib/v2/sina/router.js | 8 +++ lib/v2/sina/sports.js | 43 +++++++++++ lib/v2/sina/templates/slide.art | 3 + lib/v2/sina/templates/video.art | 5 ++ lib/v2/sina/utils.js | 104 +++++++++++++++++++++++++++ 21 files changed, 420 insertions(+), 266 deletions(-) delete mode 100644 lib/routes/sina/chuangshiji.js delete mode 100644 lib/routes/sina/discovery.js delete mode 100644 lib/routes/sina/finance.js delete mode 100644 lib/routes/sina/rollnews.js delete mode 100644 lib/routes/sina/sports.js create mode 100644 lib/v2/sina/chuangshiji.js create mode 100644 lib/v2/sina/discovery.js create mode 100644 lib/v2/sina/finance/china.js create mode 100644 lib/v2/sina/finance/stock/usstock.js create mode 100644 lib/v2/sina/maintainer.js create mode 100644 lib/v2/sina/radar.js create mode 100644 lib/v2/sina/rollnews.js create mode 100644 lib/v2/sina/router.js create mode 100644 lib/v2/sina/sports.js create mode 100644 lib/v2/sina/templates/slide.art create mode 100644 lib/v2/sina/templates/video.art create mode 100644 lib/v2/sina/utils.js diff --git a/docs/finance.md b/docs/finance.md index 48f3bafad..159313757 100644 --- a/docs/finance.md +++ b/docs/finance.md @@ -566,12 +566,6 @@ TokenInsight 官方亦有提供 RSS,可参考 -## 新浪财经 - -### 新浪财经-国內 - - - ## 雪球 ### 今日话题 diff --git a/docs/new-media.md b/docs/new-media.md index 5a1274bb9..4ec2f62bd 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -4454,11 +4454,61 @@ wechat-feeds 来源[已停止更新](https://github.com/hellodword/wechat-feeds/ -## 新浪专栏 +## 新浪 -### 创事记 +### 科技 - 科学探索 - + + +| 最新 | 天文航空 | 动物植物 | 自然地理 | 历史考古 | 生命医学 | 生活百科 | 科技前沿 | +| ---- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| zx | twhk | dwzw | zrdl | lskg | smyx | shbk | kjqy | + + + +### 滚动新闻 + + + +| 全部 | 国内 | 国际 | 社会 | 体育 | 娱乐 | 军事 | 科技 | 财经 | 股市 | 美股 | +| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | +| 2509 | 2510 | 2511 | 2669 | 2512 | 2513 | 2514 | 2515 | 2516 | 2517 | 2518 | + + + +### 体育 - 综合 + + + +| 排球 | 游泳 | 乒乓球 | 羽毛球 | 台球 | 田径 | 体操 | 冰雪 | 射击 | 马术 | 拳击搏击 | UFC | 其他 | +| ------ | ---- | -------- | ------ | ------- | -------- | ----- | ------ | ---- | ----- | -------- | --- | ------ | +| volley | swim | pingpang | badmin | snooker | tianjing | ticao | winter | sh | horse | kungfu | ufc | others | + + + +### 财经-国內 + + + +| 国内滚动 | 宏观经济 | 金融新闻 | 地方经济 | 部委动态 | 今日财经 TOP10 | +| -------- | -------- | -------- | -------- | -------- | -------------- | +| 1686 | 1687 | 1690 | 1688 | 1689 | 3231 | + + + +### 美股 + + + +| 最新报道 | 中概股 | 国际财经 | 互联网 | +| -------- | ------ | -------- | ------ | +| 57045 | 57046 | 56409 | 40811 | + + + +### 专栏 - 创事记 + + ## 选股宝 diff --git a/docs/traditional-media.md b/docs/traditional-media.md index 3c6018629..184ef9d2a 100644 --- a/docs/traditional-media.md +++ b/docs/traditional-media.md @@ -2413,36 +2413,6 @@ category 对应的关键词有 -## 新浪科技 - -### 科学探索 - - - -分类: - -| zx | twhk | dwzw | zrdl | lskg | smyx | shbk | kjqy | -| ---- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -| 最新 | 天文航空 | 动物植物 | 自然地理 | 历史考古 | 生命医学 | 生活百科 | 科技前沿 | - - - -### 滚动新闻 - - - -## 新浪体育 - -### 综合 - - - -| 排球 | 游泳 | 乒乓球 | 羽毛球 | 台球 | 田径 | 体操 | 冰雪 | 射击 | 马术 | 拳击搏击 | UFC | 其他 | -| ------ | ---- | -------- | ------ | ------- | -------- | ----- | ------ | ---- | ----- | -------- | --- | ------ | -| volley | swim | pingpang | badmin | snooker | tianjing | ticao | winter | sh | mashu | kungfu | ufc | others | - - - ## 新唐人电视台 ### 频道 diff --git a/lib/router.js b/lib/router.js index d0741a0aa..b226aca37 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1247,19 +1247,19 @@ router.get('/fitchratings/site/:type', lazyloadRouteHandler('./routes/fitchratin // router.get('/mpaypass/main/:type?', lazyloadRouteHandler('./routes/mpaypass/main')); // 新浪科技探索 -router.get('/sina/discovery/:type', lazyloadRouteHandler('./routes/sina/discovery')); +// router.get('/sina/discovery/:type', lazyloadRouteHandler('./routes/sina/discovery')); // 新浪科技滚动新闻 -router.get('/sina/rollnews', lazyloadRouteHandler('./routes/sina/rollnews')); +// router.get('/sina/rollnews', lazyloadRouteHandler('./routes/sina/rollnews')); // 新浪体育 -router.get('/sina/sports/:type', lazyloadRouteHandler('./routes/sina/sports')); +// router.get('/sina/sports/:type', lazyloadRouteHandler('./routes/sina/sports')); // 新浪专栏创事记 -router.get('/sina/csj', lazyloadRouteHandler('./routes/sina/chuangshiji')); +// router.get('/sina/csj', lazyloadRouteHandler('./routes/sina/chuangshiji')); // 新浪财经-国內 -router.get('/sina/finance', lazyloadRouteHandler('./routes/sina/finance')); +// router.get('/sina/finance', lazyloadRouteHandler('./routes/sina/finance')); // Animen router.get('/animen/news/:type', lazyloadRouteHandler('./routes/animen/news')); diff --git a/lib/routes/sina/chuangshiji.js b/lib/routes/sina/chuangshiji.js deleted file mode 100644 index e9567b933..000000000 --- a/lib/routes/sina/chuangshiji.js +++ /dev/null @@ -1,38 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -const url = 'http://feed.sina.com.cn/api/roll/get?pageid=402&lid=2559&num=20&versionNumber=1.2.8&page=1&encode=utf-8'; - -module.exports = async (ctx) => { - const response = await got.get(url); - const list = response.data.result.data; - - const out = await Promise.all( - list.map(async (data) => { - const title = data.title; - const date = data.intime * 1000; - const link = data.url; - - const description = await ctx.cache.tryGet(`sina-chuangshiji: ${link}`, async () => { - const response = await got.get(link); - const $ = cheerio.load(response.data); - - return $('.blkContainerSblkCon').html(); - }); - - const single = { - title, - link, - description, - pubDate: new Date(date).toUTCString(), - }; - return Promise.resolve(single); - }) - ); - - ctx.state.data = { - title: '新浪专栏-创事记', - link: 'https://tech.sina.com.cn/chuangshiji', - item: out, - }; -}; diff --git a/lib/routes/sina/discovery.js b/lib/routes/sina/discovery.js deleted file mode 100644 index 73072c629..000000000 --- a/lib/routes/sina/discovery.js +++ /dev/null @@ -1,52 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -const link = 'https://tech.sina.com.cn/discovery/'; -const api = 'https://feed.sina.com.cn/api/roll/get?pageid=207&num=10&versionNumber=1.2.4&page=1&encode=utf-8&lid='; - -const map = new Map([ - ['zx', { title: '最新', id: '1795' }], - ['twhk', { title: '天文航空', id: '1796' }], - ['dwzw', { title: '动物植物', id: '1797' }], - ['zrdl', { title: '自然地理', id: '1798' }], - ['lskg', { title: '历史考古', id: '1799' }], - ['smyx', { title: '生命医学', id: '1800' }], - ['shbk', { title: '生活百科', id: '1801' }], - ['kjqy', { title: '科技前沿', id: '1802' }], -]); - -module.exports = async (ctx) => { - const type = ctx.params.type; - const id = map.get(type).id; - const title = map.get(type).title; - - const api_url = api + id; - const response = await got.get(api_url); - const list = response.data.result.data; - - const out = await Promise.all( - list.map(async (data) => { - const title = data.title; - const date = data.intime * 1000; - const itemUrl = data.url; - - const response = await got.get(itemUrl); - const $ = cheerio.load(response.data); - const description = $('.article').html(); - - const single = { - title, - link: itemUrl, - description, - pubDate: new Date(date).toUTCString(), - }; - return Promise.resolve(single); - }) - ); - - ctx.state.data = { - title: `${title}-新浪科技科学探索`, - link, - item: out, - }; -}; diff --git a/lib/routes/sina/finance.js b/lib/routes/sina/finance.js deleted file mode 100644 index 431914f1e..000000000 --- a/lib/routes/sina/finance.js +++ /dev/null @@ -1,37 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -module.exports = async (ctx) => { - const url = 'http://feed.sina.com.cn/api/roll/get?pageid=155&lid=1686&num=20&versionNumber=1.2.8&page=1&encode=utf-8'; - const response = await got.get(url); - const list = response.data.result.data; - - const out = await Promise.all( - list.map(async (data) => { - const title = data.title; - const date = data.intime * 1000; - const link = data.url; - - const description = await ctx.cache.tryGet(`sina-finance: ${link}`, async () => { - const response = await got.get(link); - const $ = cheerio.load(response.data); - - return $('#artibody').html(); - }); - - const single = { - title, - link, - description, - pubDate: new Date(date).toUTCString(), - }; - return Promise.resolve(single); - }) - ); - - ctx.state.data = { - title: '新浪财经-国內', - link: 'http://finance.sina.com.cn/china/', - item: out, - }; -}; diff --git a/lib/routes/sina/rollnews.js b/lib/routes/sina/rollnews.js deleted file mode 100644 index a2d1c69c9..000000000 --- a/lib/routes/sina/rollnews.js +++ /dev/null @@ -1,41 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); -const { parseDate } = require('@/utils/parse-date'); - -module.exports = async (ctx) => { - const response = await got(`https://feed.mix.sina.com.cn/api/roll/get?pageid=372&lid=2431&k=&num=50&page=1&r=${Math.random()}&callback=&_=${new Date().getTime()}`, { - headers: { - Referer: 'https://tech.sina.com.cn/', - }, - }); - const list = response.data.result.data; - - const out = await Promise.all( - list.map(async (data) => { - const title = data.title; - const date = data.intime * 1000; - const link = data.url; - - const description = await ctx.cache.tryGet(`sina-rollnews: ${link}`, async () => { - const response = await got.get(link); - const $ = cheerio.load(response.data); - - return $('.article').html(); - }); - - const single = { - title, - link, - description, - pubDate: parseDate(date), - }; - return single; - }) - ); - - ctx.state.data = { - title: '新浪科技滚动新闻', - link: 'https://tech.sina.com.cn/roll/rollnews.shtml#pageid=372&lid=2431&k=&num=50&page=1', - item: out, - }; -}; diff --git a/lib/routes/sina/sports.js b/lib/routes/sina/sports.js deleted file mode 100644 index 73e6deeb7..000000000 --- a/lib/routes/sina/sports.js +++ /dev/null @@ -1,54 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -module.exports = async (ctx) => { - ctx.params.type = ctx.params.type || 'volley'; - - let currentUrl = `https://sports.sina.com.cn/others/${ctx.params.type}.shtml`, - query = 'ul.list2 li a'; - - if (ctx.params.type === 'ufc') { - currentUrl = 'http://roll.sports.sina.com.cn/s_ufc_all/index.shtml'; - query = '#d_list ul li span a'; - } - - const response = await got({ - method: 'get', - url: currentUrl, - }); - - const $ = cheerio.load(response.data); - const list = $(query) - .slice(0, 20) - .map((_, item) => { - item = $(item); - return { - link: item.attr('href'), - }; - }) - .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); - - item.description = content('#artibody').html(); - item.title = content('meta[property="og:title"]').attr('content'); - item.pubDate = new Date(content('meta[property="article:published_time"]').attr('content')).toUTCString(); - - return item; - }) - ) - ); - - ctx.state.data = { - title: `${$('title').text().split('_')[0]} - 新浪体育`, - link: currentUrl, - item: items, - }; -}; diff --git a/lib/v2/sina/chuangshiji.js b/lib/v2/sina/chuangshiji.js new file mode 100644 index 000000000..d82d2b0bd --- /dev/null +++ b/lib/v2/sina/chuangshiji.js @@ -0,0 +1,17 @@ +const { getRollNewsList, parseRollNewsList, parseArticle } = require('./utils'); + +module.exports = async (ctx) => { + const pageid = '402'; + const lid = '2559'; + const { limit = '50' } = ctx.query; + const response = await getRollNewsList(pageid, lid, limit); + const list = parseRollNewsList(response.data.result.data); + + const out = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: '新浪专栏-创事记', + link: 'https://tech.sina.com.cn/chuangshiji', + item: out, + }; +}; diff --git a/lib/v2/sina/discovery.js b/lib/v2/sina/discovery.js new file mode 100644 index 000000000..857813e6b --- /dev/null +++ b/lib/v2/sina/discovery.js @@ -0,0 +1,32 @@ +const { getRollNewsList, parseRollNewsList, parseArticle } = require('./utils'); + +const link = 'https://tech.sina.com.cn/discovery/'; +const map = new Map([ + ['zx', { title: '最新', id: '1795' }], + ['twhk', { title: '天文航空', id: '1796' }], + ['dwzw', { title: '动物植物', id: '1797' }], + ['zrdl', { title: '自然地理', id: '1798' }], + ['lskg', { title: '历史考古', id: '1799' }], + ['smyx', { title: '生命医学', id: '1800' }], + ['shbk', { title: '生活百科', id: '1801' }], + ['kjqy', { title: '科技前沿', id: '1802' }], +]); + +module.exports = async (ctx) => { + const type = ctx.params.type; + const lid = map.get(type).id; + const title = map.get(type).title; + const pageid = '207'; + const { limit = '50' } = ctx.query; + + const response = await getRollNewsList(pageid, lid, limit); + const list = parseRollNewsList(response.data.result.data); + + const out = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: `${title}-新浪科技科学探索`, + link, + item: out, + }; +}; diff --git a/lib/v2/sina/finance/china.js b/lib/v2/sina/finance/china.js new file mode 100644 index 000000000..d171c1f98 --- /dev/null +++ b/lib/v2/sina/finance/china.js @@ -0,0 +1,25 @@ +const { getRollNewsList, parseRollNewsList, parseArticle } = require('../utils'); + +module.exports = async (ctx) => { + const map = { + 1686: '国内滚动', + 1687: '宏观经济', + 1690: '金融新闻', + 1688: '地方经济', + 1689: '部委动态', + 3231: '今日财经 TOP10', + }; + const pageid = '155'; + const { lid = '1686' } = ctx.params; + const { limit = '50' } = ctx.query; + const response = await getRollNewsList(pageid, lid, limit); + const list = parseRollNewsList(response.data.result.data); + + const out = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: `新浪财经-${map[lid]}`, + link: 'http://finance.sina.com.cn/china/', + item: out, + }; +}; diff --git a/lib/v2/sina/finance/stock/usstock.js b/lib/v2/sina/finance/stock/usstock.js new file mode 100644 index 000000000..f5fc2eab2 --- /dev/null +++ b/lib/v2/sina/finance/stock/usstock.js @@ -0,0 +1,37 @@ +const got = require('@/utils/got'); +const { parseDate } = require('@/utils/parse-date'); +const { parseArticle } = require('../../utils'); + +module.exports = async (ctx) => { + const { cids = '57045' } = ctx.params; + const { limit = '50' } = ctx.query; + const { data: response } = await got('https://interface.sina.cn/pc_api/public_news_data.d.json', { + searchParams: { + cids, + pdps: '', + smartFlow: '', + editLevel: '0,1,2,3', + type: 'std_news,std_slide,std_video', + pageSize: limit, + cTime: '1483200000', + tm: Date.now(), + up: '0', + action: '0', + _: new Date().getTime(), + }, + }); + const list = response.data.map((item) => ({ + title: item.title, + link: item.url, + pubDate: parseDate(item.ctime, 'X'), + author: item.media, + })); + + const items = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: '美股|美股行情|美股新闻 - 新浪财经', + link: 'https://finance.sina.com.cn/stock/usstock/', + item: items, + }; +}; diff --git a/lib/v2/sina/maintainer.js b/lib/v2/sina/maintainer.js new file mode 100644 index 000000000..89232a8bb --- /dev/null +++ b/lib/v2/sina/maintainer.js @@ -0,0 +1,8 @@ +module.exports = { + '/csj': ['xapool'], + '/discovery/:type': ['LogicJake'], + '/finance/china/:lid?': ['yubinbai'], + '/finance/stock/usstock/:cids?': ['TonyRL'], + '/rollnews/:lid?': ['xyqfer'], + '/sports/:type?': ['nczitzk'], +}; diff --git a/lib/v2/sina/radar.js b/lib/v2/sina/radar.js new file mode 100644 index 000000000..10b63af52 --- /dev/null +++ b/lib/v2/sina/radar.js @@ -0,0 +1,49 @@ +module.exports = { + 'sina.com.cn': { + _name: '新浪', + finance: [ + { + title: '财经 - 国內', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/china', '/'], + target: '/sina/finance/china', + }, + { + title: '美股', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/stock/usstock', '/'], + target: '/sina/finance/stock/usstock', + }, + ], + news: [ + { + title: '滚动新闻', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/roll'], + target: (_, url) => `/sina/rollnews/${new URL(url).hash.match(/lid=(\d+)/)[1]}`, + }, + ], + sports: [ + { + title: '体育 - 综合', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/others/:type', '/:type'], + target: (params) => `/sina/sports/${params.type}`, + }, + ], + tech: [ + { + title: '专栏 - 创事记', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/chuangshiji', '/'], + target: '/sina/csj', + }, + { + title: '科技 - 科学探索', + docs: 'https://docs.rsshub.app/new-media.html#xin-lang', + source: ['/discovery', '/'], + target: '/sina/discovery/zx', + }, + ], + }, +}; diff --git a/lib/v2/sina/rollnews.js b/lib/v2/sina/rollnews.js new file mode 100644 index 000000000..9a24a1d8d --- /dev/null +++ b/lib/v2/sina/rollnews.js @@ -0,0 +1,31 @@ +const { getRollNewsList, parseRollNewsList, parseArticle } = require('./utils'); + +module.exports = async (ctx) => { + const map = { + 2509: '全部', + 2510: '国内', + 2511: '国际', + 2669: '社会', + 2512: '体育', + 2513: '娱乐', + 2514: '军事', + 2515: '科技', + 2516: '财经', + 2517: '股市', + 2518: '美股', + }; + + const pageid = '153'; + const { lid = '2509' } = ctx.params; + const { limit = '50' } = ctx.query; + const response = await getRollNewsList(pageid, lid, limit); + const list = parseRollNewsList(response.data.result.data); + + const out = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: `新浪${map[lid]}滚动新闻`, + link: `https://news.sina.com.cn/roll/#pageid=${pageid}&lid=${lid}&k=&num=${limit}&page=1`, + item: out, + }; +}; diff --git a/lib/v2/sina/router.js b/lib/v2/sina/router.js new file mode 100644 index 000000000..4436be188 --- /dev/null +++ b/lib/v2/sina/router.js @@ -0,0 +1,8 @@ +module.exports = (router) => { + router.get('/csj', require('./chuangshiji')); + router.get('/discovery/:type', require('./discovery')); + router.get('/finance/china/:lid?', require('./finance/china')); + router.get('/finance/stock/usstock/:cids?', require('./finance/stock/usstock')); + router.get('/rollnews/:lid?', require('./rollnews')); + router.get('/sports/:type?', require('./sports')); +}; diff --git a/lib/v2/sina/sports.js b/lib/v2/sina/sports.js new file mode 100644 index 000000000..86def3ddf --- /dev/null +++ b/lib/v2/sina/sports.js @@ -0,0 +1,43 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseArticle } = require('./utils'); + +module.exports = async (ctx) => { + const { type } = ctx.params; + + let currentUrl = `https://sports.sina.com.cn/others/${type}.shtml`; + let query = 'ul.list2 li a'; + + if (type === 'ufc') { + currentUrl = 'http://roll.sports.sina.com.cn/s_ufc_all/index.shtml'; + query = '#d_list ul li span a'; + } else if (type === 'winter' || type === 'horse') { + currentUrl = `https://sports.sina.com.cn/${type}/`; + query = '[class^=news-list] .list li a'; + } + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + const list = $(query) + .toArray() + .map((item) => { + item = $(item); + return { + title: item.text(), + link: item.attr('href').replace('http://', 'https://'), + }; + }); + + const items = await Promise.all(list.map((item) => parseArticle(item, ctx.cache.tryGet))); + + ctx.state.data = { + title: `${$('title').text().split('_')[0]} - 新浪体育`, + description: $('meta[name="description"]').attr('content'), + link: currentUrl, + item: items, + }; +}; diff --git a/lib/v2/sina/templates/slide.art b/lib/v2/sina/templates/slide.art new file mode 100644 index 000000000..235e1526a --- /dev/null +++ b/lib/v2/sina/templates/slide.art @@ -0,0 +1,3 @@ +{{ each slideData.images img }} + {{ img.intro }} +{{ /each }} diff --git a/lib/v2/sina/templates/video.art b/lib/v2/sina/templates/video.art new file mode 100644 index 000000000..25d894f14 --- /dev/null +++ b/lib/v2/sina/templates/video.art @@ -0,0 +1,5 @@ +{{ if videoUrl }} + +{{ /if }} diff --git a/lib/v2/sina/utils.js b/lib/v2/sina/utils.js new file mode 100644 index 000000000..4c660243c --- /dev/null +++ b/lib/v2/sina/utils.js @@ -0,0 +1,104 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); +const timezone = require('@/utils/timezone'); +const { art } = require('@/utils/render'); +const { join } = require('path'); + +const getRollNewsList = (pageid, lid, limit) => + got('https://feed.mix.sina.com.cn/api/roll/get', { + headers: { + referer: 'https://news.sina.com.cn/', + }, + searchParams: { + pageid, + lid, + k: '', + num: limit, + page: 1, + r: Math.random(), + _: new Date().getTime(), + }, + }); + +const parseRollNewsList = (data) => + data.map((item) => ({ + title: item.title, + description: item.intro, + link: item.url.replace('http://', 'https://'), + author: item.media_name, + pubDate: parseDate(item.intime, 'X'), + updated: parseDate(item.mtime, 'X'), + })); + +const parseArticle = (item, tryGet) => + tryGet(item.link, async () => { + const detailResponse = await got(item.link); + const $ = cheerio.load(detailResponse.data); + $('#left_hzh_ad, .appendQr_wrap, .app-kaihu-qr, .tech-quotation').remove(); + + const metaPublishTime = $('meta[property="article:published_time"]'); + const htmlPubDate = $('#pub_date, .date'); + const htmlDate = htmlPubDate.length ? timezone(parseDate(htmlPubDate.text(), ['YYYY年MM月DD日 HH:mm', 'YYYY年MM月DD日HH:mm']), 8) : null; + const metaDate = metaPublishTime.length ? parseDate(metaPublishTime.attr('content')) : htmlDate; // 2023-05-08T08:39:31+08:00 + item.pubDate = item.pubDate ? item.pubDate : metaDate; + item.author = $('meta[property="article:author"]').attr('content'); + + if (item.link.startsWith('https://slide.sports.sina.com.cn/') || item.link.startsWith('https://slide.tech.sina.com.cn/')) { + const slideData = JSON.parse( + $('script') + .text() + .match(/var slide_data = (\{.*?\})\s/)[1] + ); + item.description = art(join(__dirname, 'templates/slide.art'), { slideData }); + } else if (item.link.startsWith('https://video.sina.com.cn/')) { + const videoId = $('script') + .text() + .match(/video_id:'?(.*?)'?,/)[1]; + + const { data: videoResponse } = await got('https://api.ivideo.sina.com.cn/public/video/play', { + searchParams: { + video_id: videoId, + appver: 'V11220.210521.03', + appname: 'sinaplayer_pc', + applt: 'web', + tags: 'sinaplayer_pc', + jsonp: '', + plid: 2021012801, + prid: '', + uid: '', + tid: '', + pid: 1, + ran: Math.random(), + r: item.link, + ssid: `gusr_pc_${Date.now()}`, + preload: 0, + uu: '', + isAuto: 1, + }, + }); + + const videoData = videoResponse.data; + const poster = videoData.image; + const videoUrl = videoData.videos.find((v) => v.type === 'mp4').dispatch_result.url; + item.description = art(join(__dirname, 'templates/video.art'), { poster, videoUrl }); + item.pubDate = parseDate(videoData.create_time, 'X'); + } else if (item.link.startsWith('https://news.sina.com.cn/') || item.link.startsWith('https://mil.news.sina.com.cn/')) { + item.description = $('#article').html(); + item.category = $('meta[name="keywords"]').attr('content').split(','); + } else { + // https://ent.sina.com.cn + // https://finance.sina.com.cn + // https://sports.sina.com.cn + item.description = $('#artibody').html(); + item.category = $('#keywords').data('wbkey')?.split(','); + } + + return item; + }); + +module.exports = { + getRollNewsList, + parseRollNewsList, + parseArticle, +};