如何通过Python高效采集小红书公开数据:从技术痛点到完整解决方案
如何通过Python高效采集小红书公开数据从技术痛点到完整解决方案【免费下载链接】xhs基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/项目地址: https://gitcode.com/gh_mirrors/xh/xhs在小红书数据采集领域开发者面临的核心挑战是平台日益严格的反爬机制和复杂的接口签名逻辑。传统爬虫方案往往在频繁的接口变更和签名验证面前束手无策而xhs库正是为解决这些技术痛点而生的专业工具。本文将深入解析如何利用xhs库构建稳定可靠的小红书数据采集系统。技术痛点识别为什么传统爬虫方案难以应对小红书小红书作为内容社交平台采用了多层防护机制保护其数据接口。开发者常遇到以下问题签名验证机制每次请求都需要生成动态签名算法复杂且频繁更新Cookie时效性登录凭证有效期短需要持续维护请求频率限制过于频繁的访问会触发IP封禁数据结构变化接口返回格式不定期调整xhs库通过封装官方接口和自动化签名处理将这些问题抽象为简单的API调用让开发者能够专注于业务逻辑而非底层技术细节。三步构建稳定的小红书数据采集系统第一步环境配置与身份验证安装xhs库只需一行命令pip install xhs身份验证是数据采集的第一步。xhs库支持两种认证方式from xhs import XhsClient # 方式一基础Cookie认证 cookie your_cookie_here client XhsClient(cookie) # 方式二完整签名认证推荐用于生产环境 def custom_sign(uri, dataNone, a1, web_session): # 实现签名逻辑 return {x-s: signature, x-t: timestamp} client XhsClient(cookie, signcustom_sign)签名函数的实现可以参考项目中的示例代码特别是example目录下的basic_sign_server.py文件展示了如何通过Playwright浏览器自动化生成有效的签名。第二步核心数据采集功能详解笔记数据获取xhs库提供了多种笔记获取方式满足不同场景需求# 获取单篇笔记详情 note_id 6505318c000000001f03c5a6 note_detail client.get_note_by_id(note_id) # 按关键词搜索笔记 search_results client.get_note_by_keyword( keywordPython编程, page1, sortgeneral # 支持general综合和time时间排序 ) # 获取用户所有笔记 user_notes client.get_user_all_notes(user_id_here)用户信息分析用户数据分析是内容策略制定的基础# 获取用户基本信息 user_info client.get_user_info(user_id_here) # 获取用户收藏的笔记 collected_notes client.get_user_collect_notes(user_id_here, num50) # 获取用户点赞的笔记 liked_notes client.get_user_like_notes(user_id_here, num50)内容分类浏览xhs库内置了FeedType枚举类支持按内容分类获取数据from xhs import FeedType # 获取推荐内容 recommend_notes client.get_home_feed(FeedType.RECOMMEND) # 获取特定分类内容 fashion_notes client.get_home_feed(FeedType.FASION) food_notes client.get_home_feed(FeedType.FOOD) travel_notes client.get_home_feed(FeedType.TRAVEL)第三步数据处理与持久化数据清洗与格式化原始数据需要经过处理才能用于分析from xhs import help import json from datetime import datetime def process_note_data(raw_note): 清洗和格式化笔记数据 # 提取图片URL image_urls help.get_imgs_url_from_note(raw_note) # 提取视频URL video_url help.get_video_url_from_note(raw_note) processed { note_id: raw_note.get(id), title: raw_note.get(title, ).strip(), author: raw_note.get(user, {}).get(nickname, ), publish_time: datetime.fromtimestamp( raw_note.get(time, 0) / 1000 ).isoformat(), interaction_stats: { likes: raw_note.get(likes, 0), comments: raw_note.get(comments, 0), shares: raw_note.get(shares, 0), collects: raw_note.get(collects, 0) }, media: { image_count: len(image_urls), image_urls: image_urls, has_video: bool(video_url), video_url: video_url }, tags: [tag.get(name, ) for tag in raw_note.get(tag_list, [])] } return processed数据存储策略根据数据量和使用场景选择合适的存储方案import pandas as pd import sqlite3 from pathlib import Path class DataStorage: def __init__(self, storage_pathdata): self.storage_path Path(storage_path) self.storage_path.mkdir(exist_okTrue) def save_as_json(self, data, filename): 保存为JSON格式 filepath self.storage_path / f{filename}.json with open(filepath, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def save_as_csv(self, data_list, filename): 保存为CSV格式 if not data_list: return df pd.DataFrame(data_list) filepath self.storage_path / f{filename}.csv df.to_csv(filepath, indexFalse, encodingutf-8-sig) def save_to_sqlite(self, data_list, table_name): 保存到SQLite数据库 db_path self.storage_path / xhs_data.db conn sqlite3.connect(db_path) # 创建表如果不存在 if data_list: sample data_list[0] columns list(sample.keys()) create_table_sql f CREATE TABLE IF NOT EXISTS {table_name} ( id INTEGER PRIMARY KEY AUTOINCREMENT, {, .join([f{col} TEXT for col in columns])} ) conn.execute(create_table_sql) # 插入数据 for item in data_list: values [str(item.get(col, )) for col in columns] placeholders , .join([?] * len(values)) insert_sql fINSERT INTO {table_name} ({, .join(columns)}) VALUES ({placeholders}) conn.execute(insert_sql, values) conn.commit() conn.close()高级应用场景与最佳实践场景一竞品监控系统构建自动化的竞品内容监控系统import schedule import time from datetime import datetime, timedelta class CompetitorMonitor: def __init__(self, client, competitor_ids): self.client client self.competitor_ids competitor_ids self.storage DataStorage(competitor_data) def monitor_daily_content(self): 每日监控竞品内容发布情况 daily_report {} for competitor_id in self.competitor_ids: try: # 获取最新笔记 notes self.client.get_user_notes(competitor_id, cursor) # 分析数据 if notes: analysis self.analyze_content_performance(notes) daily_report[competitor_id] analysis # 保存原始数据 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) self.storage.save_as_json(notes, f{competitor_id}_{timestamp}) # 避免请求过快 time.sleep(2) except Exception as e: print(f监控竞品 {competitor_id} 失败: {e}) return daily_report def analyze_content_performance(self, notes): 分析内容表现指标 if not notes: return {} total_likes sum(note.get(likes, 0) for note in notes) total_comments sum(note.get(comments, 0) for note in notes) total_shares sum(note.get(shares, 0) for note in notes) return { total_notes: len(notes), avg_likes: total_likes / len(notes), avg_comments: total_comments / len(notes), avg_shares: total_shares / len(notes), top_note: max(notes, keylambda x: x.get(likes, 0)) if notes else None } def start_daily_monitoring(self): 启动每日定时监控 schedule.every().day.at(09:00).do(self.monitor_daily_content) while True: schedule.run_pending() time.sleep(60)场景二内容趋势分析识别平台内容趋势变化class TrendAnalyzer: def __init__(self, client, keywords): self.client client self.keywords keywords def analyze_keyword_trend(self, days7): 分析关键词7天趋势 trend_data {} for keyword in self.keywords: daily_metrics [] for day_offset in range(days): # 模拟按时间搜索实际可能需要调整搜索参数 results self.client.get_note_by_keyword( keywordkeyword, page1, sorttime ) if results: day_analysis { date: (datetime.now() - timedelta(daysday_offset)).strftime(%Y-%m-%d), total_notes: len(results), avg_engagement: self.calculate_engagement_rate(results), top_categories: self.extract_content_categories(results) } daily_metrics.append(day_analysis) trend_data[keyword] daily_metrics return trend_data def calculate_engagement_rate(self, notes): 计算互动率 if not notes: return 0 total_engagement 0 for note in notes: engagement note.get(likes, 0) note.get(comments, 0) note.get(shares, 0) total_engagement engagement return total_engagement / len(notes) def extract_content_categories(self, notes): 提取内容分类 categories {} for note in notes: tags note.get(tag_list, []) for tag in tags: category tag.get(name, ) if category: categories[category] categories.get(category, 0) 1 # 返回前5个热门分类 return dict(sorted(categories.items(), keylambda x: x[1], reverseTrue)[:5])性能优化与错误处理策略请求优化策略import random from typing import Optional from xhs.exception import DataFetchError, IPBlockError class OptimizedXhsClient: def __init__(self, base_client, max_retries3, base_delay1): self.client base_client self.max_retries max_retries self.base_delay base_delay def safe_request(self, method, *args, **kwargs): 带重试机制的请求包装器 for attempt in range(self.max_retries): try: return method(*args, **kwargs) except (DataFetchError, IPBlockError) as e: if attempt self.max_retries - 1: raise # 指数退避策略 delay self.base_delay * (2 ** attempt) random.uniform(0, 0.5) print(f请求失败{delay:.2f}秒后重试第{attempt 1}次...) time.sleep(delay) except Exception as e: print(f未知错误: {e}) raise def batch_process_with_progress(self, item_ids, process_func, batch_size10): 批量处理并显示进度 results [] total len(item_ids) for i in range(0, total, batch_size): batch item_ids[i:i batch_size] batch_results [] for item_id in batch: try: result self.safe_request(process_func, item_id) batch_results.append(result) except Exception as e: print(f处理{item_id}失败: {e}) batch_results.append(None) # 随机延迟避免规律性请求 time.sleep(random.uniform(0.5, 1.5)) results.extend(batch_results) # 进度显示 progress min(i batch_size, total) print(f进度: {progress}/{total} ({progress/total*100:.1f}%)) return results缓存机制实现import pickle from functools import lru_cache from datetime import datetime, timedelta class DataCache: def __init__(self, cache_dircache, ttl_hours24): self.cache_dir Path(cache_dir) self.cache_dir.mkdir(exist_okTrue) self.ttl timedelta(hoursttl_hours) def get_cache_key(self, func_name, *args, **kwargs): 生成缓存键 import hashlib key_str f{func_name}_{str(args)}_{str(kwargs)} return hashlib.md5(key_str.encode()).hexdigest() def get_cached_data(self, cache_key): 获取缓存数据 cache_file self.cache_dir / f{cache_key}.pkl if not cache_file.exists(): return None # 检查缓存是否过期 file_mtime datetime.fromtimestamp(cache_file.stat().st_mtime) if datetime.now() - file_mtime self.ttl: cache_file.unlink() return None with open(cache_file, rb) as f: return pickle.load(f) def set_cached_data(self, cache_key, data): 设置缓存数据 cache_file self.cache_dir / f{cache_key}.pkl with open(cache_file, wb) as f: pickle.dump(data, f) def cached_request(self, func, *args, **kwargs): 带缓存的请求装饰器 cache_key self.get_cache_key(func.__name__, *args, **kwargs) # 尝试从缓存获取 cached_data self.get_cached_data(cache_key) if cached_data is not None: print(f使用缓存数据: {cache_key}) return cached_data # 执行实际请求 data func(*args, **kwargs) # 缓存结果 self.set_cached_data(cache_key, data) return data常见问题解答FAQQ1: 如何处理签名失败错误签名失败通常由以下原因导致Cookie过期或无效签名函数实现有误请求参数格式不正确解决方案检查Cookie的有效性重新获取参考example/basic_sign_server.py中的签名实现确保请求参数与官方接口一致Q2: 遇到IP封禁怎么办IP封禁是常见的反爬措施建议采取以下策略降低请求频率添加随机延迟使用代理IP池轮换实现指数退避重试机制遵守robots.txt协议Q3: 如何确保数据采集的稳定性长期稳定运行的关键错误处理完善的异常捕获和重试机制监控告警实现运行状态监控数据校验定期检查数据完整性和准确性版本兼容关注xhs库的更新及时适配接口变化Q4: 数据采集的合规性边界是什么合规使用指南✅ 采集公开可见的数据用于研究分析✅ 遵守平台的使用条款和robots.txt✅ 添加适当的请求间隔不对服务器造成压力❌ 不要采集非公开或隐私数据❌ 不要用于商业侵权或恶意竞争❌ 不要绕过平台的安全机制Q5: 如何处理大规模数据采集大规模采集建议分布式架构使用多进程或多节点并行处理增量采集只采集新增或更新的内容数据分片按用户ID或时间范围分片处理存储优化使用数据库而非文件系统存储大量数据技术实现深度解析xhs库的核心技术优势在于对小红书Web接口的深度封装。通过分析xhs/core.py源码可以看到其实现了完整的请求签名、错误处理和数据类型转换逻辑。关键实现要点请求签名机制自动处理复杂的签名生成逻辑会话管理维护有效的Cookie和会话状态数据类型转换将原始JSON数据转换为易用的Python对象错误处理统一的异常处理框架项目测试文件tests/test_xhs.py展示了完整的API测试用例确保核心功能的稳定性。开发者可以参考这些测试用例了解如何正确使用各个API接口。总结与展望xhs库为小红书数据采集提供了一个专业、稳定的解决方案。通过本文介绍的三步构建方法开发者可以快速搭建自己的数据采集系统。无论是竞品分析、内容监控还是趋势研究xhs库都能提供可靠的技术支持。技术价值体现在降低开发门槛将复杂的接口调用抽象为简单API提高稳定性内置错误处理和重试机制保持兼容性持续跟进平台接口变化社区支持开源项目持续维护和更新未来发展方向可能包括更丰富的API接口覆盖性能优化和并发支持数据分析和可视化工具集成云服务部署方案通过合理使用xhs库开发者可以专注于业务逻辑实现而无需担心底层的数据采集技术细节。记住技术工具的价值在于解决实际问题始终将合规性和道德考量放在首位用技术创造真正的价值。【免费下载链接】xhs基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/项目地址: https://gitcode.com/gh_mirrors/xh/xhs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

C++ STL list容器深度解析:双向链表实现、核心特性与高效应用场景

C++ STL list容器深度解析:双向链表实现、核心特性与高效应用场景

1. 项目概述:为什么我们需要深入理解list容器?在C的STL(标准模板库)宇宙里,vector和list就像一对性格迥异的双胞胎。vector因其连续内存和随机访问能力,是大多数场景下的首选,名声在外。但当你真…

2026/10/11 5:17:19 阅读更多 →
B站抽奖革命:智能自动化工具如何让你的中奖率提升300%

B站抽奖革命:智能自动化工具如何让你的中奖率提升300%

B站抽奖革命:智能自动化工具如何让你的中奖率提升300% 【免费下载链接】LotteryAutoScript Bili动态抽奖助手 项目地址: https://gitcode.com/gh_mirrors/lo/LotteryAutoScript 还在为错过B站热门抽奖活动而烦恼吗?每天手动转发几十条抽奖动态&am…

2026/9/26 21:27:45 阅读更多 →
西门子PLC电梯群控系统开发与TIA Portal实战

西门子PLC电梯群控系统开发与TIA Portal实战

1. 项目概述:10层6梯电梯控制系统的博途开发实战这套基于西门子S7-1200 PLC的电梯控制系统程序,是我去年为某商业综合体完成的真实项目改造案例。系统采用TIA Portal V17开发环境,包含PLC逻辑控制、WinCC人机界面和电梯群控算法三大模块&…

2026/9/29 21:03:57 阅读更多 →

最新新闻

如何用 SearXNG 给本地 Qwen3 搭一个能联网搜索的 MCP?TaoToken 统一 Key 接入实践

如何用 SearXNG 给本地 Qwen3 搭一个能联网搜索的 MCP?TaoToken 统一 Key 接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 6:14:10 阅读更多 →
从接需求到上线:Trae 的“原生中文 Agent”模式,是否真的比 Cursor Composer 更懂中国程序员?TaoToken 统一 Key 通道实测

从接需求到上线:Trae 的“原生中文 Agent”模式,是否真的比 Cursor Composer 更懂中国程序员?TaoToken 统一 Key 通道实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 6:14:10 阅读更多 →
撕开 DeepSeek MLA 源码:现代 C++ / TensorRT-LLM 底层算子设计与优化全景

撕开 DeepSeek MLA 源码:现代 C++ / TensorRT-LLM 底层算子设计与优化全景

在 64K 长上下文推理中,以 128 头、单头 128 维的注意力层配置为例,传统多头注意力(MHA)每生成一个 Token 就需要从显存读取 64 KB 的 KV 缓存;DeepSeek 提出的多头潜在注意力(Multi-Head Latent Attention, MLA)通过 512 维潜在向量与解耦 RoPE 机制,将单 Token 缓存体…

2026/10/11 6:14:10 阅读更多 →
900KB请求就能让Next.js服务器瘫痪?CVE-2026-23870高危漏洞来袭,React 19用户必须立刻升级

900KB请求就能让Next.js服务器瘫痪?CVE-2026-23870高危漏洞来袭,React 19用户必须立刻升级

一个不足1MB的POST请求,就能让整台运行Next.js的生产服务器瞬间“冻僵”——这不是危言耸听,而是编号为CVE-2026-23870的高危拒绝服务漏洞正在上演的真实剧本。如果你团队的项目正跑在React 19.x之上,这条消息值得你放下手头的工作&#xff0…

2026/10/11 6:13:10 阅读更多 →
律所案件管理系统实战:SpringBoot+Vue3+MyBatis开发详解

律所案件管理系统实战:SpringBoot+Vue3+MyBatis开发详解

一套律师事务所案件管理系统,说高级点是数字化管理,说白了就是帮律师把案子、客户、日程、文书从“Excel 表格 微信聊天 脑子记”的混乱状态里解放出来。前端 Vue3 做交互界面,后端 SpringBoot 提供接口,MyBatis 管数据库操作&a…

2026/10/11 6:13:10 阅读更多 →
MobileNetV2实战:PyTorch训练到TensorRT部署全流程解析

MobileNetV2实战:PyTorch训练到TensorRT部署全流程解析

简介:面向深度学习初学者和有模型部署需求的开发者,提供一套基于PyTorch mobilenetv2的图像分类完整实践资源,覆盖从数据准备、模型训练到ONNX与TensorRT推理的端到端流程。资源包共2000个文件,以大量png样本图片、py脚本及pyc编译…

2026/10/11 6:13:09 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →