#!/usr/bin/env node /** * 使用 Puppeteer 搜索技术博客 */ const puppeteer = require('puppeteer-core'); const { getLaunchOptions } = require('../config/browser'); const fs = require('fs'); const path = require('path'); function saveResult(platform, keyword, items) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const data = { platform, keyword, timestamp: new Date().toISOString(), count: items.length, items, }; const filepath = path.join(__dirname, '../data', `${platform}_search_${timestamp}.json`); if (!fs.existsSync(path.dirname(filepath))) { fs.mkdirSync(path.dirname(filepath), { recursive: true }); } fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf-8'); return filepath; } function printResults(items, platform) { console.log('\n' + '='.repeat(70)); items.forEach((item, i) => { console.log(`${i + 1}. ${item.title.substring(0, 60)}${item.title.length > 60 ? '...' : ''}`); console.log(` ${item.url}`); }); console.log('='.repeat(70)); } async function searchJuejin(browser, keyword) { console.log(`\n📱 搜索掘金: "${keyword}"`); const page = await browser.newPage(); try { await page.setUserAgent( 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' ); const url = `https://juejin.cn/search?query=${encodeURIComponent(keyword)}&type=0`; await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000, }); // 等待搜索结果加载 await new Promise(r => setTimeout(r, 3000)); // 提取搜索结果 const items = await page.evaluate(() => { const results = []; // 掘金搜索结果选择器 const selectors = [ '.search-result-list .item a.title', '.result-list .item .title a', '[class*="search"] [class*="item"] a[href*="/post/"]', '.article-item a', ]; for (const selector of selectors) { const elements = document.querySelectorAll(selector); if (elements.length > 0) { elements.forEach((el) => { const title = el.textContent?.trim(); const href = el.getAttribute('href'); if (title && href && title.length > 5 && !results.find(r => r.title === title)) { const articleId = href.match(/\/post\/(\d+)/)?.[1]; if (articleId) { results.push({ title: title.substring(0, 100), url: `https://juejin.cn/post/${articleId}`, }); } } }); break; } } return results.slice(0, 10); }); if (items.length > 0) { printResults(items, '掘金'); const filepath = saveResult('juejin', keyword, items); console.log(`✅ 找到 ${items.length} 条结果`); console.log(`💾 已保存: ${filepath}`); } else { console.log('⚠️ 未找到结果,页面可能需要登录'); } return items; } catch (e) { console.error('❌ 掘金搜索失败:', e.message); return []; } finally { await page.close(); } } async function searchCnblogs(browser, keyword) { console.log(`\n💻 搜索博客园: "${keyword}"`); const page = await browser.newPage(); try { await page.setUserAgent( 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' ); const url = `https://zzk.cnblogs.com/s?w=${encodeURIComponent(keyword)}`; await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000, }); await new Promise(r => setTimeout(r, 3000)); // 提取搜索结果 const items = await page.evaluate(() => { const results = []; const selectors = [ '.searchItem .searchItemTitle a', '.search-item .title a', '#search_result .searchItem a', ]; for (const selector of selectors) { const elements = document.querySelectorAll(selector); if (elements.length > 0) { elements.forEach((el) => { const title = el.textContent?.trim(); const href = el.getAttribute('href'); if (title && href && title.length > 5 && !results.find(r => r.title === title)) { results.push({ title: title.substring(0, 100), url: href.startsWith('http') ? href : `https:${href}`, }); } }); break; } } return results.slice(0, 10); }); if (items.length > 0) { printResults(items, '博客园'); const filepath = saveResult('cnblogs', keyword, items); console.log(`✅ 找到 ${items.length} 条结果`); console.log(`💾 已保存: ${filepath}`); } else { console.log('⚠️ 未找到结果'); } return items; } catch (e) { console.error('❌ 博客园搜索失败:', e.message); return []; } finally { await page.close(); } } async function main() { const keyword = process.argv[2] || 'android 开发'; const platform = process.argv[3] || 'all'; console.log('='.repeat(70)); console.log(`🔍 技术博客搜索: "${keyword}"`); console.log('='.repeat(70)); const browser = await puppeteer.launch(getLaunchOptions()); try { if (platform === 'all' || platform === 'juejin') { await searchJuejin(browser, keyword); } if (platform === 'all' || platform === 'cnblogs') { await searchCnblogs(browser, keyword); } } finally { await browser.close(); } console.log('\n' + '='.repeat(70)); console.log('搜索完成'); console.log('='.repeat(70)); } main().catch(console.error);