发现身边大部分的朋友,都把小红书作为核心的运营阵地,而低粉爆文的挖掘,肯定是大家运营小红书项目必不可少的日常工作之一。
今天就给大家分享一个基于n8n工作流的小红书低粉爆文挖掘助手,通过输入你的挖掘要求:关键词、粉丝数要求、评论数要求、收藏数要求、点赞数要求、发布周期要求 这个工作流就会帮助你挖掘出符合要求的文章,并记录在飞书表格,供你查阅。
下图是整个工作流的概览:
这是抓取成功后,飞书表格的低粉爆文的笔记数据
好了,下面开始正式分享具体的搭建方案和思路。如上图所示,我分为五大板块,每个版块分开进行讲解:
板块一:从表格获取采集需求
这个板块很简单,主要的作用就是从飞书表格的监控要求明细表中,读取我们要搜集的笔记关键词、以及你对低粉爆文的数据定义。
填写的字段包含如下几个值。
其中,发布周期。需要填写如下4个选项(本项目调用的api规定,需要回传这几个值
具体节点说明:
起始节点
这个起始节点,大家正式运用时,可以改成Schedule Trigger节点,设定每天定时启动工作流,自动给你们抓取目标低粉爆文。
因为是测试,所以我就用了这个最普通的起始节点
飞书节点
节点作用:将要筛选的笔记的相关要求提取出来,一方面将关键词、发布时间端提取出来,供后续的数据抓取节点根据要求,抓取笔记数据;另一方面,抓取你要求的满足低粉爆文笔记的点赞数、评论数、收藏数、粉丝数,后续进行过比对,看是抓取到的否满足低粉爆文的要求。
飞书表格节点。如果之前没有安装,需要先前往社区,搜索feishu,进行安装。
我之前的文章有详细截图和指导,如果不了解这个节点的,可以翻看我之前的文章了解。
Credential to connect with、多维表格token、多维表格id,这三个字段,上面的文章,会告诉你怎么填。 请求体json如下: 名称和我们监控要求明细表的字段名一一对应
{"field_names": ["key_word","filter_note_time","fans_count","comment_count","like_count","collect_count",]}
Split Out节点
如果你在监控要求明细表中,填写的笔记需求在两行以上,这个节点就起作用了。 它会对监控要求明细表中每行的数据进行切分,每一行形成独立的数组,供后续循环节点,根据每一行的摘取需求,进行笔记数据抓取。
LOOP循环节点
板块二:根据采集需求,采集到对应关键词的大量笔记数据。
HTTP Request节点
HTTP Request节点
作用是抓取目标笔记数据的第一页数据
我调用的是这个网站的api(https://api.tikhub.io/),请求一次api大概0.01美金,实现对小红书笔记数据的抓取。大家有其他抓取小红书笔记数据的api,可以替换。我目前没有找到更便宜的api了,所以只能用这个(apify网站有类似红书节点,但是价格是这个几倍。配置会更简单。我们这个节点便宜,但配置复杂。有钱人可自己前往查阅)。 需要先登录,充值5美金。 充值流程:前往https://www.tikhub.io/,进行登录
充值完成后,按如下配置填写相关参数:
method:get
URL:https://api.tikhub.io/api/v1/xiaohongshu/app/search_notes
Send query parameters:选中
Query Parameters
name:keyword
value:{{ $json.fields.key_word[0].text }}
name:filter_note_time
value:{{ $json.fields.filter_note_time }}
name:sort_type
value:time_descending
name:page
value:1
——page这个字段,要解释下。这里的意思,从第几页开始抓取。name:filter_note_type
value:不限
最后的herder parameters
name:Authorization
value:Bearer ××××××××××××××××××××××××
××××××就是你的api,充值后可以获取。
Edit Fields节点
需要设置sid、qid这两个参数。这是api规定的,需要传递给后续节点,才能抓取第二页往后的数据。
一两句话解释不清,想要深究的朋友,自行查阅接口文档:https://api.tikhub.io/#/Xiaohongshu-App-API 参数填写:
{{ $node["采集目标数据"].json.sessionId?? $node["采集目标数据"].json.session_id?? $node["采集目标数据"].json.data?.sessionId?? $node["采集目标数据"].json.data?.session_id }}
qid
{{ $node["采集目标数据"].json.searchId?? $node["采集目标数据"].json.search_id?? $node["采集目标数据"].json.data?.searchId?? $node["采集目标数据"].json.data?.search_id }}
maxPage:2
这个是最大翻页页数的意思,可以自行更改。填写数值越大,抓取的笔记数量越多
code节点
规整数据,以便后面后一个节点能顺利从api获取更多的数据
表达式填写如下:
const N = Number($json.maxPage ?? 1);const sid = $json.sid;const qid = $json.qid;const out = [];for (let p = 2; p <= N; p++) {out.push({ json: { page: p, sid, qid } });}return out;
HTTP Request节点
抓取目标笔记的第2--N页数据:
参数填写如下:
method:get
URL:https://api.tikhub.io/api/v1/xiaohongshu/app/search_notes Send query parameters:选中
Query Parameters
name:page
value:{{ $json.page }}
name:search_id
value:{{ $json.qid }}
name:session_id
value:{{ $json.sid }}
name:keyword
value:{{ $('获取采集要求').item.json.data.items[0].fields.key_word[0].text }}
name:filter_note_time
value:{{ $('获取采集要求').item.json.data.items[0].fields.filter_note_time }}
name:sort_type
value:time_descending
name:filter_note_type
value:不限
最后的herder parameters
name:Authorization
value:Bearer ××××××××××××××××××××××××
和上一个HTTP Request节点,填写一致
merge节点
将两个HTTP Request节点获取的数据汇总在一起
Split Out节点
将之前节点的数据(两大块数组格式),拆分成独立的item(每一条item对应的就是一条独立的笔记),以便给后续的节点,根据每条独立的笔记,抓取粉丝数(这是节点的要求,只能通过这种方式,抓取粉丝)。
Fields To Split Out : data.data.items
If节点
筛选出不符合要求的笔记数据
左侧填写:{{ $json.model_type }}
中间选择:is equal to
右侧:note
板块三:筛选以留下我们需要的笔记数据,包括标题、正文、粉丝数、点赞数、评论数、发布时间等等核心数据
Edit Fields节点
之前HTTP Request获取的数据非常多,很多都不需要的。通过这个节点,选出我们需要的值:
大部分字段,可以从左侧直接拖拽,少部分需要按下方更改,以直接复制填写:
note_id:{{$json.note.id}}
title:{{$json.note.title ?? $json.note.display_title ?? ""}}
content:{{$json.note.desc ?? ""}} comment_count:{{ Number($json.note.comments_count ?? 0) }}
collect_count:{{ Number($json.note.collected_count ?? 0) }} note_link:{{ "https://www.xiaohongshu.com/explore/" + $json.note.id }}
publish_time:
{{
(() => {
const tsSec = Number($json.note?.timestamp || 0); // 秒
const date = new Date(tsSec * 1000);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = date.getHours();
const minutes = date.getMinutes();
const seconds = date.getSeconds();
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
})()
}}
account_name:{{ $json.note.user.nickname }}
account_id:{{ $json.note.user.red_id }}
note_type:{{ $json.note.widgets_context && $json.note.widgets_context.indexOf('"video":true') !== -1 ? 'video' : ($json.note.type || 'normal') }}
URL:{{ "https://www.xiaohongshu.com/explore/" + $json.note.id }}
liked_count:{{ $json.note.liked_count }}
user_id:{{$json.note.user.userid}}
LOOP循环节点
我们还需要user_id,通过获取粉丝数。 因为我们抓取的笔记数据量会很大,如果一次性调用api,会报错,导致很多笔记对应的账号粉丝数无法返回。因此设定一个循环节点,控制每次获取的数量。我这里设置了10。这样,就能保证api能正常返回粉丝数了。
wait节点
也是为了不在短时间对让api发送过多请求导致报错,所以添加了30秒的延迟。
HTTP Request节点
因为api缘故,这个api需要拿到user_id后,才能获取粉丝数。
所以要到这里才能获取到笔记对应账号的粉丝数(不同的api,要求不一致。我仅以本api为例演示讲解)。
method:get
url:https://api.tikhub.io/api/v1/xiaohongshu/app/get_user_info
Query parameters
name:user_id
Value:{{$json.user_id}}
Header parameters——这个值和之前的HTTP Request填的一致。
Edit Fields节点:
这第三个HTTP Request节点,返回的数值也非常多,我们只取我们需要的粉丝数

merge节点
将两路数据,合并。
注意,mode选combine;combine by,选position一定要注意,要改,不是默认的选项。

Edit Fields节点:最后将所有有用的数据再汇总一遍(其实相较于之前的Edit Fields,就是多加了一个粉丝数fans_count)
大家对照着截图,命名保持一致即可。
板块四:获取低粉爆文表中已有的笔记数据,给最后一个节点判定当前搜集的笔记是否有重复
飞书节点
这个节点,是为了取出已有的笔记的note_id,以供后续与这次运行工作流,抓取到的新的笔记数据的note_id进行比对,以此判断是否重复
请求体json:
{"field_names": ["note_id"]}
板块五:判断笔记是否符合低粉爆文的数据指标,符合的填入飞书表格,不符合的过滤
merge节点
将已有的笔记的note_id和本轮运转抓取到的所有笔记数据,汇聚在一起,供后面的过滤节点判断,过滤掉不符合要求的数据。
filter节点
按照我们表格中设定的要求,过滤掉不符合要求的笔记数据。
大家按照以下截图,并把对应的数据拖动到对应位置即可。
第一条:通过note_id,过滤掉重复的笔记
第二条:笔记的粉丝数,要少于数据表一:监控要求明细的粉丝数
第三条:笔记的评论数,要多于数据表一:监控要求明细的评论数
第四条:笔记的收藏数,要多于数据表一:监控要求明细的收藏数
第五条:笔记的点赞数,要多于数据表一:监控要求明细的点赞数数
飞书节点
将最终符合要求的数据,记录进数据表二:低粉爆文笔记。
下方的token和id,为数据表二:低粉爆文笔记对应的token和id
请求体json:
{"fields": {"note_id": "{{ String($json.note_id) }}","title": "{{ String($json.title) }}","content": "{{ String($json.content) }}","fans_count": "{{ String($json.fans_count ?? '') }}","comment_count": "{{ String($json.comment_count ?? '') }}","collect_count": "{{ String($json.collect_count ?? '') }}","publish_time": "{{ String($json.publish_time ?? '') }}","URL": {"link": "{{ String($json.URL) }}","text": "{{ String($json.title ?? $json.note_id ?? '打开链接') }}"},"note_type": "{{ String($json.note_type ?? '') }}","account_name": "{{ String($json.account_name ?? '') }}","account_id": "{{ String($json.account_id ?? '') }}","like_count": "{{ String($json.liked_count ?? '') }}"}}

