某生活方式社区笔记爬虫:从0到1爬取种草笔记,分析热门品类趋势
引言
在内容电商蓬勃发展的今天,某生活方式社区已成为国内最具影响力的“种草”平台之一。其用户生成的笔记内容——从美妆测评、旅行攻略到家居好物、穿搭分享——蕴含着巨大的商业洞察价值。对于品牌方、市场研究者和内容创作者而言,理解热门品类的趋势走向,几乎等同于掌握了流量的密码。
比如,你想知道“冲锋衣”这个品类在平台上近三个月的热度变化,或者想分析“露营装备”相关笔记的互动规律。手动去一条条翻看显然不现实。这时候,自动化采集笔记数据就成了刚需。
然而,爬取该平台的笔记数据难度极高。其Web端所有核心数据(如搜索结果、评论列表)均通过加密API返回,需逆向还原x-s/x-t动态签名逻辑,否则将返回401或空响应体。签名密钥每5分钟轮换,必须实时提取JS上下文中的加密函数。更麻烦的是,它不封IP——它悄悄把你的设备ID加入灰名单,后续所有请求的响应体里都混入不可见的干扰字符,导致JSON解析直接报错。
本文将从零开始,系统介绍如何爬取该平台的笔记数据,并以此为基础分析热门品类趋势。文章将涵盖反爬机制剖析、采集方案选型、代码实现以及数据应用。

一、为什么某平台笔记爬取如此困难?
在动手写代码之前,先搞清楚一个问题:这个平台到底是如何识别爬虫的?
1.1 设备指纹:三重嵌套的隐性绑定
该平台的设备指纹不是简单拼接IMEI、Android ID和MAC地址,而是采用三层嵌套结构:
-
基础层(静态) :device_id由特定文件内容决定,算法为MD5(IMEI + Build.SERIAL + Build.BOARD + Build.MANUFACTURER).substring(0,16)。Android 10+环境下Build.SERIAL已被废弃,客户端会fallback到反射调用,若失败则用随机UUID替代——这意味着模拟器环境必须手动注入合法值,否则device_id每次重启都会变化。
-
行为层(半动态) :x-b3-traceid并非全随机。通过抓包对比真实App请求发现,其前8位固定为device_id的MD5前8位,后8位为当前毫秒时间戳的十六进制表示。这使得服务端可瞬间关联设备与请求时间窗口。
-
环境层(强动态) :x-salt字段每30分钟刷新一次,值为SHA256(device_id + current_timestamp/1800 + 固定盐值)。同一设备在30分钟内所有请求的salt完全相同,但跨块时必须更新。
1.2 Cookie、请求头与X-S签名强绑定
该平台Web端接口的风控机制核心在于:Cookie、Request Header与X-S签名强绑定。简单的签名生成往往无法通过校验,因为服务端会校验签名的生成环境(Cookie、Canvas指纹等)是否与请求发起者一致。
签名(x-sign)不是对URL或Body的简单哈希,而是对标准化请求上下文的HMAC-SHA256计算。
1.3 行为分析与风控联动
该平台的风控系统不仅检测单次请求的合法性,还会分析用户行为的连贯性。它会检测鼠标移动轨迹、点击延迟、滚动速度等行为特征是否符合真人操作。甚至在App端,它融合了设备指纹、行为轨迹、动态密钥、多层签名与实时风控的完整体系。
现实情况是:即使配置了所有反检测措施,该平台目前的风控依然非常强,这是一个持续的对抗过程,没有完全可靠的程序化解决方案。
二、采集方案选型:两条路怎么走?
面对如此严密的防护体系,目前主流的采集方案有两条路径。
2.1 路径一:浏览器自动化(Playwright方案)
核心思路:用真实的浏览器模拟真人操作,让浏览器自己完成所有签名计算和加密请求,然后通过拦截网络响应来获取数据。
推荐工具:Playwright + playwright-stealth + browserforge
目前社区已经有成熟的实现方案。例如,有开源项目基于Playwright实现了具备双层反检测能力(playwright-stealth环境级 + browserforge指纹级)的采集工具,支持关键词搜索采集(瀑布流自动滚动加载)、笔记详情采集(标题、正文、互动数据、标签、图片/视频)以及评论采集。登录状态可持久化(扫码登录后自动保存,下次启动免登录)。
另一方案则通过操控真实浏览器绕过反爬检测,扫码登录一次后session持久化,所有内容获取通过浏览器内建签名(window._webmsxyw)透明完成,无需逆向工程。
优点:
-
无需逆向签名算法,维护成本相对较低
-
签名算法更新时不受影响
-
真实浏览器环境,行为更接近真人
缺点:
-
效率较低,每个请求需启动浏览器实例
-
资源消耗大(内存、CPU)
-
大规模并发困难
2.2 路径二:API逆向(纯算法签名方案)
核心思路:逆向出x-s/x-t签名生成算法,在代码中动态计算合法的请求头,直接调用API接口。
该平台Web端所有核心数据均通过加密API返回,需逆向还原x-s/x-t动态签名逻辑。签名密钥每5分钟轮换,必须实时提取JS上下文中的加密函数。
社区已有采用Pure Algorithm(纯算法签名) 策略的项目:使用Docker容器化的undetected-chromedriver获取合法的访客Cookie;纯Rust完成QR码创建、轮询、登录确认;Python Agent提供签名算法服务。浏览器仅在首次获取访客Cookie和登录同步时运行,日常请求完全由后端处理。
优点:
-
效率极高,无需加载浏览器
-
可大规模并发采集
-
资源消耗低
缺点:
-
逆向门槛高,需要逆向工程能力
-
签名算法更新时需重新逆向
-
设备指纹模拟难度大
2.3 选型建议
对于大多数开发者而言,路径一(Playwright浏览器自动化)是更务实的选择。原因有三:
-
无需逆向工程:签名算法由浏览器原生完成,平台更新时不受影响
-
社区方案成熟:已有多个开源项目可供参考和复用
-
维护成本可控:主要工作是应对风控策略调整,而非逆向算法
本文后续代码将基于Playwright方案展开。
三、代码实现:从登录到采集
3.1 环境准备
pip install playwright pandas openpyxl
playwright install chromium
3.2 登录与Session持久化
from playwright.sync_api import sync_playwright
import json
import time
class XHSScraper:
def __init__(self, headless=False, use_proxy=False):
self.headless = headless
self.use_proxy = use_proxy
self.browser = None
self.context = None
self.page = None
# 站大爷隧道代理配置
if use_proxy:
self.proxy_config = {
"server": "http://隧道代理地址:端口"
}
else:
self.proxy_config = None
def login(self, session_dir="browser_data"):
"""扫码登录并持久化session"""
with sync_playwright() as p:
# 启动浏览器(非无头模式更接近真实用户)
browser = p.chromium.launch(
headless=self.headless,
proxy=self.proxy_config
)
# 创建上下文,加载已保存的session
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0",
viewport={"width": 1440, "height": 900},
locale="zh-CN"
)
# 注入反检测脚本
context.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// 隐藏自动化特征
window.chrome = { runtime: {} };
""")
page = context.new_page()
page.goto("https://www.xiaohongshu.com")
print("请用手机扫码登录...")
# 等待用户手动扫码登录
page.wait_for_url("https://www.xiaohongshu.com/explore*", timeout=60000)
# 保存session状态
context.storage_state(path=f"{session_dir}/state.json")
print(f"登录成功,session已保存到 {session_dir}/state.json")
browser.close()
def load_session(self, session_dir="browser_data"):
"""加载已保存的session"""
with sync_playwright() as p:
self.browser = p.chromium.launch(
headless=self.headless,
proxy=self.proxy_config
)
self.context = self.browser.new_context(
storage_state=f"{session_dir}/state.json",
viewport={"width": 1440, "height": 900}
)
self.page = self.context.new_page()
return self.page
def close(self):
if self.browser:
self.browser.close()
3.3 搜索并采集笔记
def search_notes(self, keyword, max_count=50):
"""搜索关键词并采集笔记"""
if not self.page:
self.load_session()
# 访问搜索页面
search_url = f"https://www.xiaohongshu.com/search?keyword={keyword}"
self.page.goto(search_url)
time.sleep(3)
notes = []
last_height = 0
while len(notes) < max_count:
# 滚动加载更多
self.page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
# 提取笔记卡片
cards = self.page.query_selector_all("section.note-item, div.note-item")
for card in cards:
try:
title = card.query_selector("a.title, .title").inner_text() if card.query_selector("a.title, .title") else ""
link = card.query_selector("a").get_attribute("href") if card.query_selector("a") else ""
note_id = link.split("/")[-1] if link else ""
# 提取互动数据
like_text = card.query_selector(".like-wrapper .count, .like-count").inner_text() if card.query_selector(".like-wrapper .count, .like-count") else "0"
notes.append({
"note_id": note_id,
"title": title,
"link": f"https://www.xiaohongshu.com{link}" if link else "",
"likes": self._parse_count(like_text)
})
except Exception as e:
continue
# 检查是否到达底部
new_height = self.page.evaluate("document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
# 随机延迟
time.sleep(2)
return notes[:max_count]
def get_note_detail(self, note_url):
"""获取笔记详情"""
if not self.page:
self.load_session()
self.page.goto(note_url)
time.sleep(3)
# 拦截响应,获取API数据
detail_data = {}
def handle_response(response):
if "/api/sns/web/v1/feed" in response.url or "note_detail" in response.url:
try:
data = response.json()
detail_data.update(data)
except:
pass
self.page.on("response", handle_response)
self.page.reload()
time.sleep(2)
# 解析页面提取信息
try:
title = self.page.query_selector(".title, .note-title").inner_text() if self.page.query_selector(".title, .note-title") else ""
content = self.page.query_selector(".content, .note-content").inner_text() if self.page.query_selector(".content, .note-content") else ""
author = self.page.query_selector(".author-name").inner_text() if self.page.query_selector(".author-name") else ""
return {
"title": title,
"content": content,
"author": author,
"raw_data": detail_data
}
except Exception as e:
return {"error": str(e)}
3.4 数据采集的完整流程
# 使用示例
if __name__ == "__main__":
scraper = XHSScraper(headless=False, use_proxy=True)
# 首次使用:扫码登录
# scraper.login()
# 后续使用:加载已保存的session
scraper.load_session()
# 搜索多个关键词
keywords = ["冲锋衣", "露营装备", "防晒衣", "户外徒步"]
all_notes = []
for keyword in keywords:
print(f"正在搜索: {keyword}")
notes = scraper.search_notes(keyword, max_count=30)
for note in notes:
note["keyword"] = keyword
all_notes.extend(notes)
time.sleep(5) # 关键词之间间隔
# 保存数据
import pandas as pd
df = pd.DataFrame(all_notes)
df.to_csv("xiaohongshu_notes.csv", index=False, encoding="utf-8-sig")
print(f"共采集 {len(all_notes)} 条笔记")
scraper.close()
四、隧道代理:突破IP封禁的关键
4.1 为什么需要隧道代理?
即使你完美实现了浏览器自动化,当采集规模达到一定量级时,IP封禁依然不可避免。该平台对IP的检测极为严格,单一IP高频请求、多账号同IP、IP段集中,轻则限流、验证码轰炸,重则账号封禁、数据爬取失败。
该平台2026年的风控核心是IP + 设备 + 行为三重校验,对代理IP有明确的硬性要求:
-
高匿名性:必须是高匿代理,普通匿名/透明代理极易触发风控
-
IP纯净度:无历史违规记录、非机房集中IP段,数据中心IP易被标记为机器流量
-
稳定性:24小时持续可用率≥90%
-
地域分散:覆盖全国主要城市,避免同地域集中请求
4.2 隧道代理的工作原理
隧道代理是传统代理的升级方案。你不需要手动维护IP池,只需配置好接入信息。每次发送请求时,隧道代理会自动把流量引导至不同的出口IP。
以站大爷隧道代理为例,实测数据显示:
| 指标 | 实测数据 |
|---|---|
| 初始可用率 | 99.3% |
| 24小时持续可用率 | 99% |
| 晚高峰可用率 | 96.9% |
| 异常响应占比 | 1.8% |
| 平均响应时间 | 65ms |
| 匿名性 | 高匿 |
实测表现显示:几乎不触发验证码,多账号无关联,晚高峰依旧稳定,长期采集几乎零报错。
站大爷隧道代理的核心优势还包括:
-
自动切换无感知:每次请求自动更换出口IP
-
覆盖范围广泛:覆盖全国99%地域
-
主备双隧道:持续更新IP池,稳定性有保障
-
灵活配置:支持精细化的IP轮换周期自定义
4.3 在Playwright中集成隧道代理
from playwright.sync_api import sync_playwright
# 站大爷隧道代理配置
PROXY_CONFIG = {
"server": "http://隧道代理地址:端口"
}
with sync_playwright() as p:
browser = p.chromium.launch(
headless=False,
proxy=PROXY_CONFIG # 所有流量通过隧道代理
)
# 后续正常使用browser...
如果你使用的是requests库进行API调用:
import requests
PROXIES = {
"http": "http://隧道代理地址:端口",
"https": "https://隧道代理地址:端口"
}
def fetch_with_tunnel(url, headers, retry=3):
for i in range(retry):
try:
response = requests.get(
url,
headers=headers,
proxies=PROXIES,
timeout=15
)
if response.status_code == 200:
return response.json()
# 遇到403/429,隧道代理自动切换IP
if response.status_code in [403, 429]:
print(f"请求被拒绝,隧道代理自动切换IP重试...")
continue
except Exception as e:
print(f"请求异常: {e}")
continue
return None
选型建议:如果你是刚做该平台爬虫,建议先用站大爷免费版测通逻辑,正式跑量直接切换付费隧道代理,一步到位少踩坑。
五、从笔记数据到热门品类趋势分析
5.1 数据采集的核心维度
采集到的笔记数据可以从以下几个维度进行分析:
| 数据维度 | 分析价值 |
|---|---|
| 笔记数量 | 反映品类的讨论热度 |
| 互动数据(点赞/收藏/评论) | 衡量内容的用户共鸣度 |
| 发布时间 | 分析趋势的时间变化 |
| 关键词/标签 | 识别细分方向 |
| 作者画像 | 了解内容生产者的特征 |
5.2 趋势分析的方法论
第一步:关键词体系构建
选择目标品类下的核心关键词和长尾关键词。例如“户外”品类可以包含:冲锋衣、徒步鞋、露营装备、登山杖等。
第二步:时间序列采集
定时(如每天)采集各关键词下的笔记数据,构建时间序列。通过观察笔记数量和互动数据的变化,可以识别品类的“爆发期”和“平稳期”。
第三步:品类对比分析
将多个品类的数据进行横向对比,识别增长最快的品类。根据平台数据,2025年热门品类涵盖“冲锋衣、防晒衣、水壶、喂食器、睡袋、护目镜、定位器”等。休闲零食(29.73%)、鲜果(22.26%)、冲饮品(21.23%)也是热门品类。
5.3 数据可视化示例
import pandas as pd
import matplotlib.pyplot as plt
# 加载采集的数据
df = pd.read_csv("xiaohongshu_notes.csv")
# 按关键词统计笔记数量和平均互动
trend = df.groupby('keyword').agg({
'note_id': 'count',
'likes': 'mean'
}).rename(columns={'note_id': '笔记数量', 'likes': '平均点赞'})
# 绘制趋势图
fig, ax1 = plt.subplots()
ax1.bar(trend.index, trend['笔记数量'], color='skyblue')
ax1.set_xlabel('品类')
ax1.set_ylabel('笔记数量', color='skyblue')
ax2 = ax1.twinx()
ax2.plot(trend.index, trend['平均点赞'], color='red', marker='o')
ax2.set_ylabel('平均点赞', color='red')
plt.title('各品类笔记热度对比')
plt.show()
5.4 趋势发现的典型案例
根据平台2025年度报告,“谷子、拼豆、bjd(球形关节玩偶)”等兴趣在2025年强势破圈。三大年轻人兴趣趋势包括:亲手创造一个小世界获得确定性、将万物作为“嘴替”表达情感、走出门在自然中解放天性。
这些趋势的发现,正是建立在大量笔记数据的采集与分析之上。通过爬虫获取的原始数据,经过清洗、聚合、对比,最终转化为可执行的商业洞察。
六、常见问题与避坑指南
6.1 Session过期怎么办?
该平台登录态通常为数天到数周。应对策略:
-
使用
storage_state持久化session,每次启动时加载 -
编写检测脚本,定期检查登录态有效性
-
失效时自动触发重新登录
6.2 遇到验证码怎么处理?
-
关闭无头模式:确保headless=False,无头模式更容易被检测
-
降低采集频率:增加sleep间隔到5-15秒
-
保持浏览器打开:设置不自动关闭浏览器,触发验证码时可以手动完成验证
-
使用真实浏览器连接模式:连接你自己的真实浏览器,复用已有的登录态,避免走自动化流程被检测
6.3 采集不全怎么办?
-
该平台搜索结果的瀑布流加载可能受限于服务端返回的数据量
-
建议按时间分段采集(如按月份拆分)
-
使用多个关键词交叉覆盖同一品类
6.4 签名算法更新怎么办?
如果你选择的是API逆向方案,签名算法更新时需要重新逆向。建议:
-
优先选择Playwright浏览器自动化方案,签名由浏览器原生处理
-
关注开源社区的更新动态
-
建立多套备选方案
七、总结
本文从该生活方式社区的反爬机制入手,系统介绍了爬取笔记数据以分析热门品类趋势的完整方案。核心要点可以概括为:
| 挑战 | 解决方案 |
|---|---|
| 设备指纹检测 | 使用真实浏览器,注入反检测脚本 |
| X-S/X-T动态签名 | Playwright浏览器自动化,签名由浏览器原生生成 |
| Cookie与签名强绑定 | Session持久化,复用登录态 |
| IP频率限制 | 站大爷隧道代理,自动切换IP |
| 数据采集效率 | 关键词搜索 + 瀑布流滚动 + 批量导出 |
| 趋势分析 | 时间序列采集 + 多品类对比 + 可视化 |
技术选型速览:推荐“Playwright浏览器自动化 + Session持久化 + 站大爷隧道代理”的组合方案。该方案无需逆向工程,签名算法更新时不受影响,维护成本相对可控。
该平台的笔记数据是一座尚未被充分开采的金矿。通过合理的采集策略和数据分析方法,我们可以将这座金矿转化为结构化的趋势洞察,为品牌决策、内容创作和市场研究提供坚实的数据基础。
最后需要提醒的是:数据采集行为应当遵循行业规范,控制请求频率以避免对目标服务器造成过载。请遵守目标网站的robots.txt协议及相关法律法规,仅将爬虫技术用于学习和研究目的。希望本文能帮助你在数据分析的道路上迈出坚实的一步。
更多推荐
所有评论(0)