diff --git a/docs/government.md b/docs/government.md
index ceef0b77bf..5f7574a179 100644
--- a/docs/government.md
+++ b/docs/government.md
@@ -1337,6 +1337,16 @@ pageClass: routes
## 中央纪委国家监委
-### 审查调查
+### 要闻
-
+
+
+::: tip 提示
+
+路径处填写对应页面 URL 中 `http://www.ccdi.gov.cn/` 后的字段。下面是一个例子。
+
+若订阅 [审查调查 > 中管干部 > 执纪审查](https://www.ccdi.gov.cn/scdcn/zggb/zjsc/) 则将对应页面 URL 中 `http://www.ccdi.gov.cn/` 后的字段 `scdcn/zggb/zjsc` 作为路径填入。此时路由为 [`/gov/ccdi/scdcn/zggb/zjsc`](https://rsshub.app/gov/ccdi/scdcn/zggb/zjsc)
+
+:::
+
+
diff --git a/lib/router.js b/lib/router.js
index 17ed8825e6..d98489f9d8 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -1801,9 +1801,6 @@ router.get('/cninfo/announcement/:column/:code/:orgId/:category?/:search?', lazy
// 金十数据
router.get('/jinshi/index', lazyloadRouteHandler('./routes/jinshi/index'));
-// 中央纪委国家监委网站
-router.get('/ccdi/scdc', lazyloadRouteHandler('./routes/ccdi/scdc'));
-
// 中华人民共和国农业农村部
router.get('/gov/moa/sjzxfb', lazyloadRouteHandler('./routes/gov/moa/sjzxfb'));
router.get('/gov/moa/:suburl(.*)', lazyloadRouteHandler('./routes/gov/moa/moa'));
diff --git a/lib/routes/ccdi/scdc.js b/lib/routes/ccdi/scdc.js
deleted file mode 100644
index 558f53c636..0000000000
--- a/lib/routes/ccdi/scdc.js
+++ /dev/null
@@ -1,51 +0,0 @@
-const cheerio = require('cheerio');
-const got = require('@/utils/got');
-const { resolve } = require('url');
-
-module.exports = async (ctx) => {
- const url = 'https://www.ccdi.gov.cn/scdcn/';
- const res = await got.get(url);
- const $ = cheerio.load(res.data);
-
- const list = $('ul.list_news_dl.fixed li');
- const out = await Promise.all(
- list
- .map(async (index, elem) => {
- elem = $(elem);
- const title = elem.find('a').text();
- const link = resolve(url, elem.find('a').attr('href'));
- const pubDate = new Date(elem.find('span').text()).toUTCString();
-
- const item = {
- title,
- pubDate,
- link,
- };
-
- const key = link;
- const value = await ctx.cache.get(key);
- if (value) {
- item.description = value;
- } else {
- try {
- const response = await got.get(item.link);
- const data = response.data;
- const $ = cheerio.load(data);
- item.description = $('div.TRS_Editor').html();
- ctx.cache.set(key, item.description);
- } catch (error) {
- item.description = '';
- }
- }
-
- return item;
- })
- .get()
- );
-
- ctx.state.data = {
- title: '中央纪委国家监委-审查调查',
- link: url,
- item: out,
- };
-};
diff --git a/lib/v2/gov/ccdi/index.js b/lib/v2/gov/ccdi/index.js
new file mode 100644
index 0000000000..9ba24aa68f
--- /dev/null
+++ b/lib/v2/gov/ccdi/index.js
@@ -0,0 +1,31 @@
+/* eslint-disable no-await-in-loop */
+const { rootUrl, parseNewsList, parseArticle } = require('./utils');
+
+const getRandomInt = (min, max) => {
+ min = Math.ceil(min);
+ max = Math.floor(max);
+ return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive
+};
+
+module.exports = async (ctx) => {
+ const defaultPath = '/yaowenn/';
+
+ let pathname = ctx.path.replace(/(^\/ccdi|\/$)/g, '');
+ pathname = pathname === '' ? defaultPath : pathname.endsWith('/') ? pathname : pathname + '/';
+ const currentUrl = `${rootUrl}${pathname}`;
+
+ const { list, title } = await parseNewsList(currentUrl, '.list_news_dl li', ctx);
+ const items = [];
+
+ for (const item of list) {
+ items.push(await parseArticle(item, ctx));
+ // sleep randomly for anti rate limit on ccdi site
+ await new Promise((r) => setTimeout(r, getRandomInt(1000, 2500)));
+ }
+
+ ctx.state.data = {
+ title,
+ link: currentUrl,
+ item: items,
+ };
+};
diff --git a/lib/v2/gov/ccdi/utils.js b/lib/v2/gov/ccdi/utils.js
new file mode 100644
index 0000000000..a6c01b698f
--- /dev/null
+++ b/lib/v2/gov/ccdi/utils.js
@@ -0,0 +1,57 @@
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+const got = require('@/utils/got');
+const timezone = require('@/utils/timezone');
+
+const { CookieJar } = require('tough-cookie');
+const cookieJar = new CookieJar();
+
+const owner = '中央纪委国家监委网站';
+const rootUrl = 'https://www.ccdi.gov.cn';
+
+const parseNewsList = async (url, selector, ctx) => {
+ const response = await got(url, { cookieJar });
+ const $ = cheerio.load(response.data);
+ const list = $(selector)
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 8)
+ .toArray()
+ .map((item) => {
+ item = $(item);
+ return {
+ title: item.find('a').first().text().trim(),
+ link: new URL(item.find('a').first().attr('href'), url).href,
+ pubDate: parseDate(item.find('span').text(), 'YYYY-MM-DD'),
+ };
+ });
+ const title = $('.other_Location')
+ .text()
+ .replace(/(.+)首页/, owner);
+ return { list, title };
+};
+
+const parseArticle = async (item, ctx) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const response = await got(item.link, { cookieJar });
+ const $ = cheerio.load(response.data);
+
+ const title = $('.daty').text().trim();
+ item.author = title.match(/来源:(.*)发布时间/s)?.[1].trim() ?? owner;
+ item.pubDate = timezone(parseDate(title.match(/发布时间:(.*)分享/s)?.[1].trim() ?? item.pubDate), +8);
+
+ // Change the img src from relative to absolute for a better compatibility
+ $('.content')
+ .find('img')
+ .each((_, el) => {
+ $(el).attr('src', new URL($(el).attr('src'), item.link).href);
+ // oldsrc is causing freshrss imageproxy not to work correctly
+ $(el).removeAttr('oldsrc').removeAttr('alt');
+ });
+ item.description = $('.content').html();
+ return item;
+ });
+
+module.exports = {
+ rootUrl,
+ parseNewsList,
+ parseArticle,
+};
diff --git a/lib/v2/gov/maintainer.js b/lib/v2/gov/maintainer.js
index a908eca04c..ce79c3459e 100644
--- a/lib/v2/gov/maintainer.js
+++ b/lib/v2/gov/maintainer.js
@@ -1,5 +1,6 @@
module.exports = {
// ministry
+ '/ccdi/:path+': ['bigfei'],
'/cmse/xwzx/zhxw': ['nczitzk'],
'/cmse/xwzx/yzjz': ['nczitzk'],
'/cmse/gfgg': ['nczitzk'],
diff --git a/lib/v2/gov/radar.js b/lib/v2/gov/radar.js
index 5e46fccc05..090db1579e 100644
--- a/lib/v2/gov/radar.js
+++ b/lib/v2/gov/radar.js
@@ -297,6 +297,17 @@ module.exports = {
},
],
},
+ 'ccdi.gov.cn': {
+ _name: '中央纪委国家监委',
+ www: [
+ {
+ title: '要闻',
+ docs: 'https://docs.rsshub.app/government.html#zhong-yang-ji-wei-guo-jia-jian-wei-yao-wen',
+ source: ['/*'],
+ target: (params, url) => `/gov/ccdi/${new URL(url).href.match(/ccdi\.gov\.cn\/(.*)/)[1]}`,
+ },
+ ],
+ },
'cmse.gov.cn': {
_name: '中国载人航天',
www: [
diff --git a/lib/v2/gov/router.js b/lib/v2/gov/router.js
index 9ee21fec16..4fd34ba2ae 100644
--- a/lib/v2/gov/router.js
+++ b/lib/v2/gov/router.js
@@ -1,5 +1,6 @@
module.exports = function (router) {
// ministry
+ router.get(/ccdi(\/[\w/-]+)?/, require('./ccdi'));
router.get('/cmse/fxrw', require('./cmse/fxrw'));
router.get(/cmse(\/[\w/-]+)?/, require('./cmse'));
router.get(/cnnic(\/[\w/-]+)?/, require('./cnnic'));