9b395f5cc3
E2E Headed Chrome / e2e-headed (macos-15) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (ubuntu-latest) (push) Has been cancelled
E2E Headed Chrome / e2e-headed (windows-latest) (push) Has been cancelled
CI / build (macos-latest) (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
CI / unit-test (push) Has been cancelled
CI / bun-test (push) Has been cancelled
CI / adapter-test (push) Has been cancelled
CI / smoke-test (macos-latest) (push) Has been cancelled
CI / smoke-test (ubuntu-latest) (push) Has been cancelled
Security Audit / audit (push) Has been cancelled
Build Chrome Extension / build (push) Has been cancelled
Trigger Website Rebuild (Docs Updated) / dispatch (push) Has been cancelled
57 lines
2.3 KiB
JavaScript
57 lines
2.3 KiB
JavaScript
/**
|
||
* 51job hot / recommended feed.
|
||
*
|
||
* Same endpoint as `search`, but with empty keyword — 51job returns its
|
||
* own ranked recommendation list (up to ~999 for most regions).
|
||
*/
|
||
|
||
import { cli, Strategy } from '@jackwener/opencli/registry';
|
||
import { CliError } from '@jackwener/opencli/errors';
|
||
import {
|
||
WE_ORIGIN, SEARCH_COLUMNS, SORT_CODES,
|
||
requirePage, navigateTo, pageFetchJson,
|
||
buildSearchUrl, mapJobItem, resolveCity, resolveCode,
|
||
} from './utils.js';
|
||
|
||
cli({
|
||
site: '51job',
|
||
name: 'hot',
|
||
access: 'read',
|
||
description: '51job 推荐职位(按城市/行业/排序浏览)',
|
||
domain: 'we.51job.com',
|
||
strategy: Strategy.COOKIE,
|
||
browser: true,
|
||
navigateBefore: false,
|
||
args: [
|
||
{ name: 'area', type: 'string', default: '全国', help: '城市名或 6 位城市码(默认 "全国")' },
|
||
{ name: 'sort', type: 'string', default: '综合', help: '排序:综合 / 最新 / 薪资 / 距离' },
|
||
{ name: 'page', type: 'int', default: 1, help: '页码(1-based)' },
|
||
{ name: 'limit', type: 'int', default: 20, help: '返回条数(1-50)' },
|
||
],
|
||
columns: SEARCH_COLUMNS,
|
||
func: async (page, kwargs) => {
|
||
requirePage(page);
|
||
const limit = Math.max(1, Math.min(Number(kwargs.limit) || 20, 50));
|
||
const pageNum = Math.max(1, Number(kwargs.page) || 1);
|
||
const jobArea = resolveCity(kwargs.area);
|
||
const sortType = resolveCode(kwargs.sort, SORT_CODES, '0');
|
||
|
||
const currentUrl = await page.evaluate(`(() => window.location.href)()`);
|
||
if (!String(currentUrl).startsWith(WE_ORIGIN)) {
|
||
await navigateTo(page, `${WE_ORIGIN}/pc/search?searchType=2`, 2);
|
||
}
|
||
|
||
const url = buildSearchUrl({
|
||
keyword: '', jobArea, sortType,
|
||
pageNum, pageSize: Math.min(limit, 50),
|
||
});
|
||
const data = await pageFetchJson(page, url);
|
||
if (data.status !== '1' && data.status !== 1) {
|
||
throw new CliError('API_ERROR', `51job hot failed: ${data.message ?? 'unknown'}`);
|
||
}
|
||
const items = data?.resultbody?.job?.items ?? [];
|
||
if (items.length === 0) throw new CliError('NO_DATA', 'No recommended jobs returned');
|
||
return items.slice(0, limit).map((it, i) => mapJobItem(it, (pageNum - 1) * limit + i + 1));
|
||
},
|
||
});
|