mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-19 06:38:55 +08:00
feat(route): cw (#10758)
* feat(route): cw * fix: typo * fix: use custom got
This commit is contained in:
@@ -1795,6 +1795,38 @@ category 对应的关键词有
|
|||||||
|
|
||||||
<Route author="TonyRL" example="/taiwannews/hot" path="/taiwannews/hot/:lang?" :paramsDesc="['語言,`en` 或 `zh`,默認 `en`']" radar="1" rssbud="1"/>
|
<Route author="TonyRL" example="/taiwannews/hot" path="/taiwannews/hot/:lang?" :paramsDesc="['語言,`en` 或 `zh`,默認 `en`']" radar="1" rssbud="1"/>
|
||||||
|
|
||||||
|
## 天下雜誌
|
||||||
|
|
||||||
|
### 最新上線
|
||||||
|
|
||||||
|
<Route author="TonyRL" example="/cw/today" path="/cw/today" radar="1" rssbud="1"/>
|
||||||
|
|
||||||
|
### 主頻道
|
||||||
|
|
||||||
|
<Route author="TonyRL" example="/cw/master/8" path="/cw/master/:channel" :paramsDesc="['主頻道 ID,可在 URL 中找到']" radar="1" rssbud="1">
|
||||||
|
|
||||||
|
| 主頻道名稱 | 主頻道 ID |
|
||||||
|
| ----- | ------ |
|
||||||
|
| 財經 | 8 |
|
||||||
|
| 產業 | 7 |
|
||||||
|
| 國際 | 9 |
|
||||||
|
| 管理 | 10 |
|
||||||
|
| 環境 | 12 |
|
||||||
|
| 教育 | 13 |
|
||||||
|
| 人物 | 14 |
|
||||||
|
| 政治社會 | 77 |
|
||||||
|
| 調查排行 | 15 |
|
||||||
|
| 健康關係 | 79 |
|
||||||
|
| 時尚品味 | 11 |
|
||||||
|
| 運動生活 | 103 |
|
||||||
|
| 重磅外媒 | 16 |
|
||||||
|
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
### 子頻道
|
||||||
|
|
||||||
|
<Route author="TonyRL" example="/cw/sub/615" path="/cw/sub/:channel" :paramsDesc="['子頻道 ID,可在 URL 中找到']" radar="1" rssbud="1"/>
|
||||||
|
|
||||||
## 卫报 The Guardian
|
## 卫报 The Guardian
|
||||||
|
|
||||||
通过提取文章全文,以提供比官方源更佳的阅读体验。
|
通过提取文章全文,以提供比官方源更佳的阅读体验。
|
||||||
|
|||||||
5
lib/v2/cw/maintainer.js
Normal file
5
lib/v2/cw/maintainer.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
'/master/:channel': ['TonyRL'],
|
||||||
|
'/sub/:channel': ['TonyRL'],
|
||||||
|
'/today': ['TonyRL'],
|
||||||
|
};
|
||||||
28
lib/v2/cw/master.js
Normal file
28
lib/v2/cw/master.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const cheerio = require('cheerio');
|
||||||
|
const { baseUrl, cookieJar, got, parseList, parseItems } = require('./utils');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const { channel } = ctx.params;
|
||||||
|
const pageUrl = `${baseUrl}/masterChannel.action`;
|
||||||
|
const { data: response } = await got(pageUrl, {
|
||||||
|
headers: {
|
||||||
|
Referer: baseUrl,
|
||||||
|
},
|
||||||
|
cookieJar,
|
||||||
|
searchParams: {
|
||||||
|
idMasterChannel: channel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const $ = cheerio.load(response);
|
||||||
|
|
||||||
|
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : 100);
|
||||||
|
const items = await parseItems(list, ctx.cache.tryGet);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: $('head title').text(),
|
||||||
|
description: $('meta[name=description]').attr('content'),
|
||||||
|
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||||
|
language: $('meta[property="og:locale"]').attr('content'),
|
||||||
|
item: items,
|
||||||
|
};
|
||||||
|
};
|
||||||
25
lib/v2/cw/radar.js
Normal file
25
lib/v2/cw/radar.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
'cw.com.tw': {
|
||||||
|
_name: '天下雜誌',
|
||||||
|
'.': [
|
||||||
|
{
|
||||||
|
title: '最新上線',
|
||||||
|
docs: 'https://docs.rsshub.app/traditional-media.html#tian-xia-za-zhi',
|
||||||
|
source: ['/today', '/'],
|
||||||
|
target: '/cw/today',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '主頻道',
|
||||||
|
docs: 'https://docs.rsshub.app/traditional-media.html#tian-xia-za-zhi',
|
||||||
|
source: ['/masterChannel.action'],
|
||||||
|
target: (_, url) => `/cw/master/${new URL(url).searchParams.get('idMasterChannel')}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '子頻道',
|
||||||
|
docs: 'https://docs.rsshub.app/traditional-media.html#tian-xia-za-zhi',
|
||||||
|
source: ['/subchannel.action'],
|
||||||
|
target: (_, url) => `/cw/sub/${new URL(url).searchParams.get('idSubChannel')}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
5
lib/v2/cw/router.js
Normal file
5
lib/v2/cw/router.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = (router) => {
|
||||||
|
router.get('/master/:channel', require('./master'));
|
||||||
|
router.get('/sub/:channel', require('./sub'));
|
||||||
|
router.get('/today', require('./today'));
|
||||||
|
};
|
||||||
28
lib/v2/cw/sub.js
Normal file
28
lib/v2/cw/sub.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
const cheerio = require('cheerio');
|
||||||
|
const { baseUrl, cookieJar, got, parseList, parseItems } = require('./utils');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const { channel } = ctx.params;
|
||||||
|
const pageUrl = `${baseUrl}/subchannel.action`;
|
||||||
|
const { data: response } = await got(pageUrl, {
|
||||||
|
headers: {
|
||||||
|
Referer: baseUrl,
|
||||||
|
},
|
||||||
|
cookieJar,
|
||||||
|
searchParams: {
|
||||||
|
idSubChannel: channel,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const $ = cheerio.load(response);
|
||||||
|
|
||||||
|
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : 100);
|
||||||
|
const items = await parseItems(list, ctx.cache.tryGet);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: $('head title').text(),
|
||||||
|
description: $('meta[name=description]').attr('content'),
|
||||||
|
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||||
|
language: $('meta[property="og:locale"]').attr('content'),
|
||||||
|
item: items,
|
||||||
|
};
|
||||||
|
};
|
||||||
24
lib/v2/cw/today.js
Normal file
24
lib/v2/cw/today.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
const cheerio = require('cheerio');
|
||||||
|
const { baseUrl, cookieJar, got, parseList, parseItems } = require('./utils');
|
||||||
|
|
||||||
|
module.exports = async (ctx) => {
|
||||||
|
const pageUrl = `${baseUrl}/today`;
|
||||||
|
const { data: response } = await got(pageUrl, {
|
||||||
|
headers: {
|
||||||
|
Referer: baseUrl,
|
||||||
|
},
|
||||||
|
cookieJar,
|
||||||
|
});
|
||||||
|
const $ = cheerio.load(response);
|
||||||
|
|
||||||
|
const list = parseList(response, ctx.query.limit ? Number(ctx.query.limit) : 100);
|
||||||
|
const items = await parseItems(list, ctx.cache.tryGet);
|
||||||
|
|
||||||
|
ctx.state.data = {
|
||||||
|
title: $('head title').text(),
|
||||||
|
description: $('meta[name=description]').attr('content'),
|
||||||
|
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||||
|
language: $('meta[property="og:locale"]').attr('content'),
|
||||||
|
item: items,
|
||||||
|
};
|
||||||
|
};
|
||||||
63
lib/v2/cw/utils.js
Normal file
63
lib/v2/cw/utils.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
const cheerio = require('cheerio');
|
||||||
|
const { parseDate } = require('@/utils/parse-date');
|
||||||
|
const { CookieJar } = require('tough-cookie');
|
||||||
|
const cookieJar = new CookieJar();
|
||||||
|
const config = require('@/config').value;
|
||||||
|
|
||||||
|
const baseUrl = 'https://www.cw.com.tw';
|
||||||
|
|
||||||
|
const got = require('@/utils/got').extend({
|
||||||
|
headers: {
|
||||||
|
'User-Agent': config.trueUA,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const parseList = ($, limit) =>
|
||||||
|
$('.caption')
|
||||||
|
.toArray()
|
||||||
|
.map((item) => {
|
||||||
|
item = $(item);
|
||||||
|
return {
|
||||||
|
title: item.find('h3').text(),
|
||||||
|
link: item.find('h3 a').attr('href'),
|
||||||
|
pubDate: parseDate(item.find('time').text()),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.slice(0, limit);
|
||||||
|
|
||||||
|
const parseItems = (list, tryGet) =>
|
||||||
|
Promise.all(
|
||||||
|
list.map((item) =>
|
||||||
|
tryGet(item.link, async () => {
|
||||||
|
const { data: response } = await got(item.link, {
|
||||||
|
cookieJar,
|
||||||
|
});
|
||||||
|
|
||||||
|
const $ = cheerio.load(response);
|
||||||
|
const meta = JSON.parse($('head script[type="application/ld+json"]').eq(0).text());
|
||||||
|
$('.article__head .breadcrumb, .article__head h1, .article__provideViews, .ad').remove();
|
||||||
|
$('img.lazyload').each((_, img) => {
|
||||||
|
if (img.attribs['data-src']) {
|
||||||
|
img.attribs.src = img.attribs['data-src'];
|
||||||
|
delete img.attribs['data-src'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
item.title = $('head title').text();
|
||||||
|
item.category = $('meta[name=keywords]').attr('content').split(',');
|
||||||
|
item.pubDate = parseDate(meta.datePublished);
|
||||||
|
item.author = meta.author.name.replace(',', ' ') || meta.publisher.name;
|
||||||
|
item.description = $('.article__head .container').html() + $('.article__content').html();
|
||||||
|
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
baseUrl,
|
||||||
|
cookieJar,
|
||||||
|
got,
|
||||||
|
parseList,
|
||||||
|
parseItems,
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user