# TypeScript + Playwright 实战:合规拉取小红书笔记评论数与收藏数
下面是一篇可以直接复制到 CSDN 的 Markdown 博文。标题中特意写成“评论数与收藏数”避免让读者误以为本文会批量抓取评论用户隐私或绕过平台限制。# TypeScript Playwright 实战合规拉取小红书笔记评论数与收藏数 本文介绍一种面向“本人账号、本人笔记或已获得明确授权内容”的小红书数据采集方案。 不讨论验证码绕过、风控规避、Cookie 窃取、匿名批量爬取等行为。 ## 前言 在多平台内容发布系统中发布成功并不是流程的终点。 运营人员通常还需要持续查看 - 笔记是否仍然存在 - 当前评论数 - 当前收藏数 - 点赞数 - 指标最后更新时间 - 指标变化趋势。 小红书创作服务平台本身提供面向创作者的数据分析能力但普通开发者未必能够直接获得一个适用于任意笔记的通用公开接口。 因此实际项目中通常采用三层降级方案 1. 优先申请并使用官方授权接口 2. 无官方接口时使用用户授权的浏览器登录会话读取本人数据 3. 无法自动采集时支持人工导入指标。 本文使用 TypeScript、Playwright、Express 和 SQLite实现第二种方案同时预留官方接口适配器。 --- ## 一、整体架构 推荐的数据流如下 text 小红书笔记页面 ↓ Playwright 授权浏览器会话 ↓ XhsMetricsCollector ↓ 指标校验与标准化 ↓ platform_metrics 指标快照表 ↓ 前端趋势图、历史列表和 CSV 导出需要特别强调浏览器采集器只负责“读取” 指标服务负责“校验与保存” 前端只访问自己的后端接口不要让前端页面直接请求小红书也不要把登录 Cookie 返回给浏览器前端。二、为什么使用指标快照而不是覆盖旧数据错误做法UPDATE publish_results SET like_count 100, comment_count 20;这样会丢失历史变化。更合理的方式是每次采集新增一条快照10:00 收藏 20评论 5 11:00 收藏 28评论 8 12:00 收藏 41评论 13数据表可以设计为CREATE TABLE platform_metrics ( id TEXT PRIMARY KEY, publish_result_id TEXT NOT NULL, platform_code TEXT NOT NULL, view_count INTEGER, like_count INTEGER, comment_count INTEGER, favorite_count INTEGER, share_count INTEGER, data_source TEXT NOT NULL, collected_at INTEGER NOT NULL, created_at INTEGER NOT NULL );其中comment_count 表示评论数 favorite_count 表示收藏数 data_source 表示数据来源 collected_at 表示实际采集时间建议的数据来源枚举type DataSource | REAL_API | BROWSER | MANUAL_IMPORT | MOCK;不要把模拟数据标记成REAL_API或BROWSER。三、安装 Playwrightpnpm add playwright zod首次运行还需要安装浏览器pnpm exec playwright install chromium项目建议使用 Node.js 24。四、解析“1.2万”等指标文本小红书页面上的数字不一定都是普通整数可能出现986 1.2万 3万可以先编写统一的解析函数export function parseMetricCount(rawText: string): number | null { const normalized rawText .trim() .replaceAll(,, ) .replaceAll(, ); if (!normalized) { return null; } const tenThousandMatch normalized.match(/(\d(?:\.\d)?)\s*万/); if (tenThousandMatch) { return Math.round(Number(tenThousandMatch[1]) * 10_000); } const thousandMatch normalized.match(/(\d(?:\.\d)?)\s*千/); if (thousandMatch) { return Math.round(Number(thousandMatch[1]) * 1_000); } const integerMatch normalized.match(/\d/); if (!integerMatch) { return null; } return Number(integerMatch[0]); }测试console.log(parseMetricCount(986)); // 986 console.log(parseMetricCount(1.2万)); // 12000 console.log(parseMetricCount(3万)); // 30000五、使用持久化浏览器会话第一次运行时由用户本人手动登录小红书。后续运行复用本地浏览器配置目录不需要在代码中保存明文账号和密码。import { chromium, type BrowserContext, type Page } from playwright; import path from node:path; const profileDir path.resolve( process.cwd(), .auth, xiaohongshu-metrics, ); export async function openAuthorizedXhsContext(): PromiseBrowserContext { return chromium.launchPersistentContext(profileDir, { headless: false, viewport: { width: 1440, height: 960, }, locale: zh-CN, }); }第一次启动后在打开的浏览器中手动登录。需要把目录加入.gitignore.auth/禁止把浏览器配置目录、Cookie、Token 或用户凭证提交到 Git。六、实现小红书指标采集器由于页面结构可能变化不建议把选择器散落在业务代码中。可以把选择器集中配置const METRIC_SELECTORS { comment: [ [aria-label*评论], button:has-text(评论), [class*comment], ], favorite: [ [aria-label*收藏], button:has-text(收藏), [class*collect], ], like: [ [aria-label*点赞], button:has-text(点赞), [class*like], ], } as const;编写一个安全读取函数import type { Page } from playwright; async function readMetricFromSelectors( page: Page, selectors: readonly string[], ): Promisenumber | null { for (const selector of selectors) { const locator page.locator(selector).first(); if ((await locator.count()) 0) { continue; } const text await locator .innerText() .catch(() ); const value parseMetricCount(text); if (value ! null) { return value; } } return null; }定义统一输出export interface XhsMetricSnapshot { articleUrl: string; likeCount: number | null; commentCount: number | null; favoriteCount: number | null; dataSource: BROWSER; collectedAt: string; }实现采集逻辑export async function collectXhsMetrics( articleUrl: string, ): PromiseXhsMetricSnapshot { const context await openAuthorizedXhsContext(); try { const page await context.newPage(); await page.goto(articleUrl, { waitUntil: domcontentloaded, timeout: 30_000, }); await page .waitForLoadState(networkidle, { timeout: 10_000, }) .catch(() undefined); const currentUrl page.url(); if (currentUrl.includes(/login)) { throw new Error(XHS_LOGIN_REQUIRED); } const [likeCount, commentCount, favoriteCount] await Promise.all([ readMetricFromSelectors( page, METRIC_SELECTORS.like, ), readMetricFromSelectors( page, METRIC_SELECTORS.comment, ), readMetricFromSelectors( page, METRIC_SELECTORS.favorite, ), ]); return { articleUrl, likeCount, commentCount, favoriteCount, dataSource: BROWSER, collectedAt: new Date().toISOString(), }; } finally { await context.close(); } }这里没有实现验证码绕过。出现登录失效或验证码时应停止自动采集并提示用户重新完成授权登录。七、不要把“取不到”自动写成 0下面两种情况含义不同0 指标真实为零 null 当前无法可靠获取因此不要这样写const favoriteCount parsedValue ?? 0;正确做法是保留nullconst favoriteCount parsedValue;前端可以显示收藏数暂不可获取而不是误导用户收藏数0八、设计统一采集器接口为了以后能够切换到官方 API不要把 Playwright 逻辑直接写进 Controller。可以定义统一接口export interface PlatformMetricsCollector { supports(platformCode: string): boolean; collect(input: { articleUrl: string; resultId: string; }): Promise{ likeCount: number | null; commentCount: number | null; favoriteCount: number | null; collectedAt: string; dataSource: REAL_API | BROWSER; }; }Playwright 实现export class XhsBrowserMetricsCollector implements PlatformMetricsCollector { supports(platformCode: string): boolean { return platformCode XIAOHONGSHU; } async collect(input: { articleUrl: string; resultId: string; }) { const snapshot await collectXhsMetrics( input.articleUrl, ); return { likeCount: snapshot.likeCount, commentCount: snapshot.commentCount, favoriteCount: snapshot.favoriteCount, collectedAt: snapshot.collectedAt, dataSource: snapshot.dataSource, }; } }将来获得官方接口权限后只需新增class XhsOfficialApiMetricsCollector implements PlatformMetricsCollector { // 调用经过授权的官方接口 }不需要修改指标查询页面和数据库结构。九、设计后端同步接口建议提供POST /api/v1/publish-results/{resultId}/sync-metrics业务流程1. 查询 publish_result 2. 确认 platformCodeXIAOHONGSHU 3. 检查 articleUrl 4. 选择可用采集器 5. 拉取评论数与收藏数 6. 校验非负整数 7. 新增 platform_metrics 快照 8. 返回本次采集结果Express 示例import type { Request, Response } from express; export async function syncMetricsController( req: Request, res: Response, ): Promisevoid { const resultId req.params.resultId; const publishResult await publishResultRepository.findById(resultId); if (!publishResult) { res.status(404).json({ code: PUBLISH_RESULT_NOT_FOUND, message: 发布结果不存在, }); return; } if (!publishResult.articleUrl) { res.status(409).json({ code: ARTICLE_URL_MISSING, message: 发布结果尚未包含小红书笔记地址, }); return; } const collector metricsCollectorRegistry.find( publishResult.platformCode, ); if (!collector) { res.status(501).json({ code: XHS_METRICS_COLLECTOR_UNAVAILABLE, message: 当前尚未接入小红书授权指标采集器, }); return; } const snapshot await collector.collect({ articleUrl: publishResult.articleUrl, resultId, }); const saved await metricSnapshotService.create({ resultId, likeCount: snapshot.likeCount, commentCount: snapshot.commentCount, favoriteCount: snapshot.favoriteCount, viewCount: null, shareCount: null, dataSource: snapshot.dataSource, collectedAt: snapshot.collectedAt, }); res.status(201).json({ data: saved, }); }十、指标历史查询接口建议提供GET /api/v1/publish-results/{resultId}/metrics支持page pageSize latest例如GET /api/v1/publish-results/result-001/metrics?page1pageSize20查询 SQLSELECT * FROM platform_metrics WHERE publish_result_id ? ORDER BY collected_at DESC LIMIT ? OFFSET ?;如果只查询最新快照GET /api/v1/publish-results/result-001/metrics?latesttrue十一、完整评论内容与评论数不是一回事本文主要采集的是评论数量 收藏数量 点赞数量如果需要拉取完整评论内容还需要额外考虑评论分页回复层级评论用户信息脱敏删除评论的处理重复评论去重数据保存期限用户隐私和平台授权范围。不建议在没有明确授权的情况下保存评论用户头像、昵称、主页地址等信息。课程项目或内部运营系统中优先只保存聚合指标风险更低也更容易维护。十二、异常处理建议1. 登录状态失效返回XHS_LOGIN_REQUIRED页面提示小红书登录状态已失效请重新完成浏览器授权。2. 页面结构变化返回XHS_METRIC_SELECTOR_NOT_MATCHED不要自动把所有指标写成 0。3. 笔记不存在返回XHS_NOTE_NOT_FOUND4. 指标部分可用允许保存{ likeCount: 120, commentCount: 15, favoriteCount: null }不应该因为一个字段无法获取就丢弃其他有效指标。十三、安全与合规要求实际开发中应遵循以下原则只采集本人账号、本人笔记或明确授权的数据优先使用官方接口和创作者平台不绕过验证码和平台访问控制不保存明文密码不把 Cookie、Token 和 Authorization 写入日志浏览器用户目录不得提交 Git控制采集频率不进行大规模并发请求采集失败不应影响文章发布主流程Mock 数据必须明确标记为 Mock页面结构改变时应停止采集而不是盲目写入错误结果。十四、总结一个可靠的小红书指标采集模块不只是写一个页面爬虫。更合理的设计是授权浏览器会话 可替换采集器 指标标准化 追加式历史快照 数据来源标记 安全与异常处理最终可以形成小红书发布成功 → 定时或手动刷新指标 → 写入评论与收藏快照 → 查看指标变化趋势 → 导出运营报告如果未来获得官方数据接口权限只需替换采集器实现不需要重写数据库、接口和前端页面。当前小红书创作服务平台公开页面明确提到“数据分析”能力与此同时公开开放平台文档目录主要展示商品、订单、物流、售后等接口场景。基于当前公开文档我没有找到面向任意笔记评论数、收藏数的通用公开 API因此博文采用“官方授权优先、授权浏览器会话降级、人工导入兜底”的表述更严谨。:contentReference[oaicite:0]{index0} **推荐 CSDN 标题** text TypeScript Playwright 实战合规拉取小红书笔记评论数与收藏数摘要本文基于 TypeScript、Playwright、Express 和 SQLite设计并实现一个面向授权账号的小红书指标采集模块支持读取评论数、收藏数与点赞数保存追加式指标快照并通过统一采集器接口为后续官方 API 接入预留扩展点。标签TypeScript Playwright Node.js 小红书 数据采集 Express SQLite

相关新闻

广州软件测试培训机构靠谱吗?深度解析行业现状与择校要点

广州软件测试培训机构靠谱吗?深度解析行业现状与择校要点

软件测试工程师是当前IT行业中需求最为稳定的技术岗位之一。与开发岗位相比,软件测试更注重逻辑思维和细节把控,不需要开发者那样精通多门编程语言,但同样需要掌握自动化测试工具、测试用例设计、缺陷管理等核心技能。从BOSS直聘、智联招聘等…

2026/8/1 20:51:04阅读更多 →
Axure:变量表达式函数使用指南!

Axure:变量表达式函数使用指南!

【免费】AxureRP11安装包+汉化包 链接:https://pan.baidu.com/s/1ZGDcfEks9hg8DrozKl2EqA?pwd=lax8 提取码:lax8 【免费】AxureRP10安装包+汉化包 链接:https://pan.baidu.com/s/1owWvGQSk-DWn7ttAGngINg?pwd=lax8 提取码:lax8 【免费】AxureRP9安装包+汉化包 链接:https:/…

2026/8/1 20:51:04阅读更多 →
连趣云在智能系统集成平台领域的竞争力分析报告

连趣云在智能系统集成平台领域的竞争力分析报告

一、 市场定位分析连趣云在智能系统集成平台的价值链中,定位于“应用层”的轻量级集成服务提供商。其核心价值在于为非技术背景的业务人员或中小型企业提供快速、低成本的系统连接能力,解决传统集成方案技术门槛高、实施周期长、成本高昂的痛点。目标客户…

2026/8/1 20:51:04阅读更多 →
如何自己验证代理IP真实性?WebRTC/归属地/指纹自洽 技术自测

如何自己验证代理IP真实性?WebRTC/归属地/指纹自洽 技术自测

购买代理 IP 时,供应商通常会提供"真实住宅 IP""原生 IP""指纹纯净"等描述。但实际接入后,很多人发现业务仍被风控:账号异常、支付受限、内容推荐不准。问题往往不在代理本身,而在于出口 IP、DNS 解…

2026/8/1 22:05:27阅读更多 →
TEMU店群自动化管理系统:isTrusted事件注入,浏览器视为真人操作

TEMU店群自动化管理系统:isTrusted事件注入,浏览器视为真人操作

TEMU店群自动化管理系统:isTrusted事件注入,浏览器视为真人操作 老店群人都有个体会:TEMU的批量抓取采集,是店群运营中最耗人力也最容易出错的环节。 采集竞品数据是店群运营的命脉。但各大平台的反爬系统越来越强,普…

2026/8/1 22:05:27阅读更多 →
Windows 10字体渲染终极优化指南:BetterClearTypeTuner实战应用

Windows 10字体渲染终极优化指南:BetterClearTypeTuner实战应用

Windows 10字体渲染终极优化指南:BetterClearTypeTuner实战应用 【免费下载链接】BetterClearTypeTuner A better way to configure ClearType font smoothing on Windows 10. 项目地址: https://gitcode.com/gh_mirrors/be/BetterClearTypeTuner 在Windows …

2026/8/1 22:05:27阅读更多 →
ScanTailor Advanced终极指南:免费开源文档扫描优化神器

ScanTailor Advanced终极指南:免费开源文档扫描优化神器

ScanTailor Advanced终极指南:免费开源文档扫描优化神器 【免费下载链接】scantailor-advanced ScanTailor Advanced is the version that merges the features of the ScanTailor Featured and ScanTailor Enhanced versions, brings new ones and fixes. 项目地…

2026/8/1 22:05:27阅读更多 →
施工现场重型机械工程车检测数据集5296张VOC+YOLO格式

施工现场重型机械工程车检测数据集5296张VOC+YOLO格式

施工现场重型机械工程车检测数据集5296张VOCYOLO格式数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):5296 标注数量(xml文件个数)&#xff1…

2026/8/1 22:05:27阅读更多 →
新手必看!Princess-connection-farm常见问题与脚本报错解决方法

新手必看!Princess-connection-farm常见问题与脚本报错解决方法

新手必看!Princess-connection-farm常见问题与脚本报错解决方法 【免费下载链接】Princess-connection-farm 国服PCR公主连结 多开自动农场脚本 基于opencvUIAutomator 项目地址: https://gitcode.com/gh_mirrors/pr/Princess-connection-farm Princess-conn…

2026/8/1 22:03:26阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/8/1 21:54:49阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/8/1 21:14:15阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →