feat(route): wxkol (#12010)

* feat(route): wxkol

* fix: use async pool
This commit is contained in:
Tony
2023-03-03 01:59:45 +08:00
committed by GitHub
parent 85eab969a1
commit a9d6957e60
6 changed files with 113 additions and 4 deletions
+13 -3
View File
@@ -3940,6 +3940,12 @@ column 为 third 时可选的 category:
<Route author="nczitzk" example="/tam/forecast" path="/tam/forecast"/>
## 微小领
### 微信公众号
<Route author="TonyRL" example="/wxkol/show/3590876722" path="/wxkol/show/:id" :paramsDesc="['公众号 id,可在 URL 找到']" radar="1"/>
## 微信
::: tip 提示
@@ -3950,15 +3956,15 @@ column 为 third 时可选的 category:
### 公众号(CareerEngine 来源)
<Route author="HenryQW" example="/wechat/ce/595a5b14d7164e53908f1606" path="/wechat/ce/:id" :paramsDesc="['公众号 id, 在 [CareerEngine](https://search.careerengine.us/) 搜索公众号,通过 URL 中找到对应的公众号 id']" anticrawler="1"/>
<Route author="HenryQW" example="/wechat/ce/595a5b14d7164e53908f1606" path="/wechat/ce/:id" :paramsDesc="['公众号 id,在 [CareerEngine](https://search.careerengine.us/) 搜索公众号,通过 URL 中找到对应的公众号 id']" anticrawler="1"/>
### 公众号(二十次幂来源)
<Route author="sanmmm" example="/wechat/ershicimi/813oxJOl" path="/wechat/ershicimi/:id" :paramsDesc="['公众号id, 打开公众号页, 在 URL 中找到 id']" anticrawler="1"/>
<Route author="sanmmm" example="/wechat/ershicimi/813oxJOl" path="/wechat/ershicimi/:id" :paramsDesc="['公众号id,打开公众号页,在 URL 中找到 id']" anticrawler="1"/>
### 公众号(Telegram 频道来源)
<Route author="LogicJake Rongronggg9" example="/wechat/tgchannel/lifeweek" path="/wechat/tgchannel/:id/:mpName?/:searchQueryType?" :paramsDesc="['公众号绑定频道 id', '欲筛选的公众号全名(URL-encoded, 精确匹配),在频道订阅了多个公众号时可选用', '搜索查询类型,见下表']">
<Route author="LogicJake Rongronggg9" example="/wechat/tgchannel/lifeweek" path="/wechat/tgchannel/:id/:mpName?/:searchQueryType?" :paramsDesc="['公众号绑定频道 id', '欲筛选的公众号全名(URL-encoded,精确匹配),在频道订阅了多个公众号时可选用', '搜索查询类型,见下表']">
| 搜索查询类型 | 将使用的搜索关键字 | 适用于 |
| :----: | :-------: | :----------------------: |
@@ -3992,6 +3998,10 @@ column 为 third 时可选的 category:
<Route author="TonyRL" example="/wechat/wechat2rss/5b925323244e9737c39285596c53e3a2f4a30774" path="/wechat/wechat2rss/:id" :paramsDesc="['公众号 id,打开 `https://wechat2rss.xlab.app/posts/list/`,在 URL 中找到 id;注意不是公众号页的 id,而是订阅的 id']" radar="1"/>
### 公众号(微小领来源)
见 [#微小领](#wei-xiao-ling)
### 公众号栏目 (非推送 & 历史消息)
<Route author="MisteryMonster" example="/wechat/mp/homepage/MzA3MDM3NjE5NQ==/16" path="/wechat/mp/homepage/:biz/:hid/:cid?" :paramsDesc="['公众号id', '分页id', '页内栏目']" radar="1" rssbud="1" anticrawler="1">
+1 -1
View File
@@ -222,7 +222,7 @@ const fetchArticle = (ctx, url, bypassHostCheck = false) => {
let mpName = $('.profile_nickname').first().text();
mpName = mpName && mpName.trim();
return { title, author, description, summary, pubDate, mpName, link: url };
return { title, author, description, summary, pubDate, mpName, link: response.url };
});
};
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
'/show/:id': ['TonyRL'],
};
+13
View File
@@ -0,0 +1,13 @@
module.exports = {
'wxkol.com': {
_name: '微小领',
'.': [
{
title: '微信公众号',
docs: 'https://docs.rsshub.app/new-media.html#wei-xiao-ling',
source: ['/show/:id'],
target: (params) => `/wxkol/show/${params.id.replace('.html', '')}`,
},
],
},
};
+3
View File
@@ -0,0 +1,3 @@
module.exports = (router) => {
router.get('/show/:id', require('./show'));
};
+80
View File
@@ -0,0 +1,80 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { fetchArticle } = require('@/utils/wechat-mp');
const config = require('@/config').value;
const asyncPool = require('tiny-async-pool');
module.exports = async (ctx) => {
const baseUrl = 'https://www.wxkol.com';
const { id } = ctx.params;
const url = `${baseUrl}/show/${id}.html`;
const asyncPoolAll = async (...args) => {
const results = [];
for await (const result of asyncPool(...args)) {
results.push(result);
}
return results;
};
const feedData = await ctx.cache.tryGet(
url,
async () => {
const { data: response } = await got(url);
const $ = cheerio.load(response);
const list = $('.artlist li')
.toArray()
.map((item) => {
item = $(item);
const a = item.find('.title a');
return {
title: a.attr('title'),
link: `${baseUrl}${a.attr('href')}`,
};
});
return {
feedTitle: $('head title').text(),
feedDescription: $('head description').text(),
feedImage: $('.main .logo .avatar')
.attr('style')
.match(/url\('(.+)'\)/)[1],
feedItem: list,
};
},
config.cache.routeExpire,
false
);
const urlList = await asyncPoolAll(2, feedData.feedItem, (item) =>
ctx.cache.tryGet(item.link, async () => {
const { data: response } = await got(item.link);
const $ = cheerio.load(response);
item.link = `${baseUrl}${$('.source a').attr('href')}`;
return item;
})
);
const items = await asyncPoolAll(4, urlList, async (item) => {
const { title, author, description, summary, pubDate, mpName, link: itemLink } = await fetchArticle(ctx, item.link, true);
item.title = title;
item.author = author;
item.description = description;
item.summary = summary;
item.pubDate = pubDate;
item.author = mpName;
item.link = itemLink;
return item;
});
ctx.state.data = {
title: feedData.feedTitle,
description: feedData.feedDescription,
link: url,
image: feedData.feedImage,
item: items,
};
};