Python 爬虫实战:抓取小红书穿搭笔记数据

前言

小红书作为国内领先的生活方式分享平台,穿搭笔记汇聚了海量的时尚趋势、单品推荐、搭配技巧等核心信息,是时尚行业分析、消费趋势研究的重要数据源。小红书采用强反爬机制(如登录验证、动态 Cookie、签名参数、图片懒加载),且核心数据完全通过 AJAX 接口动态加载,爬虫开发需兼顾接口分析、登录态维护、反爬规避等多维度能力。本文将系统讲解基于requests+jsonpath的小红书穿搭笔记数据抓取方案,从接口分析、参数构造到数据解析,实现完整的实战落地。

摘要

本文以小红书穿搭笔记数据抓取为核心场景,深度解析小红书移动端 API 接口的请求逻辑,通过模拟登录获取有效 Cookie、构造合法请求参数、解析 JSON 响应数据,实现穿搭笔记的标题、点赞数、收藏数、评论数、正文内容、标签等核心信息的抓取。实战目标网页示例:小红书穿搭笔记示例页(可替换为任意小红书穿搭笔记 URL)。

一、爬虫开发前置知识

1.1 核心原理

小红书数据加载逻辑:

  • 网页端 / 移动端的笔记数据均通过加密的 AJAX 接口返回(JSON 格式),无静态 HTML 数据;
  • 接口请求需携带核心参数:cookie(登录态)、x-s(签名参数)、x-t(时间戳)、referer(来源);
  • 反爬机制包括:登录验证(未登录仅能获取少量数据)、签名参数校验、IP 频率限制、设备指纹验证、请求头校验。

核心解决思路:

  1. 模拟小红书登录(手动 / 自动),获取有效登录 Cookie;
  2. 分析穿搭笔记列表 / 详情接口的参数构造规则;
  3. 构造符合小红书规范的请求头和参数,调用 API 接口;
  4. 解析 JSON 响应数据,提取核心字段并结构化存储。

1.2 环境依赖

需安装的 Python 库及安装命令如下:

bash

运行

pip install requests jsonpath-python pandas fake-useragent pycryptodome 
库名称核心作用
requests发送 HTTP 请求,调用小红书 API 接口
jsonpath-python解析嵌套 JSON 数据,提取目标字段
pandas笔记数据结构化存储与导出
fake-useragent生成随机 User-Agent,规避基础反爬
pycryptodome(可选)处理小红书接口签名加密(进阶)

二、实战开发流程

2.1 目标分析

以小红书穿搭笔记为例,需抓取的核心字段:

字段名称字段说明数据类型
note_id笔记 ID(唯一标识)字符串
note_title笔记标题字符串
note_content笔记正文内容字符串
author_name作者昵称字符串
like_count点赞数整数
collect_count收藏数整数
comment_count评论数整数
tag_list笔记标签(如 #早春穿搭 #通勤穿搭)字符串
publish_time发布时间字符串
note_url笔记链接字符串

2.2 核心代码实现

python

运行

import requests import json import time import random import pandas as pd from fake_useragent import UserAgent from jsonpath import jsonpath from urllib.parse import urlencode class XiaoHongShuCrawler: def __init__(self, cookie): """ 初始化爬虫 :param cookie: 小红书登录后的Cookie字符串 """ # 初始化请求头 self.ua = UserAgent() self.headers = { 'User-Agent': self.ua.random, 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Referer': 'https://www.xiaohongshu.com/', 'Cookie': cookie, 'Origin': 'https://www.xiaohongshu.com', 'X-Requested-With': 'XMLHttpRequest', 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin' } # 存储所有笔记数据的列表 self.all_note_data = [] # 小红书API基础URL self.base_api_url = 'https://edith.xiaohongshu.com/api/sns/web/v1/feed' def get_note_detail(self, note_id): """ 获取单篇笔记的详细数据 :param note_id: 笔记ID :return: 笔记数据字典/None """ try: # 构造笔记详情接口参数 params = { 'note_id': note_id, 'source': 'web', 'timestamp': int(time.time() * 1000) } # 随机延迟(3-8秒),规避频率限制 time.sleep(random.uniform(3, 8)) # 发送GET请求 response = requests.get( url=f'{self.base_api_url}/detail?{urlencode(params)}', headers=self.headers, timeout=20 ) response.raise_for_status() json_data = response.json() # 验证接口返回状态 if json_data.get('success') is not True: print(f"笔记{note_id}接口返回失败:{json_data.get('msg', '未知错误')}") return None # 提取核心数据 note_data = {} # 基础信息 note_data['note_id'] = note_id note_data['note_title'] = jsonpath(json_data, '$..title')[0] if jsonpath(json_data, '$..title') else '无标题' note_data['note_content'] = jsonpath(json_data, '$..content')[0] if jsonpath(json_data, '$..content') else '无正文' note_data['author_name'] = jsonpath(json_data, '$..nickname')[0] if jsonpath(json_data, '$..nickname') else '未知作者' # 互动数据 note_data['like_count'] = int(jsonpath(json_data, '$..like_count')[0]) if jsonpath(json_data, '$..like_count') else 0 note_data['collect_count'] = int(jsonpath(json_data, '$..collect_count')[0]) if jsonpath(json_data, '$..collect_count') else 0 note_data['comment_count'] = int(jsonpath(json_data, '$..comment_count')[0]) if jsonpath(json_data, '$..comment_count') else 0 # 标签处理(拼接所有标签) tags = jsonpath(json_data, '$..tags[*].name') or [] note_data['tag_list'] = ' | '.join(tags) if tags else '无标签' # 发布时间(转换为可读格式) publish_ts = jsonpath(json_data, '$..create_time')[0] if jsonpath(json_data, '$..create_time') else 0 note_data['publish_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(publish_ts)) if publish_ts else '未知时间' # 笔记链接 note_data['note_url'] = f'https://www.xiaohongshu.com/explore/{note_id}' print(f"成功抓取笔记【{note_data['note_title']}】(ID:{note_id})") return note_data except requests.exceptions.RequestException as e: print(f"笔记{note_id}请求失败:{e}") return None except Exception as e: print(f"笔记{note_id}解析失败:{e}") return None def crawl_note_list(self, keyword='穿搭', page_num=3, page_size=20): """ 根据关键词抓取穿搭笔记列表 :param keyword: 搜索关键词(默认穿搭) :param page_num: 抓取页数 :param page_size: 每页笔记数 """ try: for page in range(1, page_num + 1): # 构造搜索接口参数 params = { 'keyword': keyword, 'page': page, 'page_size': page_size, 'sort': 'popular', # 按热度排序:popular-最热,latest-最新 'timestamp': int(time.time() * 1000) } # 随机延迟(5-10秒) time.sleep(random.uniform(5, 10)) # 发送搜索请求 response = requests.get( url=f'{self.base_api_url}/search?{urlencode(params)}', headers=self.headers, timeout=20 ) response.raise_for_status() json_data = response.json() if json_data.get('success') is not True: print(f"第{page}页搜索失败:{json_data.get('msg', '未知错误')}") continue # 提取笔记ID列表 note_ids = jsonpath(json_data, '$..note_id') or [] if not note_ids: print(f"第{page}页未获取到笔记ID,结束抓取") break print(f"第{page}页获取到{len(note_ids)}篇笔记ID") # 逐个抓取笔记详情 for note_id in note_ids: note_data = self.get_note_detail(note_id) if note_data: self.all_note_data.append(note_data) except Exception as e: print(f"搜索列表抓取失败:{e}") def save_data(self, save_path='xiaohongshu_fashion_notes.csv'): """ 保存笔记数据到CSV文件 :param save_path: 保存路径 """ if not self.all_note_data: print("无有效笔记数据可保存") return # 转换为DataFrame并去重(按note_id) df = pd.DataFrame(self.all_note_data) df = df.drop_duplicates(subset=['note_id'], keep='last') # 处理正文内容换行符(避免CSV格式错乱) df['note_content'] = df['note_content'].str.replace('\n', ' ') # 保存CSV(utf-8-sig解决Excel中文乱码) df.to_csv(save_path, index=False, encoding='utf-8-sig') print(f"小红书穿搭笔记数据已保存至:{save_path}") print(f"共抓取{len(df)}篇有效笔记") return df # 主程序执行 if __name__ == '__main__': # ==================== 重要配置 ==================== # 替换为你自己的小红书登录Cookie(获取方式见下文) XHS_COOKIE = '你的小红书登录Cookie字符串' # ================================================== # 实例化爬虫对象 crawler = XiaoHongShuCrawler(cookie=XHS_COOKIE) # 抓取关键词为“穿搭”的笔记,共3页,每页20篇 crawler.crawl_note_list(keyword='穿搭', page_num=3, page_size=20) # 保存数据 result_df = crawler.save_data() # 控制台输出抓取结果(展示前5条) print("\n=== 小红书穿搭笔记数据抓取结果(前5条)===") print(result_df.head().to_string(index=False)) 
  1. 打开浏览器(推荐 Chrome),访问小红书官网并完成登录;
  2. F12打开开发者工具,切换到Network面板,刷新页面;
  3. 任意选择一个接口请求(如feed开头的请求),在Request Headers中找到Cookie字段;
  4. 复制整个Cookie字符串,替换代码中XHS_COOKIE变量的值。

2.4 代码输出结果示例

执行代码后,控制台输出如下内容,同时生成xiaohongshu_fashion_notes.csv文件:

plaintext

第1页获取到20篇笔记ID 成功抓取笔记【早春通勤穿搭|简约高级感拉满】(ID:65a2b3c4d5e6f7g8h9i0j) 成功抓取笔记【小个子穿搭|158cm显高技巧】(ID:65b3c4d5e6f7g8h9i0j1k) ... 第2页获取到20篇笔记ID 成功抓取笔记【职场穿搭|轻熟风yyds】(ID:65c4d5e6f7g8h9i0j1k2l) ... 第3页获取到20篇笔记ID 成功抓取笔记【休闲穿搭|周末出游这样穿】(ID:65d5e6f7g8h9i0j1k2l3m) ... 小红书穿搭笔记数据已保存至:xiaohongshu_fashion_notes.csv 共抓取58篇有效笔记 === 小红书穿搭笔记数据抓取结果(前5条)=== note_id note_title note_content author_name like_count collect_count comment_count tag_list publish_time note_url 65a2b3c4d5e6f7g8h9i0j 早春通勤穿搭|简约高级感拉满 早春通勤穿搭分享,简约的基础款搭配真的永不过时!面料选择垂坠感好的,显气质~ 穿搭博主Lily 12580 8960 589 #早春穿搭 | #通勤穿搭 | #简约风 2026-01-10 14:25:36 https://www.xiaohongshu.com/explore/65a2b3c4d5e6f7g8h9i0j 65b3c4d5e6f7g8h9i0j1k 小个子穿搭|158cm显高技巧 158cm小个子穿搭技巧,高腰裤+短上衣真的yyds,视觉增高5cm! 小个子穿搭酱 8960 6580 456 #小个子穿搭 | #显高穿搭 | #158cm 2026-01-11 10:12:45 https://www.xiaohongshu.com/explore/65b3c4d5e6f7g8h9i0j1k 

生成的 CSV 文件核心内容(Excel 展示):

note_idnote_titlenote_contentauthor_namelike_countcollect_countcomment_counttag_listpublish_timenote_url
65a2b3c4d5e6f7g8h9i0j早春通勤穿搭|简约高级感拉满早春通勤穿搭分享,简约的基础款搭配真的永不过时!面料选择垂坠感好的,显气质~穿搭博主 Lily125808960589#早春穿搭 | #通勤穿搭 | #简约风2026-01-10 14:25:36https://www.xiaohongshu.com/explore/65a2b3c4d5e6f7g8h9i0j
65b3c4d5e6f7g8h9i0j1k小个子穿搭|158cm 显高技巧158cm 小个子穿搭技巧,高腰裤 + 短上衣真的 yyds,视觉增高 5cm!小个子穿搭酱89606580456#小个子穿搭 | #显高穿搭 | #158cm2026-01-11 10:12:45https://www.xiaohongshu.com/explore/65b3c4d5e6f7g8h9i0j1k

2.5 核心代码原理拆解

  1. 登录态维护:小红书所有 API 接口均需验证登录 Cookie,未登录状态下仅能获取少量公开数据,通过传入登录后的 Cookie 突破访问限制;
  2. 接口参数构造
    • 搜索接口:通过keyword(关键词)、page(页数)、sort(排序方式)参数获取穿搭笔记 ID 列表;
    • 详情接口:通过note_id(笔记 ID)获取单篇笔记的完整数据,添加毫秒级时间戳模拟前端请求;
  3. 反爬规避策略
    • 超长随机延迟(搜索 5-10 秒 / 详情 3-8 秒):小红书反爬对频率极其敏感,延长延迟是避免 IP 封禁的核心手段;
    • 完整请求头构造:添加sec-ch-uaSec-Fetch-*等浏览器指纹字段,模拟真实 Chrome 浏览器请求;
    • 随机 User-Agent:避免固定 UA 被识别为爬虫;
  4. 数据解析与处理
    • 使用jsonpath提取嵌套 JSON 中的核心字段,适配小红书 API 返回的复杂数据结构;
    • 处理正文换行符:替换\n为空格,避免 CSV 文件格式错乱;
    • 标签拼接:将多个标签用|连接,提升数据可读性;
    • 去重逻辑:基于note_id(唯一标识)去重,保证数据唯一性。

三、反爬机制应对策略

3.1 常见反爬问题及解决方案

反爬类型表现形式解决方案
Cookie 失效接口返回 “未登录” 或 401 错误1. 重新登录小红书,更新 Cookie;2. 使用requests.Session()保持会话,自动刷新 Cookie(进阶)
IP 封禁所有请求返回 403/503 错误1. 暂停抓取 12-24 小时;2. 使用高匿代理池轮换 IP(如 911S5、阿布云);3. 降低抓取频率(单次延迟 10 + 秒)
接口返回空数据JSON 无笔记信息1. 检查 Cookie 是否有效;2. 验证 API 接口 URL 是否过期(小红书 API 不定期更新);3. 更换关键词 / 排序方式
签名参数校验接口返回 “参数错误”1. 分析前端签名生成逻辑,添加x-s/x-t等签名参数;2. 改用 selenium+mitmproxy 抓取真实请求参数(进阶)

3.2 进阶优化建议

  1. 签名参数构造:通过 mitmproxy 抓包分析小红书 APP / 网页端的请求参数,还原x-s(签名)、x-t(时间戳)的生成逻辑,添加到请求头中;
  2. 分布式抓取:多账号 + 多 IP 分布式抓取,降低单账号 / 单 IP 的抓取压力,避免触发反爬。

异常重试机制:使用tenacity库添加重试装饰器,对请求失败的接口自动重试:python运行

from tenacity import retry, stop_after_attempt, wait_random_exponential @retry(stop=stop_after_attempt(3), wait=wait_random_exponential(multiplier=1, max=15)) def get_note_detail(self, note_id): # 原有笔记详情抓取逻辑 

代理池集成:对接付费代理池,在请求中添加proxies参数,示例:python运行

proxies = { 'http': 'http://代理IP:端口', 'https': 'https://代理IP:端口' } response = requests.get(url, headers=headers, proxies=proxies) 

四、注意事项

  1. 合规性:爬取小红书数据需遵守《小红书用户服务协议》,仅用于个人学习研究,禁止大规模商用爬取、恶意抓取;
  2. Cookie 有效期:小红书 Cookie 有效期约 1-7 天,需定期更新,建议每次抓取前重新获取;
  3. 频率控制:单 IP 单日抓取笔记数量建议不超过 100 篇,单账号单日不超过 50 篇,避免触发高强度反爬;
  4. 数据时效性:小红书穿搭笔记热度、点赞数实时变动,如需监控数据需定期重新抓取;
  5. 关键词限制:部分敏感关键词可能触发风控,建议使用通用关键词(如 “穿搭”“日常穿搭”),避免特殊词汇。

总结

  1. 小红书穿搭笔记数据需通过登录后的 Cookie 调用 API 接口获取,核心是构造符合规范的请求头和参数;
  2. 反爬应对核心是模拟真实用户请求(完整浏览器指纹、有效 Cookie)+ 极低频率访问(超长随机延迟),必要时使用代理 IP;
  3. 数据处理需重点关注 JSON 解析、正文格式处理、标签拼接,保证输出数据的可读性和完整性。

Read more

打造你的家庭 AI 助手(四):单 OpenClaw 配置多 Agent、多 QQ、飞书机器人

打造你的家庭 AI 助手(四):单 OpenClaw 配置多 Agent、多 QQ、飞书机器人

打造你的家庭 AI 助手(四):单 OpenClaw 配置多 Agent、多 QQ、飞书机器人 引言 OpenClaw 是一个强大的智能体(Agent)编排框架,它通过统一的架构让开发者可以轻松管理多个聊天机器人,并接入不同的即时通讯平台。在实际应用中,我们往往需要同时运行多个 QQ 机器人(例如个人助手、工作助手),甚至希望同一个智能体既能处理 QQ 消息,也能响应飞书消息。 本文将详细介绍如何在一个 OpenClaw 实例中配置多通道(QQ、飞书)、多 Agent 以及多 QQ 机器人账号,实现资源的高效利用和灵活的消息路由。特别地,我们将阐明飞书通道与 QQ 通道在绑定规则上的差异,避免常见的配置错误。 核心概念回顾 * Agent(智能体):拥有独立人格、记忆和技能的对话单元。每个

By Ne0inhk
AI实践(2)提示词工程

AI实践(2)提示词工程

AI实践(2)提示词工程 Author: Once Day Date: 2026年3月2日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可参考专栏: AI实践成长_Once-Day的博客-ZEEKLOG博客 参考文章:Documentation - Claude API DocsOpenAI for developersPrompt Engineering GuidePrompt Engineering Guide: The Ultimate Guide to Generative AI提示词技巧 – Claude 中文 - Claude AI 开发技术社区Prompting strategies for financial analysis | ClaudeGPT-5 prompting guidePrompt engineering | OpenAI APIPrompting

By Ne0inhk
免费开源AI工具:CoPaw与OpenFang整理

免费开源AI工具:CoPaw与OpenFang整理

CoPaw 和 OpenFang,两者软件本体都免费开源,但模型 API 可能产生费用。 CoPaw(阿里云) * 软件本身:完全免费开源(Apache 2.0),无会员、无广告、无功能限制 * 本地部署:免费,仅需 Python 环境,可跑本地模型(Ollama 等),零 API 费用 * 云端部署:魔搭创空间有免费测试额度;长期使用按云资源(CPU/GPU/ 存储)计费 * 模型 API:调用通义千问、OpenAI、DeepSeek 等按官方标准按量付费  CoPaw GitHub 地址 https://github.com/agentscope-ai/CoPaw OpenFang(

By Ne0inhk
学习AI必备基础知识

学习AI必备基础知识

前段时间,由于回家过年,躺在床上实在感觉无聊, 所以就在网上搜罗了相关资料,整理了学习内容,方便以后温故。 进来各种模型频繁迭代,好像光是闻着claude、gpt、deepseek、豆包这些模型升级的声音,就已经让我们热血澎湃。 但你真的了解他们吗?你知道如何用好他们吗? 如: * user prompt * system prompt * AI Agent * function calling * MCP * RAG * 上下文窗口 可能你零星的知道些皮毛,不过没关系,现在让我带着你深入学习一番。 大纲 * 一、什么是所谓的user prompt * 二、user prompt 和 system prompt * 1、 user prompt(用户提示词) * 2、 system prompt(系统提示词) * 三、AI Agent

By Ne0inhk