UNPKG

rsshub

Version:
160 lines (143 loc) 4.64 kB
import InvalidParameterError from '@/errors/types/invalid-parameter'; import { Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { load } from 'cheerio'; import { config } from '@/config'; import { puppeteerGet } from './utils'; import puppeteer from '@/utils/puppeteer'; const baseUrl = 'https://xsijishe.com'; export const route: Route = { path: '/rank/:type', categories: ['bbs'], example: '/xsijishe/rank/weekly', parameters: { type: { description: '排行榜类型', options: [ { value: 'weekly', label: '周榜' }, { value: 'monthly', label: '月榜' }, ], }, }, features: { requireConfig: [ { name: 'XSIJISHE_COOKIE', description: '', }, { name: 'XSIJISHE_USER_AGENT', description: '', }, ], requirePuppeteer: true, antiCrawler: true, supportBT: false, supportPodcast: false, supportScihub: false, }, name: '排行榜', maintainers: ['akynazh', 'AiraNadih'], handler, }; async function handler(ctx) { const rankType = ctx.req.param('type'); let title; let index; // 用于选择第几个 li if (rankType === 'weekly') { title = '司机社综合周排行榜'; index = 0; // 第一个 li 是周榜 } else if (rankType === 'monthly') { title = '司机社综合月排行榜'; index = 1; // 第二个 li 是月榜 } else { throw new InvalidParameterError('Invalid rank type'); } const browser = await puppeteer(); let usePuppeteer = false; const url = `${baseUrl}/portal.php`; const headers = { 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', Cookie: config.xsijishe.cookie, 'User-Agent': config.xsijishe.userAgent, }; const resp = await got(url, { headers, }); const redirectMatch = resp.data.match(/window\.location\.href\s*=\s*"([^"]+)"/); if (redirectMatch) { const redirectUrl = `${baseUrl}${redirectMatch[1]}`; // 使用提取到的地址重新请求 const realResp = await got(redirectUrl, { headers, }); resp.data = realResp.data; } const $ = load(resp.data); // 根据 index 选择对应的 li,然后获取其中的 dd 元素 let items = $('.nex_recon_lists ul li') .eq(index) .find('.nex_recons_demens dl dd') .toArray() .map((item) => { item = $(item); const title = item.find('h5').text().trim(); const link = item.find('a').attr('href'); const description = item.find('img').prop('outerHTML'); return { title, link: `${baseUrl}/${link}`, description, }; }); if (items.length > 0) { const firstItem = items[0]; const resp = await got(firstItem.link, { headers, }); const $ = load(resp.data); const firstViewBox = $('.t_f').first(); if (firstViewBox.length === 0) { usePuppeteer = true; } } items = await Promise.all( items.map((item) => cache.tryGet(item.link, async () => { let data; if (usePuppeteer) { data = await puppeteerGet(item.link, browser); } else { const resp = await got(item.link, { headers, }); data = resp.data; } const $ = load(data); const firstViewBox = $('.t_f').first(); if (firstViewBox.length === 1) { firstViewBox.find('img').each((_, img) => { img = $(img); if (img.attr('zoomfile')) { img.attr('src', img.attr('zoomfile')); img.removeAttr('zoomfile'); img.removeAttr('file'); } img.removeAttr('onmouseover'); }); item.description = firstViewBox.html(); } return item; }) ) ); await browser.close(); return { title, link: url, description: title, item: items, }; }