本文由 简悦 SimpRead 转码, 原文地址 blog.mjyai.com
官方文档简洁清晰,再增加内容就显得臃肿了。故另外写一篇对新手友好的指南。
发表于 2021-01-31|更新于 2022-10-22|笔记
| 阅读量:
官方文档简洁清晰,再增加内容就显得臃肿了。故另外写一篇对新手友好的指南。
万物皆可 RSS,这个项目是一个将任意网页内容转换为 RSS 的框架。其开源性质其实是鼓励大家按个人需求自己动手写规则的。
有的网站是有提供 RSS 的,如果你只是需要全文输出可以结合 full-text-rss 来实现。
有的网站已经有 RSSHub 规则了,可以通过 RSSHub Radar 或 RSSBud 快速发现和订阅。
Fork 然后将你的项目git clone到本地。
给你的项目增加上游:
git remote add upstream https://github.com/DIYgod/RSSHub
若以前已贡献过则需要从上游获取最新内容并强制更新:
git fetch upstream
git reset --hard upstream/master
git rebase upstream/master
git push -f origin master
推荐用 Node Version Manager 灵活切换 npm 版本。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
重启终端然后安装 npm 的稳定版:
nvm install stable
国内环境则推荐改为淘宝源(可选):
npm config set registry https://registry.npm.taobao.org
通过npm config get registry可检查是否更改成功。
进入项目根目录。
npm install
npm run dev
然后浏览器打开http://localhost:1200。dev模式下每次保存项目就会自动重启应用修改,方便实时调试。
这里以网易号(通用)为例解释如何添加新规则。
网易对大部分网易号是提供了 api 调取文章列表的,但有些网易号搜索页面搜不到的小众网易号(文章页面不含data-wemediaid)无法用 api 获取网页列表。
比如这个后厂村体工队。
添加脚本路由
打开/lib/router.js,增加路由。
router.get('/netease/dy2/:id', require('./routes/netease/dy2'));
由前面网易号的主页可见,其链接最后 html 的文件名可用于区分网易号,故作为参数id传入脚本。若是可选参数则是:param?这样的格式。
编写脚本
在 /lib/routes/中的路由对应路径下创建新的 js 脚本。由前面路由可见新建dy2.js。
import 所需模块
const got = require('@/utils/got');
const cheerio = require('cheerio');
const iconv = require('iconv-lite');
这里got用来获取 html 信息,cheerio处理获取的数据。由于某些网易页面并不是用通用的utf8编码,故还需要iconv-lite进行格式转换。
获取主页数据并生成文章列表
优先用 api 方式获取,但由前所述此法不可行。故直接抓取主页信息。另外还有一种方法是使用puppeteer渲染页面,这里不涉及。
const id = ctx.params.id;
const url = `https://www.163.com/dy/media/${id}.html`;
const response = await got.get(url, { responseType: 'buffer' });
const data = iconv.decode(response.data, 'gbk');
const $ = cheerio.load(data, { decodeEntities: false });
const list = $('.media_articles ul li')
.slice(0, 5)
.map((_, item) => {
item = $(item);
const a = item.find('h2.media_article_title a');
let pubDate = item.find('.media_article_date').text();
pubDate = new Date(pubDate).toUTCString();
return {
title: a.text(),
link: a.attr('href'),
pubDate: pubDate,
};
})
.get();
具体如何用浏览器选择可见这节图文教程。
遍历文章列表并抓取全文
const items = await Promise.all(
list.map(async (item) => {
let content;
if (item.link.startsWith('https://www.163.com')) {
const itemData = await ctx.cache.tryGet(item.link, async () =>
iconv.decode(
(
await got.get(item.link, {
responseType: 'buffer',
})
).data,
'gbk'
)
);
content = cheerio.load(itemData, { decodeEntities: false });
} else {
const itemData = await ctx.cache.tryGet(
item.link,
async () =>
(
await got.get(item.link, {
responseType: 'buffer',
})
).data
);
content = cheerio.load(itemData, { decodeEntities: false });
}
const eDescription = content('.post_body').html();
const single = {
title: item.title,
link: item.link,
description: eDescription,
pubDate: item.pubDate,
};
return Promise.resolve(single);
})
);
注:网易原来有部分网址是 gbk 编码的,现在全部改成 utf-8 了,处理更方便。更新代码见此处。
let link;
ctx.state.data = {
title: $('.media_info h1').text(),
link,
description: '',
item: items,
};
添加脚本文档
更新/docs/目录内对应的文档,可以执行npm run docs:dev查看文档效果。
这里网易号属于新媒体,故修改/docs/new-media.md。
## 网易号(通用)
<Route author="mjysci" example="/netease/dy2/T1555591616739" path="/netease/dy2/:id" :paramsDesc="['id,该网易号主页网址最后一项html的文件名']" anticrawler="1"/>
优先使用方法一,若是网易号搜索页面搜不到的小众网易号(文章页面不含`data-wemediaid`)则可使用此法。
触发反爬会只抓取到标题,建议自建。
格式是markdown。其中:paramsDesc是通过数组解释路由中每个参数的作用和获取方式,其他项不言自明,参考这个例子填写即可。
第三方 RSSHub,对于反爬严格的网站还是推荐自建服务。