diff --git a/docs/README.md b/docs/README.md
index 180b1c7ac..74576780b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -186,6 +186,48 @@ s
| -------- | ------- | ---- | ------- | ------ | ------- | ------- | ------- | ---- |
| frontend | android | ios | backend | design | product | freebie | article | ai |
+### 简书
+
+#### 首页
+
+举例: https://rss.prprpr.me/jianshu/home
+
+路由: `/jianshu/home`
+
+参数: 无
+
+#### 7 日热门
+
+举例: https://rss.prprpr.me/jianshu/weekly
+
+路由: `/jianshu/weekly`
+
+参数: 无
+
+#### 30 日热门
+
+举例: https://rss.prprpr.me/jianshu/monthly
+
+路由: `/jianshu/monthly`
+
+参数: 无
+
+#### 专题
+
+举例: https://rss.prprpr.me/jianshu/collection/xYuZYD
+
+路由: `/jianshu/collection/:id`
+
+参数: id,专题 id,可在专题页 URL 中找到
+
+#### 作者
+
+举例: https://rss.prprpr.me/jianshu/user/yZq3ZV
+
+路由: `/jianshu/user/:id`
+
+参数: id,作者 id,可在作者主页 URL 中找到
+
### 自如
#### 房源
diff --git a/index.js b/index.js
index 86d83d443..7dac7ca40 100644
--- a/index.js
+++ b/index.js
@@ -30,4 +30,11 @@ app.get('/ziroom/room/:city/:iswhole/:room/:keyword', require('./routes/ziroom/r
// 快递
app.get('/express/:company/:number', require('./routes/express/express'));
+// 简书
+app.get('/jianshu/home', require('./routes/jianshu/home'));
+app.get('/jianshu/trending/weekly', require('./routes/jianshu/weekly'));
+app.get('/jianshu/trending/monthly', require('./routes/jianshu/monthly'));
+app.get('/jianshu/collection/:id', require('./routes/jianshu/collection'));
+app.get('/jianshu/user/:id', require('./routes/jianshu/user'));
+
app.listen(1200);
\ No newline at end of file
diff --git a/package.json b/package.json
index e28b670e6..844321fba 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"devDependencies": {},
"dependencies": {
"art-template": "4.12.2",
+ "cheerio": "1.0.0-rc.2",
"eslint": "4.19.1",
"express": "^4.16.3",
"redis": "2.8.0",
diff --git a/routes/jianshu/collection.js b/routes/jianshu/collection.js
new file mode 100644
index 000000000..c76f5e696
--- /dev/null
+++ b/routes/jianshu/collection.js
@@ -0,0 +1,44 @@
+const request = require('request');
+const art = require('art-template');
+const path = require('path');
+const cheerio = require('cheerio');
+const base = require('../base');
+const mix = require('../../utils/mix');
+
+module.exports = (req, res) => {
+ const id = req.params.id;
+
+ base({
+ req: req,
+ res: res,
+ getHTML: (callback) => {
+ request.get({
+ url: `https://www.jianshu.com/c/${id}`,
+ headers: {
+ 'User-Agent': mix.ua,
+ 'Referer': `https://www.jianshu.com/c/${id}`
+ }
+ }, (err, httpResponse, body) => {
+ const $ = cheerio.load(body);
+ const list = $('.note-list li');
+
+ const html = art(path.resolve(__dirname, '../../views/rss.art'), {
+ title: $('title').text(),
+ link: `https://www.jianshu.com/c/${id}`,
+ description: $('meta[name="description"]').attr('content') || $('title').text(),
+ lastBuildDate: new Date().toUTCString(),
+ item: list && list.map((index, item) => {
+ item = $(item);
+ return {
+ title: item.find('.title').text(),
+ description: `作者:${item.find('.nickname').text()}
描述:${item.find('.abstract').text()}
`,
+ pubDate: new Date(item.find('.time').data('shared-at')).toUTCString(),
+ link: `https://www.jianshu.com${item.find('.title').attr('href')}`
+ };
+ }).get(),
+ });
+ callback(html);
+ });
+ }
+ });
+};
\ No newline at end of file
diff --git a/routes/jianshu/home.js b/routes/jianshu/home.js
new file mode 100644
index 000000000..550989e11
--- /dev/null
+++ b/routes/jianshu/home.js
@@ -0,0 +1,42 @@
+const request = require('request');
+const art = require('art-template');
+const path = require('path');
+const cheerio = require('cheerio');
+const base = require('../base');
+const mix = require('../../utils/mix');
+
+module.exports = (req, res) => {
+ base({
+ req: req,
+ res: res,
+ getHTML: (callback) => {
+ request.get({
+ url: 'https://www.jianshu.com',
+ headers: {
+ 'User-Agent': mix.ua,
+ 'Referer': 'https://www.jianshu.com'
+ }
+ }, (err, httpResponse, body) => {
+ const $ = cheerio.load(body);
+ const list = $('.note-list li');
+
+ const html = art(path.resolve(__dirname, '../../views/rss.art'), {
+ title: '简书首页',
+ link: 'https://www.jianshu.com',
+ description: $('meta[name="description"]').attr('content'),
+ lastBuildDate: new Date().toUTCString(),
+ item: list && list.map((index, item) => {
+ item = $(item);
+ return {
+ title: item.find('.title').text(),
+ description: `作者:${item.find('.nickname').text()}
描述:${item.find('.abstract').text()}
`,
+ pubDate: new Date(item.find('.time').data('shared-at')).toUTCString(),
+ link: `https://www.jianshu.com${item.find('.title').attr('href')}`
+ };
+ }).get(),
+ });
+ callback(html);
+ });
+ }
+ });
+};
\ No newline at end of file
diff --git a/routes/jianshu/monthly.js b/routes/jianshu/monthly.js
new file mode 100644
index 000000000..f7e0abfa6
--- /dev/null
+++ b/routes/jianshu/monthly.js
@@ -0,0 +1,42 @@
+const request = require('request');
+const art = require('art-template');
+const path = require('path');
+const cheerio = require('cheerio');
+const base = require('../base');
+const mix = require('../../utils/mix');
+
+module.exports = (req, res) => {
+ base({
+ req: req,
+ res: res,
+ getHTML: (callback) => {
+ request.get({
+ url: 'https://www.jianshu.com/trending/monthly',
+ headers: {
+ 'User-Agent': mix.ua,
+ 'Referer': 'https://www.jianshu.com/trending/monthly'
+ }
+ }, (err, httpResponse, body) => {
+ const $ = cheerio.load(body);
+ const list = $('.note-list li');
+
+ const html = art(path.resolve(__dirname, '../../views/rss.art'), {
+ title: '简书 30 日热门',
+ link: 'https://www.jianshu.com/trending/monthly',
+ description: '简书 30 日热门',
+ lastBuildDate: new Date().toUTCString(),
+ item: list && list.map((index, item) => {
+ item = $(item);
+ return {
+ title: item.find('.title').text(),
+ description: `作者:${item.find('.nickname').text()}
描述:${item.find('.abstract').text()}
`,
+ pubDate: new Date(item.find('.time').data('shared-at')).toUTCString(),
+ link: `https://www.jianshu.com${item.find('.title').attr('href')}`
+ };
+ }).get(),
+ });
+ callback(html);
+ });
+ }
+ });
+};
\ No newline at end of file
diff --git a/routes/jianshu/user.js b/routes/jianshu/user.js
new file mode 100644
index 000000000..19ad730bf
--- /dev/null
+++ b/routes/jianshu/user.js
@@ -0,0 +1,44 @@
+const request = require('request');
+const art = require('art-template');
+const path = require('path');
+const cheerio = require('cheerio');
+const base = require('../base');
+const mix = require('../../utils/mix');
+
+module.exports = (req, res) => {
+ const id = req.params.id;
+
+ base({
+ req: req,
+ res: res,
+ getHTML: (callback) => {
+ request.get({
+ url: `https://www.jianshu.com/u/${id}`,
+ headers: {
+ 'User-Agent': mix.ua,
+ 'Referer': `https://www.jianshu.com/u/${id}`
+ }
+ }, (err, httpResponse, body) => {
+ const $ = cheerio.load(body);
+ const list = $('.note-list li');
+
+ const html = art(path.resolve(__dirname, '../../views/rss.art'), {
+ title: $('title').text(),
+ link: `https://www.jianshu.com/u/${id}`,
+ description: $('meta[name="description"]').attr('content') || $('title').text(),
+ lastBuildDate: new Date().toUTCString(),
+ item: list && list.map((index, item) => {
+ item = $(item);
+ return {
+ title: item.find('.title').text(),
+ description: `作者:${item.find('.nickname').text()}
描述:${item.find('.abstract').text()}
`,
+ pubDate: new Date(item.find('.time').data('shared-at')).toUTCString(),
+ link: `https://www.jianshu.com${item.find('.title').attr('href')}`
+ };
+ }).get(),
+ });
+ callback(html);
+ });
+ }
+ });
+};
\ No newline at end of file
diff --git a/routes/jianshu/weekly.js b/routes/jianshu/weekly.js
new file mode 100644
index 000000000..49bc1c87f
--- /dev/null
+++ b/routes/jianshu/weekly.js
@@ -0,0 +1,42 @@
+const request = require('request');
+const art = require('art-template');
+const path = require('path');
+const cheerio = require('cheerio');
+const base = require('../base');
+const mix = require('../../utils/mix');
+
+module.exports = (req, res) => {
+ base({
+ req: req,
+ res: res,
+ getHTML: (callback) => {
+ request.get({
+ url: 'https://www.jianshu.com/trending/weekly',
+ headers: {
+ 'User-Agent': mix.ua,
+ 'Referer': 'https://www.jianshu.com/trending/weekly'
+ }
+ }, (err, httpResponse, body) => {
+ const $ = cheerio.load(body);
+ const list = $('.note-list li');
+
+ const html = art(path.resolve(__dirname, '../../views/rss.art'), {
+ title: '简书 7 日热门',
+ link: 'https://www.jianshu.com/trending/weekly',
+ description: '简书 7 日热门',
+ lastBuildDate: new Date().toUTCString(),
+ item: list && list.map((index, item) => {
+ item = $(item);
+ return {
+ title: item.find('.title').text(),
+ description: `作者:${item.find('.nickname').text()}
描述:${item.find('.abstract').text()}
`,
+ pubDate: new Date(item.find('.time').data('shared-at')).toUTCString(),
+ link: `https://www.jianshu.com${item.find('.title').attr('href')}`
+ };
+ }).get(),
+ });
+ callback(html);
+ });
+ }
+ });
+};
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 247e290b2..d36657f11 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,10 @@
# yarn lockfile v1
+"@types/node@*":
+ version "9.6.4"
+ resolved "https://registry.npmjs.org/@types/node/-/node-9.6.4.tgz#0ef7b4cfc3499881c81e0ea1ce61a23f6f4f5b42"
+
accepts@~1.3.5:
version "1.3.5"
resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
@@ -164,6 +168,10 @@ body-parser@1.18.2:
raw-body "2.3.2"
type-is "~1.6.15"
+boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+
boom@4.x.x:
version "4.3.1"
resolved "http://registry.npm.taobao.org/boom/download/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31"
@@ -234,6 +242,17 @@ chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+cheerio@1.0.0-rc.2:
+ version "1.0.0-rc.2"
+ resolved "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
+ dependencies:
+ css-select "~1.2.0"
+ dom-serializer "~0.1.0"
+ entities "~1.1.1"
+ htmlparser2 "^3.9.1"
+ lodash "^4.15.0"
+ parse5 "^3.0.1"
+
circular-json@^0.3.1:
version "0.3.3"
resolved "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
@@ -357,6 +376,19 @@ cryptiles@3.x.x:
dependencies:
boom "5.x.x"
+css-select@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
+ dependencies:
+ boolbase "~1.0.0"
+ css-what "2.1"
+ domutils "1.5.1"
+ nth-check "~1.0.1"
+
+css-what@2.1:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
+
dashdash@^1.12.0:
version "1.14.1"
resolved "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -425,6 +457,41 @@ doctrine@^2.1.0:
dependencies:
esutils "^2.0.2"
+dom-serializer@0, dom-serializer@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ dependencies:
+ domelementtype "~1.1.1"
+ entities "~1.1.1"
+
+domelementtype@1, domelementtype@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+
+domelementtype@~1.1.1:
+ version "1.1.3"
+ resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+
+domhandler@^2.3.0:
+ version "2.4.1"
+ resolved "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"
+ dependencies:
+ domelementtype "1"
+
+domutils@1.5.1:
+ version "1.5.1"
+ resolved "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+domutils@^1.5.1:
+ version "1.7.0"
+ resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
double-ended-queue@^2.1.0-0:
version "2.1.0-0"
resolved "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
@@ -449,6 +516,10 @@ encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+entities@^1.1.1, entities@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+
env-variable@0.0.x:
version "0.0.4"
resolved "https://registry.npmjs.org/env-variable/-/env-variable-0.0.4.tgz#0d6280cf507d84242befe35a512b5ae4be77c54e"
@@ -780,6 +851,17 @@ html-minifier@^3.4.3:
relateurl "0.2.x"
uglify-js "3.3.x"
+htmlparser2@^3.9.1:
+ version "3.9.2"
+ resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ dependencies:
+ domelementtype "^1.3.0"
+ domhandler "^2.3.0"
+ domutils "^1.5.1"
+ entities "^1.1.1"
+ inherits "^2.0.1"
+ readable-stream "^2.0.2"
+
http-errors@1.6.2, http-errors@~1.6.2:
version "1.6.2"
resolved "http://registry.npm.taobao.org/http-errors/download/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
@@ -816,7 +898,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.3, inherits@^2.0.3, inherits@~2.0.3:
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
version "2.0.3"
resolved "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -954,7 +1036,7 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
-lodash@^4.14.0, lodash@^4.17.4, lodash@^4.3.0:
+lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.3.0:
version "4.17.5"
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
@@ -1060,6 +1142,12 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
+nth-check@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
+ dependencies:
+ boolbase "~1.0.0"
+
oauth-sign@~0.8.2:
version "0.8.2"
resolved "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
@@ -1111,6 +1199,12 @@ param-case@2.1.x:
dependencies:
no-case "^2.2.0"
+parse5@^3.0.1:
+ version "3.0.3"
+ resolved "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
+ dependencies:
+ "@types/node" "*"
+
parseurl@~1.3.2:
version "1.3.2"
resolved "http://registry.npm.taobao.org/parseurl/download/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
@@ -1193,7 +1287,7 @@ raw-body@2.3.2:
iconv-lite "0.4.19"
unpipe "1.0.0"
-readable-stream@^2.2.2:
+readable-stream@^2.0.2, readable-stream@^2.2.2:
version "2.3.6"
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
dependencies: