diff --git a/docs/traditional-media.md b/docs/traditional-media.md index bf4c4ffb0..1aaebaa69 100644 --- a/docs/traditional-media.md +++ b/docs/traditional-media.md @@ -86,6 +86,12 @@ Solidot 提供的 feed: +## 北极星电力网 + +### 北极星环保 + + + ## 财新网 > 网站部分内容需要付费订阅, RSS 仅做更新提醒, 不含付费内容. diff --git a/lib/router.js b/lib/router.js index ce4c00b5f..d756edde1 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1172,6 +1172,9 @@ router.get('/people/opinion/:id', require('./routes/people/opinion')); router.get('/people/env/:id', require('./routes/people/env')); router.get('/people/xjpjh/:keyword?/:year?', require('./routes/people/xjpjh')); +// 北极星电力网 +router.get('/bjx/huanbao', require('./routes/bjx/huanbao')); + // gamersky router.get('/gamersky/news', require('./routes/gamersky/news')); router.get('/gamersky/ent/:category', require('./routes/gamersky/ent')); diff --git a/lib/routes/bjx/huanbao.js b/lib/routes/bjx/huanbao.js new file mode 100644 index 000000000..063c593d9 --- /dev/null +++ b/lib/routes/bjx/huanbao.js @@ -0,0 +1,84 @@ +const got = require('@/utils/got'); +const date = require('@/utils/date'); +const cheerio = require('cheerio'); +const url = require('url'); +const iconv = require('iconv-lite'); + +module.exports = async (ctx) => { + const listURL = 'http://huanbao.bjx.com.cn/NewsList'; + const response = await got({ + method: 'get', + url: listURL, + }); + + const $ = cheerio.load(response.data); + const list = $('.list_main .list_left_ul a') + .map((_, a) => $(a).attr('href')) + .get(); + + const out = await Promise.all( + // 服务器禁止单个IP大并发访问,只能少返回几条 + list.slice(0, 3).map((link) => fetchPage(ctx, link)) + ); + + ctx.state.data = { + title: '北极星环保 - 环保行业垂直门户网站', + link: listURL, + item: out, + }; +}; + +async function fetchPage(ctx, link) { + const cache = await ctx.cache.get(link); + if (cache) { + return JSON.parse(cache); + } + + // 可能一篇文章过长会分成多页 + const pages = []; + + const result = await got.get(link, { responseType: 'buffer' }); + const $page = cheerio.load(iconv.decode(result.data, 'gbk')); + pages.push($page); + + // 如果是有分页链接,则使用顺序加载以保证顺序 + const pagelinks = $page('.list_detail div.page a'); + if (pagelinks.length > 0) { + for (let i = 0; i < pagelinks.length; i++) { + const $a = $page(pagelinks[i]); + if (!/^\d+$/.test($a.text().trim())) { + continue; + } + const sublink = url.resolve(link, $a.attr('href')); + /* eslint-disable no-await-in-loop */ + const result = await got.get(sublink, { responseType: 'buffer' }); + pages.push(cheerio.load(iconv.decode(result.data, 'gbk'))); + } + } + + // 将懒加载的loading图片转换为真实图片 + pages.forEach(($p) => { + $p('#content') + .find('img[data-echo]') + .each((_, img) => { + const $img = $p(img); + $img.attr('src', $img.data('echo')).removeAttr('data-echo'); + }); + }); + + const item = { + title: $page('.list_detail > h1').text(), + description: pages.reduce((desc, $p) => desc + $p('#content').html(), ''), + pubDate: date( + $page('.list_detail .list_copy b') + .last() + .text() + ), + link, + author: $page('.list_detail .list_copy b') + .first() + .text(), + }; + ctx.cache.set(link, JSON.stringify(item)); + return item; +}