fix(route): Tradingview Blog (#14191)
* fix(route): Tradingview Blog * fix: use tiny-async-pool
This commit is contained in:
parent
ee19f9e987
commit
51168fe8e0
|
|
@ -6,55 +6,98 @@ const { art } = require('@/utils/render');
|
|||
const path = require('path');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const language = ctx.params.language ?? 'en';
|
||||
const { category = 'en' } = ctx.params;
|
||||
const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 22;
|
||||
|
||||
const rootUrl = 'https://www.tradingview.com';
|
||||
const currentUrl = `${rootUrl}/blog/${language}`;
|
||||
const currentUrl = new URL(`blog/${category.endsWith('/') ? category : `${category}/`}`, rootUrl).href;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
const { data: response } = await got(currentUrl);
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
const $ = cheerio.load(response);
|
||||
|
||||
const list = $('.articles-grid-item a[rel="bookmark"]')
|
||||
.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 20)
|
||||
const items = $('article[id]')
|
||||
.slice(0, limit)
|
||||
.toArray()
|
||||
.map((item) => {
|
||||
item = $(item);
|
||||
|
||||
const title = item.find('div.title').text();
|
||||
|
||||
return {
|
||||
title: item.find('.title').text(),
|
||||
link: item.attr('href'),
|
||||
pubDate: parseDate(item.find('.date').text(), 'MMMM D, YYYY'),
|
||||
title,
|
||||
link: item.find('a.articles-grid-link').prop('href'),
|
||||
description: art(path.join(__dirname, 'templates/description.art'), {
|
||||
image: {
|
||||
src: item
|
||||
.find('div.articles-grid-img img')
|
||||
.prop('src')
|
||||
.replace(/-\d+x\d+\./, '.'),
|
||||
alt: title,
|
||||
},
|
||||
}),
|
||||
category: item
|
||||
.find('a.section')
|
||||
.toArray()
|
||||
.map((c) => $(c).text()),
|
||||
guid: `tradingview-blog-${category}-${item.prop('id')}`,
|
||||
pubDate: parseDate(item.find('div.date').text(), 'MMM D, YYYY'),
|
||||
};
|
||||
});
|
||||
|
||||
const items = [];
|
||||
for await (const item of asyncPool(3, list, (item) =>
|
||||
for await (const item of asyncPool(3, items, (item) =>
|
||||
ctx.cache.tryGet(item.link, async () => {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
const { data: detailResponse } = await got(item.link);
|
||||
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
const content = cheerio.load(detailResponse);
|
||||
|
||||
content('div.entry-content')
|
||||
.find('img')
|
||||
.each((_, e) => {
|
||||
content(e).replaceWith(
|
||||
art(path.join(__dirname, 'templates/description.art'), {
|
||||
image: {
|
||||
src: content(e)
|
||||
.prop('src')
|
||||
.replace(/-\d+x\d+\./, '.'),
|
||||
width: content(e).prop('width'),
|
||||
height: content(e).prop('height'),
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
item.title = content('meta[property="og:title"]').prop('content');
|
||||
item.description = art(path.join(__dirname, 'templates/description.art'), {
|
||||
image: content('.single-img img').attr('src'),
|
||||
description: content('.entry-content').html(),
|
||||
image: {
|
||||
src: content('meta[property="og:image"]').prop('content'),
|
||||
alt: item.title,
|
||||
},
|
||||
description: content('div.entry-content').html(),
|
||||
});
|
||||
item.author = content('meta[property="og:site_name"]').prop('content');
|
||||
item.category = content('div.sections a.section')
|
||||
.toArray()
|
||||
.map((c) => content(c).text());
|
||||
item.pubDate = parseDate(content('div.single-date').text(), 'MMM D, YYYY');
|
||||
|
||||
return item;
|
||||
})
|
||||
)) {
|
||||
items.shift();
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
const icon = new URL($('link[rel="icon"]').prop('href'), rootUrl).href;
|
||||
|
||||
ctx.state.data = {
|
||||
item: items,
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
description: $('div.site-subtitle').text(),
|
||||
language: $('html').prop('lang'),
|
||||
icon,
|
||||
logo: icon,
|
||||
subtitle: $('h1.site-title').text(),
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = {
|
||||
'/blog/:language?': ['nczitzk'],
|
||||
'/blog/:language?/category/:category?': ['nczitzk'],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,8 +5,92 @@ module.exports = {
|
|||
{
|
||||
title: 'Blog',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language', '/'],
|
||||
target: '/tradingview/blog',
|
||||
source: ['/blog/:language/'],
|
||||
target: '/tradingview/blog/:language/',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Alerts',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/alerts/'],
|
||||
target: '/tradingview/blog/:language/category/alerts',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Bitcoin and Crypto',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/bitcoin-charts/'],
|
||||
target: '/tradingview/blog/:language/category/bitcoin-charts',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Business Updates',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/business-updates/'],
|
||||
target: '/tradingview/blog/:language/category/business-updates',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Charting',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/charts/'],
|
||||
target: '/tradingview/blog/:language/category/charts',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Charting Library',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/charting-library/'],
|
||||
target: '/tradingview/blog/:language/category/charting-library',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Data Feeds and Exchanges',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/data-feeds-exchanges/'],
|
||||
target: '/tradingview/blog/:language/category/data-feeds-exchanges',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Desktop',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/desktop/'],
|
||||
target: '/tradingview/blog/:language/category/desktop',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Market Analysis',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/market-analysis/'],
|
||||
target: '/tradingview/blog/:language/category/market-analysis',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Mobile',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/mobile/'],
|
||||
target: '/tradingview/blog/:language/category/mobile',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Pine Script®',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/pine/'],
|
||||
target: '/tradingview/blog/:language/category/pine',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Screener',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/stock-screener/'],
|
||||
target: '/tradingview/blog/:language/category/stock-screener',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Social',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/social/'],
|
||||
target: '/tradingview/blog/:language/category/social',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Trading and Brokerage',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/trading/'],
|
||||
target: '/tradingview/blog/:language/category/trading',
|
||||
},
|
||||
{
|
||||
title: 'Blog - Widgets',
|
||||
docs: 'https://docs.rsshub.app/routes/program-update#tradingview-blog',
|
||||
source: ['/blog/:language/category/widgets/'],
|
||||
target: '/tradingview/blog/:language/category/widgets',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function (router) {
|
||||
router.get('/blog/:language?', require('./blog'));
|
||||
router.get('/blog/:category*', require('./blog'));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
{{ if image }}
|
||||
<img src="{{ image }}">
|
||||
{{ if image?.src }}
|
||||
<figure>
|
||||
<img
|
||||
{{ if image.alt }}
|
||||
alt="{{ image.alt }}"
|
||||
{{ /if }}
|
||||
src="{{ image.src }}">
|
||||
</figure>
|
||||
{{ /if }}
|
||||
{{@ description }}
|
||||
|
||||
{{ if description }}
|
||||
{{@ description }}
|
||||
{{ /if }}
|
||||
|
|
@ -570,8 +570,8 @@ Logseq 开发团队已经放弃了 [旧网站](https://logseq.com/blog)。
|
|||
|
||||
### Blog {#tradingview-blog}
|
||||
|
||||
<Route author="nczitzk" example="/tradingview/blog/en" path="/tradingview/blog/:language?" paramsDesc={['Language, see below, `en` as English by default']}>
|
||||
Language
|
||||
<Route author="nczitzk" example="/tradingview/blog/en" path="/tradingview/blog/:language?/category/:category?" paramsDesc={['Language, see below, `en` as English by default', 'Category, see below, all by default']} radar="1">
|
||||
#### Language
|
||||
|
||||
| Id | Language |
|
||||
| -- | ------------------- |
|
||||
|
|
@ -595,6 +595,25 @@ Logseq 开发团队已经放弃了 [旧网站](https://logseq.com/blog)。
|
|||
| sv | Svenska |
|
||||
| ar | العربية |
|
||||
| il | Hebrew |
|
||||
|
||||
#### Category
|
||||
|
||||
| Category | ID |
|
||||
| ---------------------------------------------------------------------------------------------- | ----------------------------- |
|
||||
| [Alerts](https://www.tradingview.com/blog/en/category/alerts/) | category/alerts |
|
||||
| [Bitcoin and Crypto](https://www.tradingview.com/blog/en/category/bitcoin-charts/) | category/bitcoin-charts |
|
||||
| [Business Updates](https://www.tradingview.com/blog/en/category/business-updates/) | category/business-updates |
|
||||
| [Charting](https://www.tradingview.com/blog/en/category/charts/) | category/charts |
|
||||
| [Charting Library](https://www.tradingview.com/blog/en/category/charting-library/) | category/charting-library |
|
||||
| [Data Feeds and Exchanges](https://www.tradingview.com/blog/en/category/data-feeds-exchanges/) | category/data-feeds-exchanges |
|
||||
| [Desktop](https://www.tradingview.com/blog/en/category/desktop/) | category/desktop |
|
||||
| [Market Analysis](https://www.tradingview.com/blog/en/category/market-analysis/) | category/market-analysis |
|
||||
| [Mobile](https://www.tradingview.com/blog/en/category/mobile/) | category/mobile |
|
||||
| [Pine Script®](https://www.tradingview.com/blog/en/category/pine/) | category/pine |
|
||||
| [Screener](https://www.tradingview.com/blog/en/category/stock-screener/) | category/stock-screener |
|
||||
| [Social](https://www.tradingview.com/blog/en/category/social/) | category/social |
|
||||
| [Trading and Brokerage](https://www.tradingview.com/blog/en/category/trading/) | category/trading |
|
||||
| [Widgets](https://www.tradingview.com/blog/en/category/widgets/) | category/widgets |
|
||||
</Route>
|
||||
|
||||
## Typora {#typora}
|
||||
|
|
|
|||
Loading…
Reference in New Issue