diff --git a/docs/traditional-media.md b/docs/traditional-media.md
index 6c935cec36..6ad6e04c40 100644
--- a/docs/traditional-media.md
+++ b/docs/traditional-media.md
@@ -316,6 +316,22 @@ category 对应的关键词有
+## 齐鲁晚报
+
+### 新闻
+
+
+
+### 今日城市
+
+
+
+| 今日临沂 | 今日德州 | 今日威海 | 今日枣庄 | 今日淄博 | 今日烟台 | 今日潍坊 | 今日菏泽 | 今日日照 | 今日泰山 | 今日聊城 | 今日济宁 |
+| -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | -------- | -------- | --------- | -------- |
+| linyi | dezhou | weihai | zaozhuang | zibo | yantai | weifang | heze | rizhao | taishan | liaocheng | jining |
+
+
+
## 人民日报
### 观点
diff --git a/lib/router.js b/lib/router.js
index d254065e9f..24a5ab14f7 100755
--- a/lib/router.js
+++ b/lib/router.js
@@ -2639,6 +2639,10 @@ router.get('/slu/csggxy/:id', require('./routes/universities/slu/csggxy'));
router.get('/ruby-china/topics/:type?', require('./routes/ruby-china/topics'));
router.get('/ruby-china/jobs', require('./routes/ruby-china/jobs'));
+// 齐鲁晚报
+router.get('/qlwb/news', require('./routes/qlwb/news'));
+router.get('/qlwb/city/:city', require('./routes/qlwb/city'));
+
// 蜻蜓FM
router.get('/qingting/channel/:id', require('./routes/qingting/channel'));
diff --git a/lib/routes/qlwb/city.js b/lib/routes/qlwb/city.js
new file mode 100644
index 0000000000..c2b6dffef0
--- /dev/null
+++ b/lib/routes/qlwb/city.js
@@ -0,0 +1,55 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+const config = {
+ linyi: 'http://linyi.qlwb.com.cn/yaowen/',
+ dezhou: 'http://dezhou.qlwb.com.cn/yaowen/',
+ weihai: 'http://jrwh.qlwb.com.cn/yaowen/',
+ zaozhuang: 'http://jrzz.qlwb.com.cn/yw/',
+ zibo: 'http://jrzb.qlwb.com.cn/yw/',
+ yantai: 'http://yantai.qlwb.com.cn/yantai/yaowen/',
+ weifang: 'http://jrwf.qlwb.com.cn/xw/',
+ heze: 'http://jrhz.qlwb.com.cn/jjhz/',
+ rizhao: 'http://jrrz.qlwb.com.cn/fbh/',
+ taishan: 'http://taian.qlwb.com.cn/fabu/',
+ liaocheng: 'http://www.qlwb.com.cn/news/sqds/liaocheng/',
+ jining: 'http://jryh.qlwb.com.cn/jiningxinwen/',
+};
+
+module.exports = async (ctx) => {
+ const newsUrl = config[ctx.params.city];
+
+ const response = await got({
+ method: 'get',
+ url: newsUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+ const list = $('ul.list.list-point li a')
+ .slice(0, 10)
+ .map((_, item) => {
+ item = $(item);
+ return {
+ title: item.text(),
+ link: item.attr('href'),
+ };
+ })
+ .get();
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: newsUrl,
+ item: await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const res = await got({ method: 'get', url: item.link });
+ const content = cheerio.load(res.data);
+ item.description = content('div.article-content').html();
+ item.pubDate = new Date(content('span.date').text() + ' GMT+8').toUTCString();
+ return item;
+ })
+ )
+ ),
+ };
+};
diff --git a/lib/routes/qlwb/news.js b/lib/routes/qlwb/news.js
new file mode 100644
index 0000000000..e0e064180a
--- /dev/null
+++ b/lib/routes/qlwb/news.js
@@ -0,0 +1,38 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const newsUrl = 'http://news.qlwb.com.cn/news/';
+ const response = await got({
+ method: 'get',
+ url: newsUrl,
+ });
+ const $ = cheerio.load(response.data);
+ const list = $('ul.list.list-point li a')
+ .slice(0, 10)
+ .map((_, item) => {
+ item = $(item);
+ return {
+ title: item.text(),
+ link: item.attr('href'),
+ };
+ })
+ .get();
+
+ ctx.state.data = {
+ title: $('title').text(),
+ link: newsUrl,
+ item: await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const res = await got({ method: 'get', url: item.link });
+ const content = cheerio.load(res.data);
+ item.description = content('div.article-content').html();
+ item.pubDate = new Date(content('span.date').text() + ' GMT+8').toUTCString();
+ return item;
+ })
+ )
+ ),
+ };
+};