mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-24 23:12:34 +08:00
@@ -270,6 +270,26 @@ type 为 all 时,category 参数不支持 cost 和 free
|
||||
|
||||
</Route>
|
||||
|
||||
## wikiHow
|
||||
|
||||
### 首页
|
||||
|
||||
<Route author="sanmmm" example="/wikihow/index" path="/wikihow/index"/>
|
||||
|
||||
### 分类目录
|
||||
|
||||
<Route author="sanmmm" example="/wikihow/category/饮食与休闲/" path="/wikihow/category/:category/:type" :paramsDesc="['目录分类', '类型']">
|
||||
|
||||
顶级目录分类可在目录分类页[查看](https://zh.wikihow.com/Special:CategoryListing), 支持二级目录
|
||||
|
||||
类型
|
||||
|
||||
| 所有 | 推荐 |
|
||||
| ---- | ---- |
|
||||
| all | rec |
|
||||
|
||||
</Route>
|
||||
|
||||
## ZAKER
|
||||
|
||||
### source
|
||||
@@ -1041,6 +1061,24 @@ type 为 all 时,category 参数不支持 cost 和 free
|
||||
|
||||
</Route>
|
||||
|
||||
## 正版中国
|
||||
|
||||
### 分类列表
|
||||
|
||||
<Route author="sanmmm" example="/getitfree/category/8" path="/getitfree/category/category?" :paramsDesc="['内容类型, 默认为`全部`']">
|
||||
|
||||
类型
|
||||
|
||||
| 全部文章 | 永久免费 | 限时折扣 | 限时免费 | PC | Mac | Android | UWP |
|
||||
| -------- | -------- | -------- | -------- | --- | --- | ------- | --- |
|
||||
| all | 311 | 309 | 310 | 8 | 50 | 17 | 312 |
|
||||
|
||||
</Route>
|
||||
|
||||
### 搜索
|
||||
|
||||
<Route author="sanmmm" example="/getitfree/search/windows" path="/getitfree/search/:keyword" :paramsDesc="['搜索关键词']"/>
|
||||
|
||||
## 中国大学 MOOC(慕课)
|
||||
|
||||
### 最新
|
||||
|
||||
@@ -1545,4 +1545,12 @@ router.get('/ff14/ff14_zh/:type', require('./routes/ff14/ff14_zh'));
|
||||
router.get('/xuetangx/course/:cid/:type', require('./routes/xuetangx/course_info'));
|
||||
router.get('/xuetangx/course/list/:mode/:credential/:status/:type?', require('./routes/xuetangx/course_list'));
|
||||
|
||||
// wikihow
|
||||
router.get('/wikihow/index', require('./routes/wikihow/index.js'));
|
||||
router.get('/wikihow/category/:category/:type', require('./routes/wikihow/category.js'));
|
||||
|
||||
// 正版中国
|
||||
router.get('/getitfree/category/:category?', require('./routes/getitfree/category.js'));
|
||||
router.get('/getitfree/search/:keyword?', require('./routes/getitfree/search.js'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { category = 'all' } = ctx.params;
|
||||
const baseUrl = `https://getitfree.cn`;
|
||||
const categoryToLabel = {
|
||||
'8': 'PC',
|
||||
'17': 'Android',
|
||||
'50': 'Mac',
|
||||
'309': '限时折扣',
|
||||
'310': '限时免费',
|
||||
'311': '永久免费',
|
||||
'312': 'UWP',
|
||||
all: '全部文章',
|
||||
};
|
||||
|
||||
let item = [];
|
||||
if (category === 'all') {
|
||||
const res = await got(baseUrl);
|
||||
const $ = cheerio.load(res.data);
|
||||
$('#page-content .top-content .top-slide > .item')
|
||||
.toArray()
|
||||
.forEach((ele) => {
|
||||
const $item = cheerio.load(ele);
|
||||
const infoNode = $item('.slider-image > a');
|
||||
const title = infoNode.attr('title');
|
||||
const link = infoNode.attr('href');
|
||||
const thumbnail = infoNode.attr('style').replace(/background-image:url\(|\)/g, '');
|
||||
const deadlineStr = utils.getDeadlineStr($item, '.countDownCont');
|
||||
const description = [title, deadlineStr, `<a href="${thumbnail}"/>`].filter((str) => !!str).join('<br/>');
|
||||
item.push({
|
||||
title,
|
||||
link,
|
||||
description,
|
||||
});
|
||||
});
|
||||
item = item.concat(utils.parseListItem($, '.main-content'));
|
||||
} else {
|
||||
const res = await got(baseUrl, {
|
||||
query: {
|
||||
action: 'fa_load_postlist',
|
||||
paged: 1,
|
||||
category,
|
||||
},
|
||||
});
|
||||
const $ = cheerio.load(res.data);
|
||||
item = utils.parseListItem($, '.ajax-load-con');
|
||||
}
|
||||
|
||||
const categoryLabel = categoryToLabel[category];
|
||||
ctx.state.data = {
|
||||
title: `正版中国 - ${categoryLabel}`,
|
||||
description: `正版中国 - ${categoryLabel}`,
|
||||
link: baseUrl,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const qs = require('query-string');
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { keyword } = ctx.params;
|
||||
const link = 'https://getitfree.cn';
|
||||
const query = {
|
||||
s: keyword,
|
||||
};
|
||||
const res = await got(link, {
|
||||
query,
|
||||
});
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
const item = utils.parseListItem($, '#page-content');
|
||||
|
||||
ctx.state.data = {
|
||||
title: `正版中国搜索 - ${keyword}`,
|
||||
description: `正版中国搜索 - ${keyword}`,
|
||||
link: `${link}?${qs.stringify(query)}`,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const getDeadlineStr = ($, countDownNodeSelector) => {
|
||||
const countDownNode = $(countDownNodeSelector);
|
||||
let deadlineStr = '';
|
||||
if (countDownNode.text().includes('活动已经结束')) {
|
||||
return '截至日期: 活动已经结束';
|
||||
}
|
||||
const countdownCodeStr = countDownNode.children('script').html() || '';
|
||||
const arr = /ShowCountDown\("\d*"\s*,\s*([\d,]+)\s*\)/.exec(countdownCodeStr.trim());
|
||||
if (arr) {
|
||||
const dateStr = arr[1].replace(/,/g, (...args) => {
|
||||
const index = args[args.length - 2];
|
||||
return index === 10 ? ' ' : index < 10 ? '-' : ':';
|
||||
});
|
||||
deadlineStr = `截至日期: ${new Date(dateStr).toUTCString()}`;
|
||||
}
|
||||
return deadlineStr;
|
||||
};
|
||||
|
||||
const parseListItem = ($, listSelector) =>
|
||||
$(`${listSelector} .content-box`)
|
||||
.map((_, ele) => {
|
||||
const $item = cheerio.load(ele);
|
||||
const infoNode = $item('.posts-default-title > h2 > a');
|
||||
const title = infoNode.attr('title');
|
||||
const link = infoNode.attr('href');
|
||||
const pubDateStr = $item('.posts-default-info .icon-time').text();
|
||||
const pubDate = new Date(pubDateStr).toUTCString();
|
||||
const thumbnail = $item('.posts-default-img img').attr('data-original');
|
||||
const deadlineStr = getDeadlineStr($item, '.countDownCont');
|
||||
const digest = $item('.posts-default-content > .posts-text')
|
||||
.text()
|
||||
.trim();
|
||||
return {
|
||||
title,
|
||||
link,
|
||||
pubDate,
|
||||
description: [title, deadlineStr, digest, `<img src="${thumbnail}"/>`].filter((str) => !!str).join('<br/>'),
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
module.exports = {
|
||||
getDeadlineStr,
|
||||
parseListItem,
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const { category, type = 'all' } = ctx.params;
|
||||
const link = encodeURI(`https://zh.wikihow.com/Category:${category}`);
|
||||
const res = await got(link);
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
const itemsSelector = type === 'all' ? '#cat_featured .thumbnail' : '#cat_all .thumbnail';
|
||||
const item = $(itemsSelector)
|
||||
.map((_, ele) => {
|
||||
const $item = cheerio.load(ele);
|
||||
const title = '如何' + $item('.text span').text();
|
||||
const link = $item('a').attr('href');
|
||||
const thumbnail = $item('img').attr('data-src');
|
||||
return {
|
||||
title,
|
||||
description: `
|
||||
${title}<br/>
|
||||
<img src="${thumbnail}"/>
|
||||
`,
|
||||
link,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: `wikiHow - ${category}`,
|
||||
description: `wikiHow - ${category}`,
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const link = `https://zh.wikihow.com/${encodeURIComponent('首页')}`;
|
||||
const res = await got(link);
|
||||
const $ = cheerio.load(res.data);
|
||||
|
||||
const item = $('#fa_container td.image_map')
|
||||
.map((_, ele) => {
|
||||
const $item = cheerio.load(ele);
|
||||
const title = '如何' + $item('.text span').text();
|
||||
const link = $item('.thumbnail > a').attr('href');
|
||||
const thumbnail = $item('.thumbnail img').attr('data-src');
|
||||
return {
|
||||
title,
|
||||
description: `
|
||||
${title}<br/>
|
||||
<img src="${thumbnail}"/>
|
||||
`,
|
||||
link,
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
ctx.state.data = {
|
||||
title: 'wikiHow - 首页',
|
||||
description: 'wikiHow - 首页',
|
||||
link,
|
||||
item,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user