feat(route): add 木木博客频道 & 标签 & 专题 & 搜索 (#13170)

* feature(route): add 木木博客频道 & 标签 & 专题 & 搜索

* fix typo
This commit is contained in:
Ethan Shen 2023-09-02 01:50:27 +08:00 committed by GitHub
parent 73bb1083cd
commit c103270f7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 232 additions and 114 deletions

View File

@ -0,0 +1,98 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
module.exports = async (ctx) => {
const { params } = ctx.params;
const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 20;
const rootUrl = 'https://www.liulinblog.com';
const currentUrl = params ? new URL(params, rootUrl).href : rootUrl;
const { data: response } = await got(currentUrl);
const $ = cheerio.load(response);
let items = $('div.scroll')
.first()
.find('article')
.slice(0, limit)
.toArray()
.map((item) => {
item = $(item);
const a = item.find('h2.entry-title a');
return {
title: a.prop('title'),
link: a.prop('href'),
description: item.find('div.entry-excerpt').html(),
author: item
.find('span.meta-author a')
.toArray()
.map((a) => $(a).prop('title'))
.join(' / '),
category: item
.find('span.meta-category-dot a[rel="category"]')
.toArray()
.map((c) => $(c).text()),
guid: `liulinblog-${item.prop('id')}`,
pubDate: parseDate(item.find('span.meta-date time').prop('datetime')),
comments: item.find('span.meta-comment').text() ? parseInt(item.find('span.meta-comment').text().trim(), 10) : 0,
};
});
items = await Promise.all(
items.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const { data: detailResponse } = await got(item.link);
const content = cheerio.load(detailResponse);
content('div[role="alert"]').remove();
item.title = content('meta[property="og:title"]').prop('content');
item.description = content('div.entry-content').html();
item.author = content('div.entry-meta')
.first()
.find('span.meta-author a')
.toArray()
.map((a) => content(a).prop('title'))
.join(' / ');
item.category = content('div.entry-meta')
.first()
.find('span.meta-category a[rel="category"]')
.toArray()
.map((c) => content(c).text());
item.guid = `liulinblog-${content('article').first().prop('id')}`;
item.pubDate = parseDate(content('span.meta-date time').first().prop('datetime'));
item.comments = content('h3.comments-title').text()
? parseInt(
content('h3.comments-title')
.text()
.match(/\((\d+)\)/),
10
)
: 0;
return item;
})
)
);
const icon = $('link[rel="icon"]').prop('href');
const title = $('img.logo').prop('alt');
ctx.state.data = {
item: items,
title: `${title} - ${params ? $('h1.term-title').text().split('搜索到')[0] : '最新'}`,
link: currentUrl,
description: $('meta[name="description"]').prop('content'),
language: 'zh-cn',
image: $('img.logo').prop('src'),
icon,
logo: icon,
subtitle: $('p.term-description').text(),
author: title,
};
};

View File

@ -1,23 +0,0 @@
const got = require('@/utils/got');
const { processList, processItems } = require('./utils');
const host = 'https://www.liulinblog.com';
const titleMap = {
internet: '互联网早报',
seo: '站长圈',
};
module.exports = async (ctx) => {
const channel = ctx.params.channel ?? 'internet';
const url = `${host}/itnews/${channel}`;
const response = await got(url);
const list = processList(response);
const items = await processItems(list, ctx);
ctx.state.data = {
title: titleMap[channel],
link: url,
item: items,
};
};

View File

@ -1,17 +0,0 @@
const got = require('@/utils/got');
const { processList, processItems } = require('./utils');
const host = 'https://www.liulinblog.com';
module.exports = async (ctx) => {
const url = `${host}/kuaixun`;
const response = await got(url);
const list = processList(response);
const items = await processItems(list, ctx);
ctx.state.data = {
title: '每天六十秒60秒读懂世界',
link: url,
item: items,
};
};

View File

@ -1,4 +1,8 @@
module.exports = {
'/kuaixun': ['Fatpandac'],
'/itnews/:channel?': ['Fatpandac'],
'/itnews/:channel?': ['Fatpandac', 'nczitzk'],
'/kuaixun': ['Fatpandac', 'nczitzk'],
'/search/:keyword': ['nczitzk'],
'/series/:id': ['nczitzk'],
'/tag/:id': ['nczitzk'],
'/:channel?': ['nczitzk'],
};

View File

@ -3,29 +3,49 @@ module.exports = {
_name: '木木博客',
'.': [
{
title: '每天六十秒60秒读懂世界',
docs: 'https://docs.rsshub.app/routes/new-media#mu-mu-bo-ke',
source: ['/kuaixun'],
target: '/liulinblog/kuaixun',
},
{
title: '互联网早报',
docs: 'https://docs.rsshub.app/routes/new-media#mu-mu-bo-ke',
source: ['/itnews/:channel'],
target: (params) => {
if (params.channel === 'internet') {
return '/liulinblog/itnews/:channel';
}
title: '频道',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/:channel', '/'],
target: (params, url) => {
url = new URL(url);
const path = url.href.match(/\.com(.*?)/)[1];
return `/liulinblog${path === '/' ? '' : path}`;
},
},
{
title: '站长圈',
docs: 'https://docs.rsshub.app/routes/new-media#mu-mu-bo-ke',
source: ['/itnews/:channel'],
target: (params) => {
if (params.channel === 'seo') {
return '/liulinblog/itnews/:channel';
}
title: '标签',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/tag/:id', '/'],
target: '/liulinblog/tag/:id',
},
{
title: '专题',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/series/:id', '/'],
target: '/liulinblog/series/:id',
},
{
title: '搜索',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/search/:keyword', '/'],
target: '/liulinblog/search/:keyword',
},
{
title: '60秒读懂世界',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/kuaixun', '/'],
target: '/liulinblog/kuaixun',
},
{
title: '网络营销',
docs: 'https://docs.rsshub.app/new-media.html#mu-mu-bo-ke',
source: ['/:channel', '/'],
target: (params, url) => {
url = new URL(url);
const path = url.href.match(/\.com(.*?)/)[1];
return `/liulinblog${path === '/' ? '' : path}`;
},
},
],

View File

@ -1,4 +1,8 @@
module.exports = function (router) {
router.get('/kuaixun', require('./kuaixun'));
router.get('/itnews/:channel?', require('./itnews'));
module.exports = (router) => {
router.get('/itnews/:channel', (ctx) => {
const { channel } = ctx.params;
const redirectTo = `/liulinblog/${channel}`;
ctx.redirect(redirectTo);
});
router.get('/:params*', require('./'));
};

View File

@ -1,42 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const processList = (res) => {
const $ = cheerio.load(res.data);
const list = $('div.archive.container > div.row > div > div > div.row.posts-wrapper.scroll > div')
.map((_, item) => ({
title: $(item).find('h2.entry-title').text(),
link: $(item).find('h2.entry-title > a').attr('href'),
pubDate: parseDate($(item).find('time').attr('datetime')),
author: '60秒读懂世界',
}))
.get();
return list;
};
const processItems = async (list, ctx) => {
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detailResponse = await got(item.link);
const $ = cheerio.load(detailResponse.data);
const fullContent = $('div > div.entry-wrapper > div.entry-content');
fullContent.find('img').remove();
fullContent.find('div.pt-0').remove();
fullContent.find('div.post-note').remove();
item.description = fullContent.html();
return item;
})
)
);
return items;
};
module.exports = {
processList,
processItems,
};

View File

@ -3719,17 +3719,91 @@ column 为 third 时可选的 category:
## 木木博客 {#mu-mu-bo-ke}
### 每天六十秒60 秒)读懂世界 {#mu-mu-bo-ke-mei-tian-liu-shi-miao-%EF%BC%8860-miao-%EF%BC%89-du-dong-shi-jie}
### 频道 {#mu-mu-bo-ke-pin-dao}
<Route author="Fatpandac" example="/liulinblog/kuaixun" path="/liulinblog/kuaixun"/>
<Route author="nczitzk" example="/liulinblog" path="/liulinblog/:channel?" paramsDesc={['频道 id可在对应频道页 URL 中找到见下表默认为最新']} radar="1" rssbud="1">
### 科技新闻 {#mu-mu-bo-ke-ke-ji-xin-wen}
| 最新 | 60秒读懂世界 | 精品资源 | 视频资源 | 音频资源 |
| ---- | ------------ | -------- | -------- | -------- |
| | kuaixun | ziyuan | video | yinpin |
<Route author="Fatpandac" example="/liulinblog/itnews/seo" path="/liulinblog/itnews/:channel?" paramsDesc={['频道,默认为互联网早报']}>
| 绝版资源 | 实用文档 | PPT素材 | 后期素材 | 技能教程 |
| -------- | -------- | --------- | -------- | --------- |
| jueban | wendang | ppt-sucai | sucai | jiaocheng |
| 互联网早报 | 站长圈 |
| :--------: | :----: |
| internet | seo |
| 创业副业 | 单机游戏 | 冒险解谜 | 竞技格斗 | 赛车竞技 |
| -------- | -------- | -------- | ----------- | -------- |
| money | game | mxjm | jingjigedou | saiche |
| 模拟经营 | 角色扮演 | 飞行游戏 | 塔防策略 | 射击游戏 |
| -------- | -------- | -------- | -------- | -------- |
| moni | jiaose | feixing | tafang | sheji |
| 恐怖冒险 | 策略生存 | 动作冒险 | 电商运营 | 互联网早报 |
| -------- | -------- | -------- | --------- | ---------- |
| kongbu | celve | dongzuo | dianshang | internet |
| 站长圈 | 自媒体运营 | 短视频 |
| ------ | ---------- | ----------- |
| seo | zimeiti | duan-shipin |
</Route>
### 标签 {#mu-mu-bo-ke-biao-qian}
<Route author="nczitzk" example="/liulinblog/tag/qukuailian" path="/liulinblog/tag/:id" paramsDesc={['标签 id可在对应标签页 URL 中找到见下表']} radar="1" rssbud="1">
| 区块链 | 小红书 | 小说项目 | 微信公众号 | 微信营销 |
| ---------- | ----------- | -------- | ---------- | -------- |
| qukuailian | xiaohongshu | xiaoshuo | 微信公众号 | we-chat |
| 抖音 | 抖音直播 | 拼多多 | 支付宝 | 教育 |
| ---- | -------- | --------- | ------ | ---- |
| 抖音 | 抖音直播 | pinduoduo | alipay | 教育 |
| chrome插件 | galgame汉化游戏 | honeyselect 汉化游戏 | PSD笔刷素材 | ps插件 |
| ---------- | --------------- | -------------------- | ----------- | ---------- |
| chrome插件 | galgame | honey-select | psd-bishua | ps-chajian |
| vip视频 | windows实用技巧 | 下载软件 | 丝袜玉足 | 免费字体下载 |
| ---------- | --------------- | -------- | -------- | ------------ |
| vip-shipin | computer | download | siwa | ziti |
| 二战游戏下载 | 冒险解谜游戏 | 动作游戏下载 | 安卓游戏 | 策略游戏 |
| ------------ | ------------ | ------------ | ------------ | ---------- |
| war-games | 冒险解谜游戏 | 动作游戏下载 | android-game | game-celve |
| Pr插件 | Python | seo优化 | VLOG | wordpress | word技巧 |
| ------ | ------ | ------- | ---- | --------- | -------- |
| pr插件 | python | seo | vlog | wordpress | word |
</Route>
### 专题 {#mu-mu-bo-ke-zhuan-ti}
<Route author="nczitzk" example="/liulinblog/series/xunlei" path="/liulinblog/series/:id" paramsDesc={['专题 id可在对应标签页 URL 中找到见下表']} radar="1" rssbud="1">
| 【免费速存】迅雷资源合集 | 直播带货教程 | 电商培训课程 | 拼多多运营培训 | 小红书运营 | 抖音运营 | 闲鱼运营 | 短视频运营 |
| ------------------------ | ------------ | --------------- | -------------- | ----------- | ------------- | ------------- | ----------------- |
| xunlei | zhibodaihuo | dianshangpeixun | pinduoduo | xiaohongshu | douyinyunying | xianyuyunying | duanshipinyunying |
</Route>
### 搜索 {#mu-mu-bo-ke-sou-suo}
<Route author="nczitzk" example="/liulinblog/search/单机游戏" path="/liulinblog/search/:keyword" paramsDesc={['关键字']} radar="1" rssbud="1"/>
### 60秒读懂世界 {#mu-mu-bo-ke-60-miao-du-dong-shi-jie}
<Route author="Fatpandac nczitzk" example="/liulinblog/kuaixun" path="/liulinblog/kuaixun"/>
### 网络营销 {#mu-mu-bo-ke-wang-luo-ying-xiao}
<Route author="Fatpandac nczitzk" example="/liulinblog/itnews" path="/liulinblog/itnews/:channel?" paramsDesc={['频道,默认为网络营销']}>
| 网络营销 | 电商运营 | 互联网早报 | 站长圈 |
| -------- | --------- | ---------- | ------ |
| | dianshang | internet | seo |
</Route>