fix(route/cjlu/yjsy): use Puppeteer to fetch CJLU Graduate School notices after anti-crawler update (#20359)
* fix(route/yjsy): use puppeteer to bypass WAF * fix: chage waiting-util to get fully loaded page * fix: remove 'stylesheet' from excludeResourceTypes in yjsy route * chore: provide default title for notifications in yjsy route * fix: add HTTP headers for Puppeteer page requests in yjsy route * fix: replace global ua in config with a static value * fix: change waitUntil from 'networkidle0' to 'networkidle2' * fix: set ua with setUserAgent * fix: ensure user agent is set after HTTP headers in Puppeteer page requests * fix: add limit parameter to handler for controlling result set size * fix: update resource type handling in request interception - use default maxAge managed by env
This commit is contained in:
parent
4c3591265f
commit
e45d803691
|
|
@ -4,6 +4,7 @@ import { load } from 'cheerio';
|
|||
import { parseDate } from '@/utils/parse-date';
|
||||
import cache from '@/utils/cache';
|
||||
import timezone from '@/utils/timezone';
|
||||
import { getPuppeteerPage } from '@/utils/puppeteer';
|
||||
|
||||
const host = 'https://yjsy.cjlu.edu.cn/';
|
||||
|
||||
|
|
@ -11,18 +12,49 @@ const titleMap = new Map([
|
|||
['yjstz', '中量大研究生院 —— 研究生通知'],
|
||||
['jstz', '中量大研究生院 —— 教师通知'],
|
||||
]);
|
||||
const headers = {
|
||||
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'Cache-Control': 'max-age=0',
|
||||
Connection: 'keep-alive',
|
||||
Referer: 'https://yjsy.cjlu.edu.cn',
|
||||
'Sec-Fetch-Dest': 'document',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'Sec-Fetch-User': '?1',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0',
|
||||
'sec-ch-ua': '"Microsoft Edge";v="141", "Not?A_Brand";v="8", "Chromium";v="141"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
};
|
||||
|
||||
const allowedResourceTypes = new Set(['document', 'script']);
|
||||
|
||||
export const route: Route = {
|
||||
path: '/yjsy/:cate',
|
||||
categories: ['university'],
|
||||
example: '/cjlu/yjsy/yjstz',
|
||||
parameters: {
|
||||
cate: '订阅的类型,支持 yjstz(研究生通知)和 jstz(教师通知)',
|
||||
cate: {
|
||||
description: '订阅的类型,支持 yjstz(研究生通知)和 jstz(教师通知)',
|
||||
default: 'yjstz',
|
||||
options: [
|
||||
{
|
||||
label: '教师通知',
|
||||
value: 'jstz',
|
||||
},
|
||||
{
|
||||
label: '研究生通知',
|
||||
value: 'yjstz',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
antiCrawler: false,
|
||||
requirePuppeteer: true,
|
||||
antiCrawler: true,
|
||||
supportRadar: true,
|
||||
supportBT: false,
|
||||
supportPodcast: false,
|
||||
|
|
@ -50,17 +82,33 @@ export const route: Route = {
|
|||
|
||||
async function handler(ctx) {
|
||||
const cate = ctx.req.param('cate');
|
||||
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 10;
|
||||
const url = `${host}index/${cate}.htm`;
|
||||
|
||||
const response = await ofetch(`${cate}.htm`, {
|
||||
baseURL: `${host}/index/`,
|
||||
responseType: 'text',
|
||||
const { page, destory, browser } = await getPuppeteerPage(url, {
|
||||
onBeforeLoad: async (page) => {
|
||||
await page.setExtraHTTPHeaders(headers);
|
||||
await page.setUserAgent(headers['User-Agent']);
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (request) => {
|
||||
allowedResourceTypes.has(request.resourceType()) ? request.continue() : request.abort();
|
||||
});
|
||||
},
|
||||
gotoConfig: { waitUntil: 'networkidle2' },
|
||||
});
|
||||
|
||||
const cookies = await browser.cookies();
|
||||
const cookieString = cookies.map((c) => `${c.name}=${c.value}`).join('; ');
|
||||
|
||||
const response = await page.content();
|
||||
await destory();
|
||||
|
||||
const $ = load(response);
|
||||
|
||||
const list = $('div.grid685.right div.body ul')
|
||||
.find('li')
|
||||
.toArray()
|
||||
.slice(0, limit)
|
||||
.map((element) => {
|
||||
const item = $(element);
|
||||
|
||||
|
|
@ -71,7 +119,7 @@ async function handler(ctx) {
|
|||
const route = href.startsWith('../') ? href.replace(/^\.\.\//, '') : href;
|
||||
|
||||
return {
|
||||
title: a.attr('title') ?? titleMap.get(cate),
|
||||
title: a.attr('title') ?? titleMap.get(cate) ?? '中量大研究生院通知',
|
||||
pubDate: timezone(parseDate(timeStr, 'YYYY/MM/DD'), +8),
|
||||
link: `${host}${route}`,
|
||||
description: '',
|
||||
|
|
@ -87,6 +135,11 @@ async function handler(ctx) {
|
|||
|
||||
const res = await ofetch(item.link, {
|
||||
responseType: 'text',
|
||||
headers: {
|
||||
...headers,
|
||||
Cookie: cookieString,
|
||||
Referer: url,
|
||||
},
|
||||
});
|
||||
const $ = load(res);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue