☰
xhs 快速入门:基于 Playwright 的 x-s 签名获取与统一签名服务搭建指南
2026/10/4 1:55:57 网站建设 项目流程
  • 网页爬虫

【免费下载链接】xhs

基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/

项目地址:https://gitcode.com/gh_mirrors/xh/xhs
点击查看免费下载

导读

本文是基于小红书网页端请求封装库xhs的快速入门指南,聚焦于最核心的技术难点——x-s签名的获取与复用。文章完整覆盖从环境安装、浏览器签名函数调用、cookie 字段准备,到将签名能力封装为 Flask 服务端并通过XhsClient实现多账号统一签名的完整链路。读完本文,你将掌握xhs包的基础使用方式、playwright模拟浏览器取签的落地细节,以及一套可直接运行的生产级签名服务方案。

一、为什么需要 x-s 签名

小红书 Web 端接口对每个请求都要求携带x-s、x-t等签名参数,而该签名算法基于网页内的 JS 函数(即window._webmsxyw)动态计算,逻辑复杂且包含大量环境检测行为。直接逆向纯 Python 复现签名成本高、易失效,因此xhs采用Playwright 模拟真实浏览器执行 JS的方式来获取签名,同时配合stealth.min.js注入脚本绕过反爬环境检测。

从源码看,xhs/core.py 中XhsClient._pre_headers在每次请求前都会调用外部传入的sign回调(或内置快速签名),把返回的x-s、x-t写入请求头(xhs/core.py),可见签名函数是整个客户端可用的前置条件。

二、环境安装

在开始使用之前,需要依次安装 Python 依赖包、浏览器运行时以及 stealth 脚本:

pip install xhs # 下载 xhs 包 pip install playwright # 下载 playwright playwright install # 安装浏览器环境 curl -O <stealth.min.js 下载地址> # 下载 stealth.min.js

说明:

  • xhs包已发布在 PyPI,可直接通过pip安装;安装后可从xhs导入XhsClient、异常类等(参见 xhs/init.py)。
  • playwright install会为 Playwright 下载配套的 Chromium 浏览器内核,签名脚本依赖真实浏览器环境。
  • stealth.min.js来自requireCool/stealth.min.js项目,下载后需要记录其本地绝对路径,后续签名脚本与 Flask 服务中都要引用该路径。

三、基础使用:本地签名 + XhsClient

3.1 cookie 的三个必需字段

使用XhsClient前,请先从浏览器(登录小红书网页版后)复制 cookie 字符串。其中a1、web_session、webId三个字段为必需字段,缺失会导致签名或请求异常。从 xhs/help.py 的update_session_cookies_from_cookie实现可见:当 cookie 中缺少a1或webId时,客户端会自动补充内置的默认值;但为了签名稳定,仍建议使用真实登录后浏览器产生的 cookie。

3.2 本地签名函数示例

完整可运行示例见 example/basic_usage.py,其核心sign函数流程如下:

  1. 启动无头 Chromium,创建浏览器上下文;
  2. 通过browser_context.add_init_script(path=stealth_js_path)在页面加载前注入 stealth 脚本;
  3. 打开小红书首页https://www.xiaohongshu.com并写入a1cookie;
  4. reload()后sleep(1)等待环境就绪(原注释提示:若不 sleep 签名获取可能失败,失败频繁时可适当调长);
  5. 通过context_page.evaluate("([url, data]) => window._webmsxyw(url, data)", [uri, data])调用页面内 JS 签名函数,返回X-s与X-t;
  6. 整个函数包在 10 次重试循环中,捕获异常后重试,最终失败则抛出异常。

签名函数返回格式必须为:

{ "x-s": encrypt_params["X-s"], "x-t": str(encrypt_params["X-t"]) }

3.3 组装客户端并发起请求

import datetime import json from time import sleep from playwright.sync_api import sync_playwright from xhs import DataFetchError, XhsClient, help # ... 上述 sign 函数定义 ... if __name__ == '__main__': cookie = "please get cookie from your website" # 替换为你的真实 cookie xhs_client = XhsClient(cookie, sign=sign) print(datetime.datetime.now()) for _ in range(10): # 即便 sign 内部做了重试,仍有签名失败的可能,这里再包一层重试 try: note = xhs_client.get_note_by_id("6505318c000000001f03c5a6", "xsec_token of the note") print(json.dumps(note, indent=4)) print(help.get_imgs_url_from_note(note)) break except DataFetchError as e: print(e) print("失败重试一下下")

要点:

  • XhsClient构造函数支持cookie、user_agent、timeout、proxies、sign等参数(xhs/core.py),其中sign即我们自定义的签名函数,签名函数签名约定为sign(uri, data, a1, web_session)。
  • get_note_by_id(note_id, xsec_token)用于按笔记 ID 拉取笔记详情(xhs/core.py),xsec_token是笔记分享链接中携带的鉴权参数。
  • help.get_imgs_url_from_note(note)可从笔记数据中提取图片直链列表(xhs/help.py)。
  • 建议对外层调用也做重试,因为window._webmsxyw is not a function或页面跳转等偶发错误依然存在。

四、进阶使用:将 Playwright 封装为统一签名服务

本地每次请求都启动一次浏览器开销大、速度慢,且多账号场景下每个进程维护一个浏览器非常浪费。进阶方案是:将 Playwright 浏览器常驻在一个 Flask 服务进程中,主程序改用requests调用该服务获取签名。这样浏览器只启动一次,多个调用方共享同一个签名通道。

4.1 多账号使用时的关键约束

多账号使用统一签名服务时,请确保 cookie 中的a1字段统一,防止签名一直出现错误。原因在于:签名算法生成x-s时会将当前页面的a1值混入计算(源码中x-s-common的x5字段即取自 cookie 的a1,参见 xhs/help.py),若调用方传入的a1与服务端浏览器上下文中的a1不一致,签名校验就会失败。

4.2 方式一:使用 Docker 一键启动

项目提供了现成的 Docker 镜像reajason/xhs-api:latest(构建相关配置见 xhs-api/Dockerfile),一条命令即可启动签名服务:

docker run -it -d -p 5005:5005 reajason/xhs-api:latest

服务启动后会在日志中打印当前浏览器 cookie 的a1值,推荐将自己 cookie 中的a1与服务端设置成一致,随后即可通过XhsClient使用。

4.3 方式二:本机启动 Flask 签名服务

如果在本机直接启动 Flask,需要安装如下依赖:

pip install flask, gevent, requests

完整示例见 example/basic_sign_server.py,服务端逻辑要点:

  1. 启动常驻的 Playwright 实例,注入 stealth 脚本并跳转小红书首页(等待数秒后 reload 一次);
  2. 从浏览器上下文中读取 cookie,取到a1值打印出来,提示调用方对齐a1;
  3. 提供POST /sign接口:接收{uri, data, a1, web_session},调用window._webmsxyw返回{x-s, x-t};
  4. 提供GET /a1接口返回当前服务端的a1,便于调用方查询对齐。
# 简化版核心逻辑 @app.route("/sign", methods=["POST"]) def sign_endpoint(): json_body = request.json encrypt_params = context_page.evaluate( "([url, data]) => window._webmsxyw(url, data)", [json_body["uri"], json_body["data"]] ) return { "x-s": encrypt_params["X-s"], "x-t": str(encrypt_params["X-t"]), }

仓库内 xhs-api/app.py 还额外实现了a1动态切换:当请求携带的a1与当前服务端不一致时,自动写入新a1cookie 并 reload 页面后再签名,适合多账号轮换场景。

4.4 客户端对接签名服务

完整示例见 example/basic_sign_usage.py,此时主程序不再依赖 Playwright,只需把sign函数改为 HTTP 调用:

import datetime import json import requests from xhs import XhsClient def sign(uri, data=None, a1="", web_session=""): # 填写自己的 flask 签名服务端口地址 res = requests.post( "http://localhost:5005/sign", json={"uri": uri, "data": data, "a1": a1, "web_session": web_session} ) signs = res.json() return { "x-s": signs["x-s"], "x-t": signs["x-t"] } if __name__ == '__main__': cookie = "please get cookie from your website" xhs_client = XhsClient(cookie, sign=sign) note_info = xhs_client.get_note_by_id("63db8819000000001a01ead1") print(datetime.datetime.now()) print(json.dumps(note_info, indent=2)) print(xhs.help.get_imgs_url_from_note(note_info))

这种"浏览器服务端 + requests 客户端"的架构与项目测试代码中的做法一致:tests/test_xhs.py 的 fixture 正是向本地localhost:5555/sign发起 HTTP 请求获取签名后构造XhsClient,验证了该模式可直接用于自动化测试与批量任务。

五、签名服务与 XhsClient 的配合原理

从源码理解整条调用链,有助于排查问题:

  1. XhsClient构造时将外部sign保存在self.external_sign(xhs/core.py);
  2. 每次get/post请求前调用_pre_headers,若非快速签名模式,则执行self.external_sign(url, data, a1=self.cookie_dict.get("a1"), web_session=self.cookie_dict.get("web_session", ""))(xhs/core.py);
  3. 客户端会自动从 cookie 中提取a1和web_session传给签名服务,因此签名服务端拿到的a1就是当前账号 cookie 中的a1——这就是"必须统一 a1"的底层原因;
  4. 若签名缺失或错误,服务端响应码命中ErrorEnum.SIGN_FAULT时会抛出SignError(xhs/core.py),高频请求触发风控时则抛出IPBlockError,可据此在代码中分类处理。

六、常见问题与注意事项

  • a1不一致导致签名失败:检查调用方 cookie 与签名服务浏览器上下文的a1是否一致,优先统一。
  • window._webmsxyw is not a function:多为页面未加载完成或跳转异常,可在 reload 后增加sleep时长,并加失败重试。
  • stealth.min.js 路径:示例中硬编码了作者本机的绝对路径(如/Users/reajason/ReaJason/xhs/tests/stealth.min.js),实际使用请替换为你下载文件的真实路径。
  • 启动浏览器失败:确认已执行playwright install完成浏览器内核下载;本地调试时可把headless=False打开浏览器观察页面状态(示例源码注释中亦有提示)。
  • 请求异常类型:DataFetchError(通用数据错误)、IPBlockError(IP 被风控拦截)、SignError(签名错误)、NeedVerifyError(出现验证码,携带Verifytype/Verifyuuid信息),均可从xhs包导入并针对性捕获(参见 xhs/exception.py 及 xhs/core.py)。

七、结语

本文完整梳理了xhs的两条使用路径:本地 Playwright 取签的快速上手,以及 Flask 统一签名服务的生产化部署。前者适合单机、低频场景,后者适合多账号、批量请求场景。配合XhsClient提供的笔记、搜索、评论、关注、发布等接口(详见 xhs/core.py),你可以在统一签名架构之上自由构建自己的采集或自动化应用。更多示例(手机号登录、扫码登录、创作服务平台登录)可参考 example/ 目录下的其他脚本。

  • 网页爬虫

【免费下载链接】xhs

基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/

项目地址:https://gitcode.com/gh_mirrors/xh/xhs
点击查看免费下载

相关推荐

上一篇:如何使用ddt4all轻松读取汽车故障码(DTC)?新手必备教程
下一篇:Superstruct文档验证:PDF与Office文件的内容提取

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询