Files
nanocode/playwright-hotspots/src/platforms/xiaohongshu.js
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

97 lines
2.6 KiB
JavaScript

/**
* 小红书搜索/热点抓取
* 注意:小红书需要登录才能获取完整数据
*/
const puppeteer = require('puppeteer-core');
const { getLaunchOptions } = require('../../config/browser');
const { saveData, randomDelay, printTable } = require('../utils/helpers');
const PLATFORM = 'xiaohongshu';
/**
* 抓取小红书搜索建议/热点
* @param {string} keyword - 搜索关键词
*/
async function fetchXiaohongshuSearch(keyword = 'AI') {
const browser = await puppeteer.launch(getLaunchOptions());
try {
console.log(`🔴 开始抓取小红书搜索: "${keyword}"...`);
const page = await browser.newPage();
// 设置 User-Agent
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 searchUrl = `https://www.xiaohongshu.com/search_result?keyword=${encodeURIComponent(keyword)}`;
await page.goto(searchUrl, {
waitUntil: 'networkidle2',
timeout: 60000
});
await randomDelay(2000, 4000);
// 尝试提取笔记数据
const notes = await page.evaluate(() => {
const items = [];
// 小红书的笔记卡片选择器(可能随时间变化)
const cards = document.querySelectorAll('.note-item, [class*="note"], .feeds-page > div > div');
cards.forEach((card, index) => {
const titleEl = card.querySelector('.title, .desc, [class*="title"]');
const linkEl = card.querySelector('a[href*="/explore/"]');
if (titleEl) {
items.push({
rank: index + 1,
title: titleEl.textContent.trim().substring(0, 100),
url: linkEl ? linkEl.href : '',
});
}
});
return items;
});
const result = {
platform: PLATFORM,
keyword,
timestamp: new Date().toISOString(),
url: searchUrl,
count: notes.length,
items: notes.slice(0, 10),
note: '小红书需要登录才能获取完整数据',
};
if (notes.length > 0) {
printTable(result.items);
} else {
console.log('⚠️ 未获取到数据,可能需要登录');
}
saveData(PLATFORM, result);
console.log(`✅ 完成`);
return result;
} catch (error) {
console.error('❌ 抓取失败:', error.message);
throw error;
} finally {
await browser.close();
}
}
module.exports = { fetchXiaohongshuSearch };
// 直接运行
if (require.main === module) {
const keyword = process.argv[2] || 'AI';
fetchXiaohongshuSearch(keyword).catch(console.error);
}