解锁小红书搜索、笔记、评论数据的商业价值,新手也能快速上手的自动化采集方案
小红书数据里的商机
每天,小红书上都有无数真实用户在分享他们的体验、吐槽和需求。作为国内最大的生活方式社区,小红书汇集了超过3亿用户,他们在这里寻找种草推荐、分享购物体验、交流生活心得。这些真实的用户声音,背后蕴藏着巨大的商业价值:
小红书上的评论区就像一个聊天群,用户们在这里吐槽产品的不足,分享使用体验,通过这些真实的声音,我们不仅能发现用户的痛点,还能看到市场上还有哪些没被满足的需求。
刷小红书就像是在看一场实时的潮流直播,今天大家在追什么,明天会流行什么,哪些产品突然就火了,这些都能让我们第一时间嗅到市场的风向。
那些点赞收藏超高的笔记,背后都藏着吸引用户的秘密 - 是文案打动了人心,还是找对了目标人群,研究这些成功案例,能帮我们做出更精准的营销决策。
就拿我刚才测试采集的“咖啡机”笔记和用户评论数据来看,至少有这些分析发现:
分析发现一:广东区域的咖啡机可以考虑开发咖啡机防虫配件产品线
- 蟑螂是南方同学挥之不去的噩梦,南方地区(特别是广东)咖啡机容易吸引蟑螂
相关的用户反馈:
分析发现二:咖啡机专用家具系列
咖啡机周边配套家具和装饰需求非常旺盛。很多咖啡机的话题往往带着咖啡机角布置、咖啡家具陈列和展示。
分析发现三:现在的咖啡机市场还处于入门级
推出入门级性价比产品线。
除了咖啡机制造商和配件等实体供应商,其实,还有这些服务升级方向:
提供咖啡机使用培训,开发配套清洁维护服务,设计整体咖啡角解决方案。
自媒体内容创作,可以聚焦用户教育方向,制作咖啡知识科普内容,开发咖啡制作教程。分享咖啡角布置灵感。
但是,手动收集和分析这些数据是一项耗时耗力的工作。如果能自动化采集这些信息,将为品牌和创业者带来巨大价值。正好最近在尝试用Cursor开发,就想着是不是可以快速搞一个自动化采集方案?
让我分享一下,我是如何在一个下午的时间里,借助Cursor开发出一个小红书数据采集工具的经历。这个过程不仅简单有趣,最后的成果也相当实用。
一、为什么选择Cursor,让AI辅助开发?
1.1 从踩坑到顿悟
半年前,我第一次接触Cursor编程,说实话,最开始也是将信将疑。但经过这段时间的实践,我发现Cursor不仅能帮我解决复杂的编程问题,还能大大提升开发效率。特别是在处理爬虫这类技术性较强的项目时,它的帮助简直是雪中送炭。
众所周知,小红书的技术难度几乎是数据采集的天花板。
-
搜索结果是动态加载的,得处理下拉刷新
-
笔记详情页有反爬措施,各种加密参数
-
评论数据藏得深,还得考虑登录态...
以前遇到这种情况,可能要花好几天去研究文档、测试方案。但现在有了Cursor,很多技术难题都能快速突破。这半年来的开发经验告诉我,与其纠结于技术细节,不如先和它讨论一下解决方案。
1.2 开发实录:轻车熟路的配合
经过半年的磨合,我和Cursor配合已经很有默契了。这次开发采用了我最常用的节奏。而且是在我之前做的油猴插件的基础上,再让Cursor开发的。
先说需求,后提难点
比如我是这么说的:"我想增加一个功能,每次在采集笔记的标题、作者等信息后,点开笔记,采集笔记详情和笔记下的用户评论内容。你明白我的需求吗?是否可行?请你思考该如何实现。这个是点击笔记后,展开的内容地址:..."
Cursor马上就理解了我的意思,给出了具体的实现思路:用油猴脚本实现,监听页面滚动,处理动态加载等等。
分步骤实现
- 先搞定基础采集
- 再处理下拉加载
- 最后优化体验
每一步我都说出我的具体需求,Cursor就会给出相应的代码和解释。遇到问题,我就描述现象,它就能给出解决方案。
不断优化
开发过程中遇到了不少小问题:
- 搜索关键词参数莫名其妙变成乱码
- 笔记列表丢失,导致采集不全
- 采集太快容易被限制...
但每次我把问题一说,Cursor都能给出合理的解决方案。比如通过添加随机延迟、优化滚动策略等方式,一步步把这些问题都解决了。
二、这个工具是怎么实现的?
2.1 核心功能
经过一番折腾,最终实现了这些功能:
搜索结果采集
- 输入关键词就能自动采集
- 支持自定义采集页数
- 然后,再一篇一篇自动采集,数据一个都不落下
笔记详情获取
- 自动打开笔记看全文
- 评论也能一起保存,数据格式清晰规整
导出方便
- 直接导出成JSON,需要啥字段都行,原始数据都保留着。JSON数据结构完美解决了一条笔记下多条评论内容。且评论还需要记录正文、时间、点赞数、收藏数(方便分析用户的认可度)。比如这款咖啡机的配件米奇头,得到了好多评论区用户的反馈。
{
"user": "Carol",
"content": "用款咖啡机,用款米奇哈哈",
"time": "2024-07-21",
"likes": "33",
"replies": "25"
},,
{
"user": "虾皮~59611940",
"content": "同款米奇",
"time": "2024-07-31",
"likes": "34",
"replies": "17"
},
采集结果是一个JSON文件:
2.2 关键技术点
开发过程中解决了几个棘手问题:
应对反爬限制
最开始采集没多久就被限制了,后来加了这些措施:
- 随机等待3-7秒,模拟人工操作
- 滚动也做得很自然,不是生硬的跳转
- 控制访问频率,不给服务器太大压力
// 更新状态提示
if (result.details) {
switch (result.details.status) {
case 'success':
updateLoadingTip(loadingTip, `成功采集笔记: ${result.title.slice(0, 20)}...`, 'success');
break;
case 'app\_only':
updateLoadingTip(loadingTip, `笔记需要App查看: ${result.title.slice(0, 20)}...`, 'warning');
break;
case 'error':
updateLoadingTip(loadingTip, `采集详情失败: ${result.title.slice(0, 20)}...`, 'error');
break;
}
// 等待一小段时间显示状态(1-2秒)
await new Promise(resolve => setTimeout(resolve, getRandomDelay(1000, 2000)));
}
// 添加随机延迟避免被反爬
function getRandomDelay(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 在获取详情前添加延迟
const delay = getRandomDelay(3000, 7000);
await new Promise(resolve => setTimeout(resolve, delay));
// 平滑滚动加载
async function smoothScroll(distance, steps = 10) {
const stepDistance = distance / steps;
for (let i = 0; i < steps; i++) {
window.scrollBy(0, stepDistance);
await new Promise(resolve => setTimeout(resolve, 50));
}
提高稳定性
实际使用中发现了不少边界情况:
- 网络不稳定时可能断掉,设置超时和重试,处理机制如下:
// 在getNoteDetails函数中设置超时和重试机制
async function getNoteDetails(noteUrl) {
try {
// 设置15秒超时
const timeout = 15000;
// 使用Promise.race处理超时情况
const pageLoaded = await Promise.race([
new Promise(resolve => {
const checkLoaded = setInterval(() => {
// 检查页面加载状态
}, 100);
}),
new Promise(resolve => setTimeout(() => resolve(false), timeout))
]);
// 如果加载失败,返回错误状态
if (!pageLoaded) {
return {
status: 'error',
message: '页面加载超时或窗口已关闭',
content: null,
comments: []
};
}
} catch (err) {
console.error('获取笔记详情时出错:', err);
return {
status: 'error',
message: err.message || '获取笔记详情时出错',
content: null,
comments: []
};
}
}
- 有些笔记格式特殊,根据链接格式差异,使用正则表达式进行兼容。
async function extractNoteInfo(note, searchKeyword, collectDetails) {
try {
// 使用多个选择器适配不同格式
const title = note.querySelector('span[data-v-51ec0135], div.title, div.content')?.innerText.trim() || '';
// 处理不同类型的链接格式
let link = '';
const coverLink = note.querySelector('a.cover.mask.ld[target="\_self"]');
if (coverLink) {
const href = coverLink.getAttribute('href');
if (href) {
link = href.startsWith('http') ? href : `https://www.xiaohongshu.com${href}`;
}
}
} catch (err) {
console.error('提取笔记信息时出错:', err);
return {};
}
}
- 页面结构偶尔会变,使用了更多可能的容器选择器、笔记选择器,并且同时验证笔记元素的有效性。
async function getAllNotes() {
// 使用多个可能的容器选择器
const containerSelectors = [
'div.search-content',
'div.feeds-page',
'div[role="feed"]',
'div.web-feed'
];
// 尝试多个可能的笔记选择器
const selectors = [
'div.note-item',
'div[data-v-a264b01a]',
'div[role="listitem"]',
'div.search-container div.note-container',
'div[data-testid="note-item"]',
'div[data-testid="search-note-item"]'
];
// 验证笔记元素的有效性
const validNotes = notes.filter((note, index) => {
try {
const hasTitle = note.querySelector('span[data-v-51ec0135], div.title, div.content');
const hasLink = note.querySelector('a[href*="/explore/"], a[href*="/discovery/"]');
const hasAuthor = note.querySelector('a.author, div.author, span.name');
return hasTitle || hasLink || hasAuthor;
} catch (err) {
console.error(`验证第 ${index + 1} 个笔记元素时出错:`, err);
return false;
}
});
}
三、怎么上手使用?
如果你也想试试这个工具,以下是详细的上手指南:
3.1 准备工作
参考这篇文章的指引,先装个油猴插件,把脚本导进去
https://mp.weixin.qq.com/s/4hADaRw3FcY16YBE7NptFg
3.2 实际操作
具体使用很简单:
设置参数
- 搜索你感兴趣的关键词
- 设置采集条件
- 配置采集几页
然后,点击开始就行,等它自动完成。完成后会提醒。
在浏览器的下载区,就能看到采集好的JSON文件。
四、未来计划
工具目前只是第一版,我后面还想加这些功能:
采集更多数据维度
- 把图片也保存下来,加入用户画像分析,支持其他内容平台
AI智能分析
-
自动找出热点,预测内容趋势,生成AI智能分析报告
说实话,这次和Cursor配合开发的经历让我对编程的未来有了新的认识。编程不是程序员的专属技能,现在看来,借助它的帮助,很多人都能参与到技术创造中来。
如果你对文章内容感兴趣,欢迎在评论区交流。后面我还会分享更多AI开发和数据应用的实战经验,我们下期见!