小红书笔记和评论数据自动采集分析全指南:从0到1的AI开发实战

大数据机器学习数据库

解锁小红书搜索、笔记、评论数据的商业价值,新手也能快速上手的自动化采集方案

小红书数据里的商机

每天,小红书上都有无数真实用户在分享他们的体验、吐槽和需求。作为国内最大的生活方式社区,小红书汇集了超过3亿用户,他们在这里寻找种草推荐、分享购物体验、交流生活心得。这些真实的用户声音,背后蕴藏着巨大的商业价值:

小红书上的评论区就像一个聊天群,用户们在这里吐槽产品的不足,分享使用体验,通过这些真实的声音,我们不仅能发现用户的痛点,还能看到市场上还有哪些没被满足的需求。

刷小红书就像是在看一场实时的潮流直播,今天大家在追什么,明天会流行什么,哪些产品突然就火了,这些都能让我们第一时间嗅到市场的风向。

那些点赞收藏超高的笔记,背后都藏着吸引用户的秘密 - 是文案打动了人心,还是找对了目标人群,研究这些成功案例,能帮我们做出更精准的营销决策。

就拿我刚才测试采集的“咖啡机”笔记和用户评论数据来看,至少有这些分析发现:

分析发现一:广东区域的咖啡机可以考虑开发咖啡机防虫配件产品线

  • 蟑螂是南方同学挥之不去的噩梦,南方地区(特别是广东)咖啡机容易吸引蟑螂

picture.image

相关的用户反馈:

picture.image

picture.image

picture.image

分析发现二:咖啡机专用家具系列

咖啡机周边配套家具和装饰需求非常旺盛。很多咖啡机的话题往往带着咖啡机角布置、咖啡家具陈列和展示。

picture.image

picture.image

picture.image

分析发现三:现在的咖啡机市场还处于入门级

推出入门级性价比产品线。

picture.image

picture.image

除了咖啡机制造商和配件等实体供应商,其实,还有这些服务升级方向:

提供咖啡机使用培训,开发配套清洁维护服务,设计整体咖啡角解决方案。

picture.image

picture.image

自媒体内容创作,可以聚焦用户教育方向,制作咖啡知识科普内容,开发咖啡制作教程。分享咖啡角布置灵感。

picture.image

但是,手动收集和分析这些数据是一项耗时耗力的工作。如果能自动化采集这些信息,将为品牌和创业者带来巨大价值。正好最近在尝试用Cursor开发,就想着是不是可以快速搞一个自动化采集方案?

让我分享一下,我是如何在一个下午的时间里,借助Cursor开发出一个小红书数据采集工具的经历。这个过程不仅简单有趣,最后的成果也相当实用。

一、为什么选择Cursor,让AI辅助开发?

1.1 从踩坑到顿悟

半年前,我第一次接触Cursor编程,说实话,最开始也是将信将疑。但经过这段时间的实践,我发现Cursor不仅能帮我解决复杂的编程问题,还能大大提升开发效率。特别是在处理爬虫这类技术性较强的项目时,它的帮助简直是雪中送炭。

众所周知,小红书的技术难度几乎是数据采集的天花板。

  • 搜索结果是动态加载的,得处理下拉刷新

  • 笔记详情页有反爬措施,各种加密参数

  • 评论数据藏得深,还得考虑登录态...

以前遇到这种情况,可能要花好几天去研究文档、测试方案。但现在有了Cursor,很多技术难题都能快速突破。这半年来的开发经验告诉我,与其纠结于技术细节,不如先和它讨论一下解决方案。

1.2 开发实录:轻车熟路的配合

经过半年的磨合,我和Cursor配合已经很有默契了。这次开发采用了我最常用的节奏。而且是在我之前做的油猴插件的基础上,再让Cursor开发的。

先说需求,后提难点

比如我是这么说的:"我想增加一个功能,每次在采集笔记的标题、作者等信息后,点开笔记,采集笔记详情和笔记下的用户评论内容。你明白我的需求吗?是否可行?请你思考该如何实现。这个是点击笔记后,展开的内容地址:..."

picture.image

Cursor马上就理解了我的意思,给出了具体的实现思路:用油猴脚本实现,监听页面滚动,处理动态加载等等。

分步骤实现

  • 先搞定基础采集
  • 再处理下拉加载
  • 最后优化体验

每一步我都说出我的具体需求,Cursor就会给出相应的代码和解释。遇到问题,我就描述现象,它就能给出解决方案。

不断优化

开发过程中遇到了不少小问题:

  • 搜索关键词参数莫名其妙变成乱码

picture.image

  • 笔记列表丢失,导致采集不全

picture.image

  • 采集太快容易被限制...

picture.image

但每次我把问题一说,Cursor都能给出合理的解决方案。比如通过添加随机延迟、优化滚动策略等方式,一步步把这些问题都解决了。

二、这个工具是怎么实现的?

2.1 核心功能

经过一番折腾,最终实现了这些功能:

搜索结果采集
  • 输入关键词就能自动采集

picture.image

  • 支持自定义采集页数

picture.image

  • 然后,再一篇一篇自动采集,数据一个都不落下
笔记详情获取
  • 自动打开笔记看全文

picture.image

  • 评论也能一起保存,数据格式清晰规整

picture.image

导出方便
  • 直接导出成JSON,需要啥字段都行,原始数据都保留着。JSON数据结构完美解决了一条笔记下多条评论内容。且评论还需要记录正文、时间、点赞数、收藏数(方便分析用户的认可度)。比如这款咖啡机的配件米奇头,得到了好多评论区用户的反馈。

picture.image

  
{  
          "user": "Carol",  
          "content": "用款咖啡机,用款米奇哈哈",  
          "time": "2024-07-21",  
          "likes": "33",  
          "replies": "25"  
        },,  
        {  
          "user": "虾皮~59611940",  
          "content": "同款米奇",  
          "time": "2024-07-31",  
          "likes": "34",  
          "replies": "17"  
        },

采集结果是一个JSON文件:

picture.image

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 实际操作

具体使用很简单:

设置参数

  • 搜索你感兴趣的关键词

picture.image

  • 设置采集条件

picture.image

  • 配置采集几页

picture.image

然后,点击开始就行,等它自动完成。完成后会提醒。

picture.image

在浏览器的下载区,就能看到采集好的JSON文件。

picture.image

四、未来计划

工具目前只是第一版,我后面还想加这些功能:

采集更多数据维度

  • 把图片也保存下来,加入用户画像分析,支持其他内容平台

AI智能分析

  • 自动找出热点,预测内容趋势,生成AI智能分析报告

说实话,这次和Cursor配合开发的经历让我对编程的未来有了新的认识。编程不是程序员的专属技能,现在看来,借助它的帮助,很多人都能参与到技术创造中来。

如果你对文章内容感兴趣,欢迎在评论区交流。后面我还会分享更多AI开发和数据应用的实战经验,我们下期见!

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
大规模高性能计算集群优化实践
随着机器学习的发展,数据量和训练模型都有越来越大的趋势,这对基础设施有了更高的要求,包括硬件、网络架构等。本次分享主要介绍火山引擎支撑大规模高性能计算集群的架构和优化实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论