diff --git a/lib/router.js b/lib/router.js
index 6b5c978193..17bc344762 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -995,7 +995,7 @@ router.get('/dekudeals/:type', lazyloadRouteHandler('./routes/dekudeals'));
router.get('/metacritic/release/:platform/:type/:sort?', lazyloadRouteHandler('./routes/metacritic/release'));
// 快科技(原驱动之家)
-router.get('/kkj/news', lazyloadRouteHandler('./routes/kkj/news'));
+// router.get('/kkj/news', lazyloadRouteHandler('./routes/kkj/news'));
// sixthtone
router.get('/sixthtone/news', lazyloadRouteHandler('./routes/sixthtone/news'));
diff --git a/lib/routes/kkj/news.js b/lib/routes/kkj/news.js
deleted file mode 100644
index 37a8387667..0000000000
--- a/lib/routes/kkj/news.js
+++ /dev/null
@@ -1,52 +0,0 @@
-const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const parser = require('@/utils/rss-parser');
-
-module.exports = async (ctx) => {
- const feed = await parser.parseURL('http://rss.mydrivers.com/rss.aspx?Tid=1');
-
- const ProcessFeed = (data) => {
- const $ = cheerio.load(data);
-
- // 移除广告等内容
- $('.news_info .weixin ~ div').remove();
- $('.news_info .weixin').remove();
- $('.news_info script').remove();
-
- // 提取内容
- return $('.news_info').html();
- };
-
- const items = await Promise.all(
- feed.items.map(async (item) => {
- const cache = await ctx.cache.get(item.link);
- if (cache) {
- return Promise.resolve(JSON.parse(cache));
- }
-
- const response = await got({
- method: 'get',
- url: item.link,
- });
-
- const description = ProcessFeed(response.data);
-
- const single = {
- title: item.title,
- description,
- pubDate: item.pubDate,
- link: item.link,
- author: item.author,
- };
- ctx.cache.set(item.link, JSON.stringify(single));
- return Promise.resolve(single);
- })
- );
-
- ctx.state.data = {
- title: feed.title,
- link: feed.link,
- description: feed.description,
- item: items,
- };
-};
diff --git a/lib/v2/mydrivers/cid.js b/lib/v2/mydrivers/cid.js
new file mode 100644
index 0000000000..65f44a6499
--- /dev/null
+++ b/lib/v2/mydrivers/cid.js
@@ -0,0 +1,38 @@
+const { parseDate } = require('@/utils/parse-date');
+const parser = require('@/utils/rss-parser');
+
+const { rootUrl, rootRSSUrl, title, categories, getInfo, processItems } = require('./util');
+
+module.exports = async (ctx) => {
+ const { id } = ctx.params;
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 100;
+
+ const queryString = id ? `?cid=${id}` : '';
+ const currentUrl = new URL(id ? `newsclass.aspx${queryString}` : '', rootUrl).href;
+
+ const rssUrl = new URL(`rss.aspx${queryString}`, rootRSSUrl).href;
+
+ const feed = await parser.parseURL(rssUrl);
+
+ let items = feed.items.slice(0, limit).map((item) => ({
+ title: item.title,
+ link: item.link,
+ description: item.content,
+ author: item.creator,
+ category: item.categories,
+ guid: item.guid.match(/\/(\d+)\.htm/)[1],
+ pubDate: parseDate(item.isoDate),
+ }));
+
+ if (id) {
+ items = await processItems(items, ctx.cache.tryGet);
+ }
+
+ ctx.state.data = {
+ ...(await getInfo(currentUrl, ctx.cache.tryGet)),
+ ...{
+ item: items,
+ title: `${title} - ${feed.title.split(/_/).pop() || categories.zhibo}`,
+ },
+ };
+};
diff --git a/lib/v2/mydrivers/index.js b/lib/v2/mydrivers/index.js
index b7dca23d8a..02bf789954 100644
--- a/lib/v2/mydrivers/index.js
+++ b/lib/v2/mydrivers/index.js
@@ -2,109 +2,60 @@ const got = require('@/utils/got');
const cheerio = require('cheerio');
const timezone = require('@/utils/timezone');
const { parseDate } = require('@/utils/parse-date');
+const { art } = require('@/utils/render');
+const path = require('path');
-const titles = {
- '': { '': '最新' },
- new: { '': '最新' },
- hot: { '': '最热' },
- ac: {
- new: '最新',
- hot: '最热',
- },
- bcid: {
- 801: '电脑',
- 802: '手机',
- 803: '业界',
- 806: '游戏',
- 807: '汽车',
- 809: '影视',
- },
- tid: {
- 1000: '科学',
- 1001: '排行',
- 1002: '评测',
- 1003: '一图',
- },
- icid: {
- 67: '百度',
- 90: '微软',
- 121: '安卓',
- 136: '华为',
- 140: '魅族',
- 148: 'OPPO',
- 154: '三星',
- 194: 'Xbox',
- 270: '阿里',
- 288: 'VIVO',
- 385: '一加',
- 429: '奔驰',
- 461: '宝马',
- 481: '大众',
- 770: '比亚迪',
- 1193: '特斯拉',
- 6950: 'PS5',
- 7259: '小鹏',
- 7318: '蔚来',
- 9355: '小米',
- 12947: '理想',
- },
- cid: {
- 12: '显卡',
- 13: 'CPU',
- 38: '路由器',
- 201: '苹果',
- },
-};
+const { rootUrl, title, categories, convertToQueryString, getInfo, processItems } = require('./util');
module.exports = async (ctx) => {
- const type = ctx.params.type ?? '';
- const id = ctx.params.id ?? '';
+ let { category = 'new' } = ctx.params;
- const rootUrl = 'https://m.mydrivers.com';
- const currentUrl = `${rootUrl}/${type === '' || type === 'ac' ? 'm/newslist.ashx' : 'newsclass.aspx'}${type ? (id ? `?${type}=${id}` : `?ac=${type}`) : ''}`;
+ let newTitle = '';
- const response = await got({
- method: 'get',
- url: currentUrl,
- });
+ if (!/^(\w+\/\w+)$/.test(category)) {
+ newTitle = `${title} - ${categories.hasOwnProperty(category) ? categories[category] : categories[Object.keys(categories)[0]]}`;
+ category = `ac/${category}`;
+ }
- const $ = cheerio.load(response.data);
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 20;
- const list = $('.newst a')
- .map((_, item) => {
+ const queryString = convertToQueryString(category);
+ const currentUrl = new URL(`newsclass.aspx${queryString}`, rootUrl).href;
+
+ const apiUrl = new URL(`m/newslist.ashx${queryString}`, rootUrl).href;
+
+ const { data: response } = await got(apiUrl);
+
+ const $ = cheerio.load(response);
+
+ let items = $('li[data-id]')
+ .slice(0, limit)
+ .toArray()
+ .map((item) => {
item = $(item);
return {
- title: item.text(),
- link: `${rootUrl}${item.attr('href')}`,
+ title: item.find('div.news_title').text(),
+ link: new URL(item.find('div.news_title span.newst a').prop('href'), rootUrl).href,
+ description: art(path.join(__dirname, 'templates/description.art'), {
+ image: item.find('a.newsimg img').prop('src'),
+ }),
+ author: item.find('p.tname').text(),
+ guid: item.prop('data-id'),
+ pubDate: timezone(parseDate(item.find('p.ttime').text()), +8),
+ comments: item.find('a.tpinglun').text() ? parseInt(item.find('a.tpinglun').text(), 10) : 0,
};
- })
- .get();
+ });
- const items = await Promise.all(
- list.map((item) =>
- ctx.cache.tryGet(item.link, async () => {
- const detailResponse = await got({
- method: 'get',
- url: item.link,
- });
-
- const content = cheerio.load(detailResponse.data);
-
- content('.ab, .bb').remove();
-
- item.author = content('.writer').text();
- item.description = content('#content').html();
- item.pubDate = timezone(parseDate(content('.news_t1 ul li').eq(1).text().trim(), 'YYYY年MM月DD日 mm:ss'), +8);
-
- return item;
- })
- )
- );
+ items = await processItems(items, ctx.cache.tryGet);
ctx.state.data = {
- title: `${titles[type][id]} - 快科技`,
- link: currentUrl,
- item: items,
+ ...(await getInfo(currentUrl, ctx.cache.tryGet)),
+ ...Object.fromEntries(
+ Object.entries({
+ item: items,
+ title: newTitle,
+ }).filter(([value]) => value)
+ ),
};
};
diff --git a/lib/v2/mydrivers/maintainer.js b/lib/v2/mydrivers/maintainer.js
index 5930963c00..863b0c8d4a 100644
--- a/lib/v2/mydrivers/maintainer.js
+++ b/lib/v2/mydrivers/maintainer.js
@@ -1,3 +1,7 @@
module.exports = {
- '/:type?/:id?': ['nczitzk'],
+ '/hot': ['nczitzk'],
+ '/new': ['kt286', 'nczitzk'],
+ '/rank/:range?': ['nczitzk'],
+ '/zhibo': ['nczitzk'],
+ '/:category?': ['nczitzk'],
};
diff --git a/lib/v2/mydrivers/radar.js b/lib/v2/mydrivers/radar.js
index fba4d1a1b9..5cb79e7920 100644
--- a/lib/v2/mydrivers/radar.js
+++ b/lib/v2/mydrivers/radar.js
@@ -1,12 +1,213 @@
module.exports = {
'mydrivers.com': {
_name: '快科技',
- '.': [
+ m: [
{
- title: '新闻',
- docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-xin-wen',
+ title: '最新',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-zui-xin',
source: ['/'],
- target: '/mydrivers/:type?/:id?',
+ target: '/mydrivers/new',
+ },
+ {
+ title: '热门',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-re-men',
+ source: ['/'],
+ target: '/mydrivers/hot',
+ },
+ {
+ title: '发布会',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fa-bu-hui',
+ source: ['/'],
+ target: '/mydrivers/zhibo',
+ },
+ {
+ title: '排行',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-pai-hang',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/rank',
+ },
+ {
+ title: '分类',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: (params, url) => {
+ url = new URL(url);
+
+ const theParam = [...url.searchParams.entries()]
+ .filter(([key, value]) => key && value !== '')
+ .map(([key, value]) => `${key}/${value}`)
+ .pop();
+
+ return `/mydrivers/${theParam}`;
+ },
+ },
+ {
+ title: '板块 - 电脑',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/bcid/801',
+ },
+ {
+ title: '板块 - 手机',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/bcid/802',
+ },
+ {
+ title: '板块 - 汽车',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/bcid/807',
+ },
+ {
+ title: '板块 - 业界',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/bcid/803',
+ },
+ {
+ title: '板块 - 游戏',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/bcid/806',
+ },
+ {
+ title: '话题 - 科学',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/tid/1000',
+ },
+ {
+ title: '话题 - 排行',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/tid/1001',
+ },
+ {
+ title: '话题 - 评测',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/tid/1002',
+ },
+ {
+ title: '话题 - 一图',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/tid/1003',
+ },
+ {
+ title: '品牌 - 安卓',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/121',
+ },
+ {
+ title: '品牌 - 阿里',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/270',
+ },
+ {
+ title: '品牌 - 微软',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/90',
+ },
+ {
+ title: '品牌 - 百度',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/67',
+ },
+ {
+ title: '品牌 - PS5',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/6950',
+ },
+ {
+ title: '品牌 - Xbox',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/194',
+ },
+ {
+ title: '品牌 - 华为',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/136',
+ },
+ {
+ title: '品牌 - 小米',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/9355',
+ },
+ {
+ title: '品牌 - VIVO',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/288',
+ },
+ {
+ title: '品牌 - 三星',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/154',
+ },
+ {
+ title: '品牌 - 魅族',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/140',
+ },
+ {
+ title: '品牌 - 一加',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/385',
+ },
+ {
+ title: '品牌 - 比亚迪',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/770',
+ },
+ {
+ title: '品牌 - 小鹏',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/7259',
+ },
+ {
+ title: '品牌 - 蔚来',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/7318',
+ },
+ {
+ title: '品牌 - 理想',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/12947',
+ },
+ {
+ title: '品牌 - 奔驰',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/429',
+ },
+ {
+ title: '品牌 - 宝马',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/461',
+ },
+ {
+ title: '品牌 - 大众',
+ docs: 'https://docs.rsshub.app/routes/new-media#kuai-ke-ji-fen-lei',
+ source: ['/newsclass.aspx'],
+ target: '/mydrivers/icid/481',
},
],
},
diff --git a/lib/v2/mydrivers/rank.js b/lib/v2/mydrivers/rank.js
new file mode 100644
index 0000000000..5a917f8396
--- /dev/null
+++ b/lib/v2/mydrivers/rank.js
@@ -0,0 +1,40 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const { rootUrl, getInfo, processItems } = require('./util');
+
+module.exports = async (ctx) => {
+ const { range = '0' } = ctx.params;
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 10;
+
+ const currentUrl = new URL('newsclass.aspx?tid=1001', rootUrl).href;
+
+ const apiUrl = new URL(`m/newslist.ashx?ac=rank&tid=${range}`, rootUrl).href;
+
+ const { data: response } = await got(apiUrl);
+
+ const $ = cheerio.load(response);
+
+ let items = $('a')
+ .toArray()
+ .filter((item) => /\/(\d+)\.html?/.test($(item).prop('href')))
+ .slice(0, limit)
+ .map((item) => {
+ item = $(item);
+
+ const link = item.prop('href');
+
+ return {
+ title: item.text(),
+ link: new URL(link, rootUrl).href,
+ guid: link.match(/\/(\d+)\.html?/)[1],
+ };
+ });
+
+ items = await processItems(items, ctx.cache.tryGet);
+
+ ctx.state.data = {
+ item: items,
+ ...(await getInfo(currentUrl, ctx.cache.tryGet, parseInt(range, 10))),
+ };
+};
diff --git a/lib/v2/mydrivers/router.js b/lib/v2/mydrivers/router.js
index 5f136f299b..00c9ce5876 100644
--- a/lib/v2/mydrivers/router.js
+++ b/lib/v2/mydrivers/router.js
@@ -1,3 +1,6 @@
module.exports = function (router) {
- router.get('/:type?/:id?', require('./index'));
+ router.get('/cid/:id?', require('./cid'));
+ router.get('/rank/:range?', require('./rank'));
+ router.get('/zhibo', require('./cid'));
+ router.get('/:category*', require('./'));
};
diff --git a/lib/v2/mydrivers/templates/description.art b/lib/v2/mydrivers/templates/description.art
new file mode 100644
index 0000000000..779c2f675f
--- /dev/null
+++ b/lib/v2/mydrivers/templates/description.art
@@ -0,0 +1,5 @@
+{{ if image }}
+
+
+
+{{ /if }}
\ No newline at end of file
diff --git a/lib/v2/mydrivers/util.js b/lib/v2/mydrivers/util.js
new file mode 100644
index 0000000000..2242b75e06
--- /dev/null
+++ b/lib/v2/mydrivers/util.js
@@ -0,0 +1,125 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
+const { parseDate } = require('@/utils/parse-date');
+
+const domain = 'mydrivers.com';
+const rootUrl = `https://m.${domain}`;
+const rootRSSUrl = `https://rss.${domain}`;
+const apiVoteUrl = new URL('m/newsvote.ashx', rootUrl).href;
+
+const title = '快科技';
+
+const categories = {
+ new: '最新',
+ hot: '热门',
+ zhibo: '直播',
+};
+
+/**
+ * Converts a path string into a query string.
+ * @param {string} path - The path string separated by slashes, containing key-value pairs.
+ * @returns {string} - The query string with key-value pairs separated by question marks and equal signs.
+ */
+const convertToQueryString = (path) => {
+ const parts = path.split('/');
+ const queryStringParams = [];
+
+ for (const [key, value] of parts.reduce((acc, part, index) => {
+ if (index % 2 === 0) {
+ acc.push([part]);
+ } else {
+ acc[acc.length - 1].push(part);
+ }
+ return acc;
+ }, [])) {
+ queryStringParams.push(`${key}=${value}`);
+ }
+
+ return `?${queryStringParams.join('&')}`;
+};
+
+/**
+ * Retrieves information from a given URL using a provided tryGet function.
+ * @param {string} url - The URL to retrieve information from.
+ * @param {function} tryGet - The tryGet function that handles the retrieval process.
+ * @param {number|undefined} [range] - The index value of the range (optional).
+ * @returns {Promise