Skip to content

Commit 095aa9e

Browse files
authored
fix(route): QuestMobile行业研究报告 (#14020)
* fix(route): QuestMobile行业研究报告 * Update website/docs/routes/new-media.mdx ---------
1 parent 9e0248c commit 095aa9e

File tree

8 files changed

+277
-188
lines changed

8 files changed

+277
-188
lines changed

lib/router.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2665,7 +2665,7 @@ router.get('/netflix/newsroom/:category?/:region?', lazyloadRouteHandler('./rout
26652665
router.get('/sbs/chinese/:category?/:id?/:dialect?/:language?', lazyloadRouteHandler('./routes/sbs/chinese'));
26662666

26672667
// QuestMobile
2668-
router.get('/questmobile/report/:category?/:label?', lazyloadRouteHandler('./routes/questmobile/report'));
2668+
// router.get('/questmobile/report/:category?/:label?', lazyloadRouteHandler('./routes/questmobile/report'));
26692669

26702670
// Fashion Network
26712671
router.get('/fashionnetwork/news/:sectors?/:categories?/:language?', lazyloadRouteHandler('./routes/fashionnetwork/news.js'));

lib/routes/questmobile/report.js

Lines changed: 0 additions & 121 deletions
This file was deleted.

lib/v2/questmobile/maintainer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
'/report/:industry?/:label?': ['nczitzk'],
3+
};

lib/v2/questmobile/radar.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
'questmobile.com.cn': {
3+
_name: 'QuestMobile',
4+
'.': [
5+
{
6+
title: '行业研究报告',
7+
docs: 'https://docs.rsshub.app/routes/new-media#questmobile-hang-ye-yan-jiu-bao-gao',
8+
source: ['/research/reports/:industry/:label'],
9+
target: (params) => {
10+
const industry = params.industry;
11+
const label = params.label;
12+
13+
return `/questmobile/report/${industry}/${label}`;
14+
},
15+
},
16+
],
17+
},
18+
};

lib/v2/questmobile/report.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
const got = require('@/utils/got');
2+
const cheerio = require('cheerio');
3+
const { parseDate } = require('@/utils/parse-date');
4+
const { art } = require('@/utils/render');
5+
const path = require('path');
6+
7+
/**
8+
* Parses a tree array and returns an array of objects containing the key-value pairs.
9+
* @param {Array} tree - The tree to parse.
10+
* @param {Array} result - The result array to store the parsed key-value pairs. Default is an empty array.
11+
*
12+
* @returns {Array} - An array of objects containing the key-value pairs.
13+
*/
14+
const parseTree = (tree, result = []) => {
15+
tree.forEach((obj) => {
16+
const { key, value, children } = obj;
17+
result.push({ key, value });
18+
19+
if (children && children.length > 0) {
20+
parseTree(children, result);
21+
}
22+
});
23+
24+
return result;
25+
};
26+
27+
module.exports = async (ctx) => {
28+
const { industry, label } = ctx.params;
29+
const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 50;
30+
31+
const rootUrl = 'https://www.questmobile.com.cn';
32+
const apiUrl = new URL('api/v2/report/article-list', rootUrl).href;
33+
const apiTreeUrl = new URL('api/v2/report/industry-label-tree', rootUrl).href;
34+
35+
const {
36+
data: {
37+
data: { industryTree, labelTree },
38+
},
39+
} = await got(apiTreeUrl);
40+
41+
const industries = parseTree(industryTree);
42+
const labels = parseTree(labelTree);
43+
44+
const industryObj = industry ? industries.find((i) => i.key === industry || i.value === industry) : undefined;
45+
const labelObj = label ? labels.find((i) => i.key === label || i.value === label) : industryObj ? undefined : labels.find((i) => i.key === industry || i.value === industry);
46+
47+
const industryId = industryObj?.key ?? -1;
48+
const labelId = labelObj?.key ?? -1;
49+
50+
const currentUrl = new URL(`research/reports/${industryObj?.key ?? -1}/${labelObj?.key ?? -1}`, rootUrl).href;
51+
52+
const { data: response } = await got(apiUrl, {
53+
searchParams: {
54+
version: 0,
55+
pageSize: limit,
56+
pageNo: 1,
57+
industryId,
58+
labelId,
59+
},
60+
});
61+
62+
let items = response.data.slice(0, limit).map((item) => ({
63+
title: item.title,
64+
link: new URL(`research/report/${item.id}`, rootUrl).href,
65+
description: art(path.join(__dirname, 'templates/description.art'), {
66+
image: {
67+
src: item.coverImgUrl,
68+
alt: item.title,
69+
},
70+
introduction: item.introduction,
71+
description: item.content,
72+
}),
73+
category: [...(item.industryList ?? []), ...(item.labelList ?? [])],
74+
guid: `questmobile-report#${item.id}`,
75+
pubDate: parseDate(item.publishTime),
76+
}));
77+
78+
items = await Promise.all(
79+
items.map((item) =>
80+
ctx.cache.tryGet(item.link, async () => {
81+
const { data: detailResponse } = await got(item.link);
82+
83+
const content = cheerio.load(detailResponse);
84+
85+
content('div.text div.daoyu').remove();
86+
87+
item.title = content('div.title h1').text();
88+
item.description += art(path.join(__dirname, 'templates/description.art'), {
89+
description: content('div.text').html(),
90+
});
91+
item.author = content('div.source')
92+
.text()
93+
.replace(/^.*?/, '');
94+
item.category = content('div.hy, div.keyword')
95+
.find('span')
96+
.toArray()
97+
.map((c) => content(c).text());
98+
item.pubDate = parseDate(content('div.data span').prop('datetime'));
99+
100+
return item;
101+
})
102+
)
103+
);
104+
105+
const { data: currentResponse } = await got(currentUrl);
106+
107+
const $ = cheerio.load(currentResponse);
108+
109+
const author = $('meta[property="og:title"]').prop('content').split(/-/)[0];
110+
const categories = [industryObj?.value, labelObj?.value].filter((c) => c);
111+
const image = $(`img[alt="${author}"]`).prop('src');
112+
const icon = $('link[rel="shortcut icon"]').prop('href');
113+
114+
ctx.state.data = {
115+
item: items,
116+
title: `${author}${categories.length === 0 ? '' : ` - ${categories.join(' - ')}`}`,
117+
link: currentUrl,
118+
description: $('meta[property="og:description"]').prop('content'),
119+
language: 'zh',
120+
image,
121+
icon,
122+
logo: icon,
123+
subtitle: $('meta[name="keywords"]').prop('content'),
124+
author,
125+
allowEmpty: true,
126+
};
127+
};

lib/v2/questmobile/router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = (router) => {
2+
router.get('/report/:industry?/:label?', require('./report'));
3+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{{ if image?.src }}
2+
<figure>
3+
<img
4+
{{ if image.alt }}
5+
alt="{{ image.alt }}"
6+
{{ /if }}
7+
src="{{ image.src }}">
8+
</figure>
9+
{{ /if }}
10+
11+
{{ if introduction }}
12+
<blockquote>{{ introduction }}</blockquote>
13+
{{ /if }}
14+
15+
{{ if description }}
16+
{{@ description }}
17+
{{ /if }}

0 commit comments

Comments
 (0)