From a4e2eda25aa5d34afe7b4bda7ca6f798da97b155 Mon Sep 17 00:00:00 2001
From: Ethan Shen <42264778+nczitzk@users.noreply.github.com>
Date: Wed, 21 Jun 2023 08:04:50 +0800
Subject: [PATCH] =?UTF-8?q?feat(route):=20add=2036kr=E8=B5=84=E8=AE=AF?=
=?UTF-8?q?=E7=83=AD=E6=A6=9C=20(#12681)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat(route): add 36kr资讯热榜
* fix docs
* update lib/v2/36kr/utils.js
---------
---
docs/new-media.md | 10 +++++++
lib/v2/36kr/hot-list.js | 59 +++++++++++++++++++++++++++++++++++++++
lib/v2/36kr/index.js | 33 ++--------------------
lib/v2/36kr/maintainer.js | 1 +
lib/v2/36kr/radar.js | 6 ++++
lib/v2/36kr/router.js | 1 +
lib/v2/36kr/utils.js | 36 ++++++++++++++++++++++++
7 files changed, 116 insertions(+), 30 deletions(-)
create mode 100644 lib/v2/36kr/hot-list.js
create mode 100644 lib/v2/36kr/utils.js
diff --git a/docs/new-media.md b/docs/new-media.md
index aac99901f..427a9634d 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -68,6 +68,16 @@ pageClass: routes
+### 资讯热榜
+
+
+
+| 24小时热榜 | 资讯人气榜 | 资讯综合榜 | 资讯收藏榜 |
+| ---------- | ---------- | ---------- | ---------- |
+| 24 | renqi | zonghe | shoucang |
+
+
+
## 52hrtt 华人头条
### 新闻
diff --git a/lib/v2/36kr/hot-list.js b/lib/v2/36kr/hot-list.js
new file mode 100644
index 000000000..52e8d95cc
--- /dev/null
+++ b/lib/v2/36kr/hot-list.js
@@ -0,0 +1,59 @@
+const got = require('@/utils/got');
+const { parseDate } = require('@/utils/parse-date');
+
+const { rootUrl, ProcessItem } = require('./utils');
+
+const categories = {
+ 24: {
+ title: '24小时热榜',
+ key: 'homeData.data.hotlist.data',
+ },
+ renqi: {
+ title: '资讯人气榜',
+ key: 'hotListData.topList',
+ },
+ zonghe: {
+ title: '资讯综合榜',
+ key: 'hotListData.hotList',
+ },
+ shoucang: {
+ title: '资讯综合榜',
+ key: 'hotListData.collectList',
+ },
+};
+
+module.exports = async (ctx) => {
+ const category = ctx.params.category ?? '24';
+
+ const currentUrl = category === '24' ? rootUrl : `${rootUrl}/hot-list/catalog`;
+
+ const response = await got({
+ method: 'get',
+ url: currentUrl,
+ });
+
+ const getProperty = (object, key) => key.split('.').reduce((o, k) => o && o[k], object);
+ const data = getProperty(JSON.parse(response.data.match(/window.initialState=({.*})/)[1]), categories[category].key);
+
+ let items = data
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 10)
+ .filter((item) => item.itemType !== 0)
+ .map((item) => {
+ item = item.templateMaterial ?? item;
+ return {
+ title: item.widgetTitle.replace(/<\/?em>/g, ''),
+ author: item.authorName,
+ pubDate: parseDate(item.publishTime),
+ link: `${rootUrl}/p/${item.itemId}`,
+ description: item.summary,
+ };
+ });
+
+ items = await Promise.all(items.map((item) => ProcessItem(item, ctx.cache.tryGet)));
+
+ ctx.state.data = {
+ title: `36氪 - ${categories[category].title}`,
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/v2/36kr/index.js b/lib/v2/36kr/index.js
index 04dc4cb39..6f2f34ec5 100644
--- a/lib/v2/36kr/index.js
+++ b/lib/v2/36kr/index.js
@@ -1,7 +1,8 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
-const CryptoJS = require('crypto-js');
+
+const { rootUrl, ProcessItem } = require('./utils');
const shortcuts = {
'/information': '/information/web_news',
@@ -15,7 +16,6 @@ const shortcuts = {
module.exports = async (ctx) => {
const path = ctx.path.replace(/^\/news(?!flashes)/, '/information').replace(/\/search\/article/, '/search/articles');
- const rootUrl = 'https://www.36kr.com';
const currentUrl = `${rootUrl}${shortcuts.hasOwnProperty(path) ? shortcuts[path] : path}`;
const response = await got({
@@ -42,34 +42,7 @@ module.exports = async (ctx) => {
});
if (!/^\/(search|newsflashes)/.test(path)) {
- items = await Promise.all(
- items.map((item) =>
- ctx.cache.tryGet(item.link, async () => {
- const detailResponse = await got({
- method: 'get',
- url: item.link,
- });
-
- const cipherTextList = detailResponse.data.match(/{"state":"(.*)","isEncrypt":true}/) ?? [];
- if (cipherTextList.length !== 0) {
- const key = CryptoJS.enc.Utf8.parse('efabccee-b754-4c');
- const content = JSON.parse(
- CryptoJS.AES.decrypt(cipherTextList[1], key, {
- mode: CryptoJS.mode.ECB,
- padding: CryptoJS.pad.Pkcs7,
- })
- .toString(CryptoJS.enc.Utf8)
- .toString()
- ).articleDetail.articleDetailData.data;
- item.description = content.widgetContent;
- } else {
- const $ = cheerio.load(detailResponse.body);
- item.description = $('div.articleDetailContent').html();
- }
- return item;
- })
- )
- );
+ items = await Promise.all(items.map((item) => ProcessItem(item, ctx.cache.tryGet)));
}
ctx.state.data = {
diff --git a/lib/v2/36kr/maintainer.js b/lib/v2/36kr/maintainer.js
index d72d4d414..aad6ba56d 100644
--- a/lib/v2/36kr/maintainer.js
+++ b/lib/v2/36kr/maintainer.js
@@ -1,4 +1,5 @@
module.exports = {
+ '/hot-list/:category?': ['nczitzk'],
'/information/:category?': ['nczitzk'],
'/motif/:id': ['nczitzk'],
'/newsflashes': ['hillerliao', 'nczitzk'],
diff --git a/lib/v2/36kr/radar.js b/lib/v2/36kr/radar.js
index 420da8b60..d7ab9315c 100644
--- a/lib/v2/36kr/radar.js
+++ b/lib/v2/36kr/radar.js
@@ -44,6 +44,12 @@ module.exports = {
source: ['/search/newsflashes/:keyword', '/'],
target: '/36kr/search/newsflashes/:keyword',
},
+ {
+ title: '资讯热榜',
+ docs: 'https://docs.rsshub.app/new-media.html#_36kr-zi-xun-re-bang',
+ source: ['/hot-list/:category', '/'],
+ target: '/36kr/hot-list/:category',
+ },
],
},
};
diff --git a/lib/v2/36kr/router.js b/lib/v2/36kr/router.js
index 2aa2b0a19..aaddd322f 100644
--- a/lib/v2/36kr/router.js
+++ b/lib/v2/36kr/router.js
@@ -1,3 +1,4 @@
module.exports = (router) => {
+ router.get('/hot-list/:category?', require('./hot-list'));
router.get(/([\w-/]+)?/, require('./index'));
};
diff --git a/lib/v2/36kr/utils.js b/lib/v2/36kr/utils.js
new file mode 100644
index 000000000..a2be6ea1b
--- /dev/null
+++ b/lib/v2/36kr/utils.js
@@ -0,0 +1,36 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const CryptoJS = require('crypto-js');
+
+const rootUrl = 'https://www.36kr.com';
+
+module.exports = {
+ rootUrl,
+ ProcessItem: (item, tryGet) =>
+ tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const cipherTextList = detailResponse.data.match(/{"state":"(.*)","isEncrypt":true}/) ?? [];
+
+ if (cipherTextList.length !== 0) {
+ const key = CryptoJS.enc.Utf8.parse('efabccee-b754-4c');
+ const content = JSON.parse(
+ CryptoJS.AES.decrypt(cipherTextList[1], key, {
+ mode: CryptoJS.mode.ECB,
+ padding: CryptoJS.pad.Pkcs7,
+ })
+ .toString(CryptoJS.enc.Utf8)
+ .toString()
+ ).articleDetail.articleDetailData.data;
+ item.description = content.widgetContent;
+ } else {
+ const $ = cheerio.load(detailResponse.body);
+ item.description = $('div.articleDetailContent').html();
+ }
+
+ return item;
+ }),
+};