From 5b4910e6e4fa47e595e16f60cfaf21f01573bb97 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 13 Apr 2018 16:23:49 +0800 Subject: [PATCH] jianshu --- docs/README.md | 42 +++++++++++++++ index.js | 7 +++ package.json | 1 + routes/jianshu/collection.js | 44 +++++++++++++++ routes/jianshu/home.js | 42 +++++++++++++++ routes/jianshu/monthly.js | 42 +++++++++++++++ routes/jianshu/user.js | 44 +++++++++++++++ routes/jianshu/weekly.js | 42 +++++++++++++++ yarn.lock | 100 +++++++++++++++++++++++++++++++++-- 9 files changed, 361 insertions(+), 3 deletions(-) create mode 100644 routes/jianshu/collection.js create mode 100644 routes/jianshu/home.js create mode 100644 routes/jianshu/monthly.js create mode 100644 routes/jianshu/user.js create mode 100644 routes/jianshu/weekly.js 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: