feat(route): cw author (#11618)
This commit is contained in:
parent
b0253d09d8
commit
2502bef792
|
|
@ -2071,6 +2071,10 @@ category 对应的关键词有
|
|||
|
||||
<Route author="TonyRL" example="/cw/sub/615" path="/cw/sub/:channel" :paramsDesc="['子頻道 ID,可在 URL 中找到']" radar="1" rssbud="1" puppeteer="1"/>
|
||||
|
||||
### 作者
|
||||
|
||||
<Route author="TonyRL" example="/cw/author/57" path="/cw/author/:channel" :paramsDesc="['作者 ID,可在 URL 中找到']" radar="1" rssbud="1" puppeteer="1"/>
|
||||
|
||||
## 卫报 The Guardian
|
||||
|
||||
通过提取文章全文,以提供比官方源更佳的阅读体验。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
const { baseUrl, parsePage } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const browser = await require('@/utils/puppeteer')();
|
||||
|
||||
const { $, items } = await parsePage('author', browser, ctx);
|
||||
|
||||
await browser.close();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('head title').text(),
|
||||
description: $('.authorTxt').text(),
|
||||
link: `${baseUrl}/author/${ctx.params.channel}`,
|
||||
image: $('.authorPhoto img').attr('src') || `${baseUrl}/assets_new/img/fbshare.jpg'`,
|
||||
language: $('meta[property="og:locale"]').attr('content'),
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = {
|
||||
'/author/:channel': ['TonyRL'],
|
||||
'/master/:channel': ['TonyRL'],
|
||||
'/sub/:channel': ['TonyRL'],
|
||||
'/today': ['TonyRL'],
|
||||
|
|
|
|||
|
|
@ -1,34 +1,16 @@
|
|||
const cheerio = require('cheerio');
|
||||
const { baseUrl, parseList, parseItems, getCookie, setCookies } = require('./utils');
|
||||
const { baseUrl, parsePage } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { channel } = ctx.params;
|
||||
const pageUrl = `${baseUrl}/masterChannel.action`;
|
||||
|
||||
const browser = await require('@/utils/puppeteer')();
|
||||
const cookie = await getCookie(browser, ctx.cache.tryGet);
|
||||
const page = await browser.newPage();
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (request) => {
|
||||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
await setCookies(page, cookie, 'cw.com.tw');
|
||||
await page.goto(`${pageUrl}?idMasterChannel=${channel}`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
||||
const response = await page.evaluate(() => document.documentElement.innerHTML);
|
||||
await page.close();
|
||||
const $ = cheerio.load(response);
|
||||
|
||||
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : 12);
|
||||
const items = await parseItems(list, browser, ctx.cache.tryGet);
|
||||
const { $, items } = await parsePage('master', browser, ctx);
|
||||
|
||||
await browser.close();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('head title').text(),
|
||||
description: $('meta[name=description]').attr('content'),
|
||||
link: `${baseUrl}/masterChannel.action?idMasterChannel=${ctx.params.channel}`,
|
||||
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||
language: $('meta[property="og:locale"]').attr('content'),
|
||||
item: items,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ module.exports = {
|
|||
source: ['/subchannel.action'],
|
||||
target: (_, url) => `/cw/sub/${new URL(url).searchParams.get('idSubChannel')}`,
|
||||
},
|
||||
{
|
||||
title: '作者',
|
||||
docs: 'https://docs.rsshub.app/traditional-media.html#tian-xia-za-zhi',
|
||||
source: ['/author/:channel'],
|
||||
target: '/cw/author/:channel',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
module.exports = (router) => {
|
||||
router.get('/author/:channel', require('./author'));
|
||||
router.get('/master/:channel', require('./master'));
|
||||
router.get('/sub/:channel', require('./sub'));
|
||||
router.get('/today', require('./today'));
|
||||
|
|
|
|||
|
|
@ -1,34 +1,16 @@
|
|||
const cheerio = require('cheerio');
|
||||
const { baseUrl, parseList, parseItems, getCookie, setCookies } = require('./utils');
|
||||
const { baseUrl, parsePage } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { channel } = ctx.params;
|
||||
const pageUrl = `${baseUrl}/subchannel.action`;
|
||||
|
||||
const browser = await require('@/utils/puppeteer')();
|
||||
const cookie = await getCookie(browser, ctx.cache.tryGet);
|
||||
const page = await browser.newPage();
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (request) => {
|
||||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
await setCookies(page, cookie, 'cw.com.tw');
|
||||
await page.goto(`${pageUrl}?idSubChannel=${channel}`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
||||
const response = await page.evaluate(() => document.documentElement.innerHTML);
|
||||
await page.close();
|
||||
const $ = cheerio.load(response);
|
||||
|
||||
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : 12);
|
||||
const items = await parseItems(list, browser, ctx.cache.tryGet);
|
||||
const { $, items } = await parsePage('sub', browser, ctx);
|
||||
|
||||
await browser.close();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('head title').text(),
|
||||
description: $('meta[name=description]').attr('content'),
|
||||
link: `${baseUrl}/subchannel.action?idSubChannel=${ctx.params.channel}`,
|
||||
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||
language: $('meta[property="og:locale"]').attr('content'),
|
||||
item: items,
|
||||
|
|
|
|||
|
|
@ -1,33 +1,16 @@
|
|||
const cheerio = require('cheerio');
|
||||
const { baseUrl, parseList, parseItems, getCookie, setCookies } = require('./utils');
|
||||
const { baseUrl, parsePage } = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const pageUrl = `${baseUrl}/today`;
|
||||
|
||||
const browser = await require('@/utils/puppeteer')();
|
||||
const cookie = await getCookie(browser, ctx.cache.tryGet);
|
||||
const page = await browser.newPage();
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (request) => {
|
||||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
await setCookies(page, cookie, 'cw.com.tw');
|
||||
await page.goto(pageUrl, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
||||
const response = await page.evaluate(() => document.documentElement.innerHTML);
|
||||
await page.close();
|
||||
const $ = cheerio.load(response);
|
||||
|
||||
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : 30);
|
||||
const items = await parseItems(list, browser, ctx.cache.tryGet);
|
||||
const { $, items } = await parsePage('today', browser, ctx);
|
||||
|
||||
await browser.close();
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('head title').text(),
|
||||
description: $('meta[name=description]').attr('content'),
|
||||
link: `${baseUrl}/today`,
|
||||
image: `${baseUrl}/assets_new/img/fbshare.jpg`,
|
||||
language: $('meta[property="og:locale"]').attr('content'),
|
||||
item: items,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,30 @@
|
|||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
const { getCookies, setCookies } = require('@/utils/puppeteer-utils');
|
||||
const logger = require('@/utils/logger');
|
||||
let cookie;
|
||||
|
||||
const baseUrl = 'https://www.cw.com.tw';
|
||||
|
||||
const pathMap = {
|
||||
today: {
|
||||
pageUrl: () => '/today',
|
||||
limit: 30,
|
||||
},
|
||||
master: {
|
||||
pageUrl: (channel) => `/masterChannel.action?idMasterChannel=${channel}`,
|
||||
limit: 12,
|
||||
},
|
||||
sub: {
|
||||
pageUrl: (channel) => `/subchannel.action?idSubChannel=${channel}`,
|
||||
limit: 12,
|
||||
},
|
||||
author: {
|
||||
pageUrl: (channel) => `/author/${channel}`,
|
||||
limit: 10,
|
||||
},
|
||||
};
|
||||
|
||||
const getCookie = async (browser, tryGet) => {
|
||||
if (!cookie) {
|
||||
cookie = await tryGet('cw:cookie', async () => {
|
||||
|
|
@ -13,6 +33,7 @@ const getCookie = async (browser, tryGet) => {
|
|||
page.on('request', (request) => {
|
||||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
logger.debug(`Requesting ${baseUrl}/user/get/cookie-bar`);
|
||||
await page.goto(`${baseUrl}/user/get/cookie-bar`, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
|
@ -24,6 +45,31 @@ const getCookie = async (browser, tryGet) => {
|
|||
return cookie;
|
||||
};
|
||||
|
||||
const parsePage = async (path, browser, ctx) => {
|
||||
const pageUrl = `${baseUrl}${pathMap[path].pageUrl(ctx.params.channel)}`;
|
||||
|
||||
const cookie = await getCookie(browser, ctx.cache.tryGet);
|
||||
const page = await browser.newPage();
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (request) => {
|
||||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
await setCookies(page, cookie, 'cw.com.tw');
|
||||
logger.debug(`Requesting ${pageUrl}`);
|
||||
await page.goto(pageUrl, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
||||
const response = await page.evaluate(() => document.documentElement.innerHTML);
|
||||
await page.close();
|
||||
const $ = cheerio.load(response);
|
||||
|
||||
const list = parseList($, ctx.query.limit ? Number(ctx.query.limit) : pathMap[path].limit);
|
||||
const items = await parseItems(list, browser, ctx.cache.tryGet);
|
||||
|
||||
return { $, items };
|
||||
};
|
||||
|
||||
const parseList = ($, limit) =>
|
||||
$('.caption')
|
||||
.toArray()
|
||||
|
|
@ -47,6 +93,7 @@ const parseItems = (list, browser, tryGet) =>
|
|||
request.resourceType() === 'document' || request.resourceType() === 'script' ? request.continue() : request.abort();
|
||||
});
|
||||
await setCookies(page, cookie, 'cw.com.tw');
|
||||
logger.debug(`Requesting ${item.link}`);
|
||||
await page.goto(item.link, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
|
@ -77,8 +124,10 @@ const parseItems = (list, browser, tryGet) =>
|
|||
|
||||
module.exports = {
|
||||
baseUrl,
|
||||
pathMap,
|
||||
getCookie,
|
||||
setCookies,
|
||||
parsePage,
|
||||
parseList,
|
||||
parseItems,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue