---
sidebar: auto
---
# 参与我们
如果有任何想法或需求,可以在 [issue](https://github.com/DIYgod/RSSHub/issues) 中告诉我们,同时我们欢迎各种 pull requests
## 参与讨论
1. [Telegram 群](https://t.me/rsshub)
2. [GitHub Issues](https://github.com/DIYgod/RSSHub/issues)
## 提交新的 RSSHub 规则
开始编写 RSS 源前请确认源站没有提供 RSS,部分网页会在 HTML 头部包含 type 为 `application/atom+xml` 或 `application/rss+xml` 的 link 元素来指明 RSS 链接
### 调试
首先 `yarn` 或者 `npm install` 安装依赖,然后执行 `npm run dev`,打开 `http://localhost:1200` 就可以看到效果,修改文件也会自动刷新
### 添加脚本路由
在 [/lib/router.js](https://github.com/DIYgod/RSSHub/blob/master/lib/router.js) 里添加路由
#### 举例
1. [bilibili/bangumi](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/bilibili/bangumi.js)
| 名称 | 说明 |
| -------------------------- | ---------------------------------------------------------------------------------- |
| 路由 | `/bilibili/bangumi/:seasonid` |
| 数据来源 | bilibili |
| 路由名称 | bangumi |
| 参数 1 | :seasonid 必选 |
| 参数 2 | 无 |
| 参数 3 | 无 |
| 脚本路径 | `./routes/bilibili/bangumi` |
| lib/router.js 中的完整代码 | `router.get('/bilibili/bangumi/:seasonid', require('./routes/bilibili/bangumi'));` |
2. [github/issue](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/github/issue.js)
| 名称 | 说明 |
| -------------------------- | ---------------------------------------------------------------------------- |
| 路由 | `/github/issue/:user/:repo` |
| 数据来源 | github |
| 路由名称 | issue |
| 参数 1 | :user 必选 |
| 参数 2 | :repo 必选 |
| 参数 3 | 无 |
| 脚本路径 | `./routes/github/issue` |
| lib/router.js 中的完整代码 | `router.get('/github/issue/:user/:repo', require('./routes/github/issue'));` |
3. [embassy](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/embassy/index.js)
| 名称 | 说明 |
| -------------------------- | ---------------------------------------------------------------------------- |
| 路由 | `/embassy/:country/:city?` |
| 数据来源 | embassy |
| 路由名称 | 无 |
| 参数 1 | :country 必选 |
| 参数 2 | ?city 可选 |
| 参数 3 | 无 |
| 脚本路径 | `./routes/embassy/index` |
| lib/router.js 中的完整代码 | `router.get('/embassy/:country/:city?', require('./routes/embassy/index'));` |
---
### 编写脚本
在 [/lib/routes/](https://github.com/DIYgod/RSSHub/tree/master/lib/routes) 中的路由对应路径下创建新的 js 脚本:
#### 获取源数据
- 获取源数据的主要手段为使用 [got](https://github.com/sindresorhus/got) 发起 HTTP 请求(请求接口或请求网页)获取数据
- 个别情况需要使用 [puppeteer](https://github.com/GoogleChrome/puppeteer) 模拟浏览器渲染目标页面并获取数据
- 返回的数据一般为 JSON 或 HTML 格式
- 对于 HTML 格式的数据,使用 [cheerio](https://github.com/cheeriojs/cheerio) 进行处理
- 以下三种获取数据方法按 **「推荐优先级」** 排列:
1. **使用 got 从接口获取数据**
样例:[/lib/routes/bilibili/coin.js](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/bilibili/coin.js)。
使用 got 通过数据源提供的 API 接口获取数据:
```js
// 发起 HTTP GET 请求
const response = await got({
method: 'get',
url: `https://api.bilibili.com/x/space/coin/video?vmid=${uid}&jsonp=jsonp`,
headers: {
Referer: `https://space.bilibili.com/${uid}/`,
},
});
const data = response.data.data; // response.data 为 HTTP GET 请求返回的数据对象
// 这个对象中包含了数组名为 data,所以 response.data.data 则为需要的数据
```
返回的数据样例之一(response.data.data[0]):
```json
{
"aid": 33614333,
"videos": 2,
"tid": 20,
"tname": "宅舞",
"copyright": 1,
"pic": "http://i0.hdslb.com/bfs/archive/5649d7fe6ff7f7b431300fc1a0db80d3f174cacd.jpg",
"title": "【赤九玖】响喜乱舞【和我一起狂舞吧,团长大人(✧◡✧)】",
"pubdate": 1539259203,
"ctime": 1539249536,
"desc": "编舞出处:av31984673\n真心好喜欢这个舞和这首歌,居然恰巧被邀请跳了,感谢《苍之纪元》官方的邀请。这次cos的是游戏的新角色缪斯。然而时间有限很多地方还有很多不足。也没跳够,以后私下还会继续练习,希望能学到更多动作,也能为了有机会把它跳的更好。 \n摄影:绯山圣瞳九命猫 \n后期:炉火"
// 省略部分数据
}
```
对数据进行进一步处理,生成符合 RSS 规范的对象,把获取的标题、链接、描述、发布时间等数据赋值给 ctx.state.data, [生成 RSS 源](#生成-rss-源):
```js
ctx.state.data = {
// 源标题
title: `${name} 的 bilibili 投币视频`,
// 源链接
link: `https://space.bilibili.com/${uid}`,
// 源说明
description: `${name} 的 bilibili 投币视频`,
//遍历此前获取的数据
item: data.map((item) => ({
// 文章标题
title: item.title,
// 文章正文
description: `${item.desc}`,
// 文章发布时间
pubDate: new Date(item.time * 1000).toUTCString(),
// 文章链接
link: `https://www.bilibili.com/video/av${item.aid}`,
})),
};
// 至此本路由结束
```
2. **使用 got 从 HTML 获取数据**
有时候数据是写在 HTML 里的,**没有接口供我们调用**,样例: [/lib/routes/douban/explore.js](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/douban/explore.js)。
使用 got 请求 HTML 数据:
```js
// 发起 HTTP GET 请求
const response = await got({
method: 'get',
url: 'https://www.douban.com/explore',
});
const data = response.data; // response.data 为 HTTP GET 请求返回的 HTML,也就是简书首页的所有 HTML
```
使用 cheerio 解析返回的 HTML:
```js
const $ = cheerio.load(data); // 使用 cheerio 加载返回的 HTML
const list = $('div[data-item_id]');
// 使用 cheerio 选择器,选择 class="list-item" 的所有元素,返回 cheerio node 对象数组
// 注:每一个 cheerio node 对应一个 HTML DOM
// 注:cheerio 选择器与 jquery 选择器几乎相同
// 参考 cheerio 文档:https://cheerio.js.org/
```
使用 map 遍历数组,解析出每一个 item 的结果
```js
ctx.state.data = {
title: '豆瓣-浏览发现',
link: 'https://www.douban.com/explore',
item:
list &&
list
.map((index, item) => {
item = $(item);
itemPicUrl = `${item.find('a.cover').attr('style')}`.replace('background-image:url(', '').replace(')', '');
return {
title: item
.find('.title a')
.first()
.text(),
description: `作者:${item
.find('.usr-pic a')
.last()
.text()}
描述:${item.find('.content p').text()}`,
link: item.find('.title a').attr('href'),
};
})
.get(),
};
// 至此本路由结束
```
3. **使用 puppeteer 渲染页面获取数据**
::: tip 提示
由于此方法性能较差且消耗较多资源,使用前请确保以上两种方法无法获取数据,不然将导致您的 pull requests 被拒绝!
:::
部分网站**没有接口供调用,且页面有加密**
样例:[/lib/routes/sspai/series.js](https://github.com/DIYgod/RSSHub/blob/master/lib/routes/sspai/series.js)
```js
// 使用 RSSHub 提供的 puppeteer 工具类,初始化 Chrome 进程
const browser = await require('@/utils/puppeteer')();
// 创建一个新的浏览器页面
const page = await browser.newPage();
// 访问指定的链接
const link = 'https://sspai.com/series';
await page.goto(link);
// 渲染目标网页
const html = await page.evaluate(
() =>
// 选取渲染后的 HTML
document.querySelector('div.new-series-wrapper').innerHTML
);
// 关闭浏览器进程
browser.close();
```
使用 cheerio 解析返回的 HTML:
```js
const $ = cheerio.load(html); // 使用 cheerio 加载返回的 HTML
const list = $('div.item'); // 使用 cheerio 选择器,选择所有