search.js
1 import { cli, Strategy } from '@jackwener/opencli/registry'; 2 import { decodeHtmlEntities, getHupuSearchUrl, readHupuSearchData, stripHtml } from './utils.js'; 3 cli({ 4 site: 'hupu', 5 name: 'search', 6 description: '搜索虎扑帖子 (使用官方API)', 7 domain: 'bbs.hupu.com', 8 strategy: Strategy.PUBLIC, // 公开API,不需要Cookie 9 browser: true, 10 navigateBefore: false, 11 args: [ 12 { 13 name: 'query', 14 required: true, 15 positional: true, 16 help: '搜索关键词' 17 }, 18 { 19 name: 'page', 20 type: 'int', 21 default: 1, 22 help: '结果页码' 23 }, 24 { 25 name: 'limit', 26 type: 'int', 27 default: 20, 28 help: '返回结果数量' 29 }, 30 { 31 name: 'forum', 32 help: '板块ID过滤 (可选)' 33 }, 34 { 35 name: 'sort', 36 default: 'general', 37 help: '排序方式: general/createtime/replytime/light/reply' 38 } 39 ], 40 columns: ['rank', 'title', 'author', 'replies', 'lights', 'forum', 'url'], 41 func: async (page, kwargs) => { 42 const { query, page: pageNum = 1, limit = 20, forum, sort = 'general' } = kwargs; 43 const searchUrl = getHupuSearchUrl(query, pageNum, forum, sort); 44 const data = await readHupuSearchData(page, searchUrl, 'Search Hupu threads'); 45 // 提取搜索结果 46 const results = data.searchRes?.data || []; 47 // 处理结果:清理HTML标签,解码HTML实体 48 const processedResults = results.slice(0, Number(limit)).map((item, index) => ({ 49 rank: index + 1, 50 title: decodeHtmlEntities(stripHtml(item.title)), 51 author: item.username || '未知用户', 52 replies: item.replies || '0', 53 lights: item.lights || '0', 54 forum: item.forum_name || '未知板块', 55 url: `https://bbs.hupu.com/${item.id}.html` 56 })); 57 return processedResults; 58 }, 59 });