rebang.today — API Reverse Engineering
从首页 HTML 与 JS bundle 逆向出聚合热榜 API:接口路径、参数 schema、签名真相与全部踩坑记录(已实测验证)。
1. Overview / TL;DR
rebang.today(今日热榜)是一个多平台热榜聚合站,聚合了小红书、微博、知乎、 B 站、抖音、36氪等平台的热搜/热榜。目标是从它的前端产物中逆向出 小红书热榜的正确抓取方式——不依赖浏览器自动化,直接用 curl 打接口。
核心结论:接口是 GET https://rebang.today/api/latest-list,
小红书热榜的正确参数为
tab=xiaohongshu&sub_tab=hot-search&page=1&page_size=50——
无需任何签名,带浏览器 UA 裸请求即可拿到完整 JSON。
| 关键事实 | 值 |
|---|---|
| API 端点 | /api/latest-list(同源路径,非 api.rebang.today 子域) |
| 小红书参数 | tab=xiaohongshu + sub_tab=hot-search(子榜「热点」) |
| 单页条数 | 实际最多 20 条(schema 上限 50,has_more=false 即榜单结束) |
| 签名 | 机制存在(X-Sign / X-Timestamp / X-Nonce / X-Version),但密钥不在客户端 → 无需签名 |
| 错误码 | 1001 invalid request parameter · 1025 榜单不存在 · 1026 快照过期 |
2. 为什么选聚合站
直接抓小红书官方热榜接口需要处理签名、cookie、风控等一堆问题; 聚合站已经把这些脏活做完了,而且天然覆盖多个平台,一个接口全家桶。
需要签名参数(x-s / x-t 等)、可能要求登录 cookie、有风控与频控, 接口路径不公开、经常变动——逆向成本高。
前端是标准 Next.js/React 产物,接口逻辑在 JS bundle 里可读; 一个端点覆盖 N 个平台;无需登录、无需签名,纯 curl 即可。
代价是数据经过聚合站二次加工(热度单位、排序、标签),且接口随时可能改版。 但作为「快速获取热榜话题」的场景,性价比远高于啃官方接口。
3. 逆向过程(方法学)
整体思路:下载目标站点全部前端产物 → 用 grep/python 从 bundle 里提取 schema 与配置 → 构造请求验证。 全程不需要打开浏览器,省 token、可脚本化:
-
1
抓首页 HTML。
curl -s https://rebang.today/ -o /tmp/rebang.html。 Next.js 的 RSC payload 里直接内嵌了全部 tab 配置(含平台 key、id、子榜结构、品牌色)。 -
2
下载全部 JS chunk。
从 HTML 里提取
_next/static/chunks/*.js脚本 URL,逐个下载到/tmp/rbjs/(共 35 个)。接口路径、zod schema、签名逻辑都在这些 bundle 里。 -
3
grep 提取 schema 与配置。
搜
latestList、PROXY_PATH、NEXT_PUBLIC_*、latestListQuerySchema等关键词,定位参数校验逻辑与代理路径。 -
4
构造请求验证。
用 curl 直接打
/api/latest-list,根据错误码(1001/1025)迭代参数,直到返回 200。
# 定位「小红书」tab 配置(RSC payload 里 key/id/品牌色)
grep -o '"key":"[a-z-]*"' /tmp/rebang.html | sort -u
# 找接口路径与 schema(chunk 里 latestListQuerySchema)
grep -o 'latestListQuerySchema[^;]\{0,120\}' /tmp/rbjs/*.js | head
# 找代理路径配置
grep -o 'PROXY_PATH:"[^"]*"' /tmp/rbjs/*.js | sort -u
# 环境变量清单(确认是否有签名密钥暴露)
grep -o 'NEXT_PUBLIC[A-Z_]*' /tmp/rbjs/*.js | sort -u
彩蛋:分析过程中曾定位神秘数字 905020——最终发现它只是某个
process.env polyfill 模块入口调用的首个实参,与业务无关。
逆向时很容易被这类「看起来有意义的数字」带偏,先判断它所在的模块角色再深挖。
4. API 端点与参数
4.1 参数 schema(从 bundle 中 latestListQuerySchema 还原)
| 参数 | 类型 | 说明 |
|---|---|---|
tab | string | 必填。平台 key,如 xiaohongshu / weibo / zhihu。用数字 id(如 100)会报 1001 |
sub_tab | string | 平台内子榜 key。小红书是 hot-search(「热点」);父 tab 没有顶层榜单,漏了它必报 1025 |
page | number | 页码,从 1 开始 |
page_size | number | ≤ 50(超了报 1001)。实测每榜最多返回 20 条 |
snapshot_id | string | 翻页令牌(stat: 前缀的 base64),page>1 时必需;秒级过期 |
curl -s 'https://rebang.today/api/latest-list?tab=xiaohongshu&sub_tab=hot-search&page=1&page_size=50' \
-H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' \
-H 'Accept: application/json' | python3 -m json.tool | head -60
{
"code": 200,
"data": {
"list": [
{
"title": "用万能旅行拍照姿势美美出片",
"extra_info": { "display_text_items": [{ "text": "920.8w" }] },
"www_url": "https://www.xiaohongshu.com/search_result?keyword=...",
"hot": true
}
],
"next_refresh_time": 1786811108,
"snapshot_id": "stat:eyJ0YWIiOiJ4aWFvaG9uZ3NodSIs...",
"has_more": false
}
}
注意热度值在 extra_info.display_text_items[].text 里(形如
"920.8w",w = 万),hot: true 表示平台置顶/热推标签。
5. 签名机制真相
前端 bundle 里确实存在一套 HMAC-SHA256 签名机制:请求需要带
X-Sign / X-Timestamp / X-Nonce / X-Version
四个头,服务端校验。这是不少 Next.js 站点的标准防刷配置。
但在客户端产物里搜 NEXT_PUBLIC_API_SIGN_SECRET 等密钥变量——
一个都没有。签名密钥只存在于服务端,浏览器端实际发的请求也不带签名头。
结论:裸请求即可,无需计算签名。判断方法很简单——在浏览器 DevTools 里看真实请求头,
或搜 bundle 里是否有 NEXT_PUBLIC_* 密钥变量;两者都没有 → 不用签名。
若将来接口开始校验签名(返回 401/403 或新的错误码),需要重新评估:要么服务端下发密钥, 要么换数据源。本笔记的抓取脚本会在那时失效——这是所有逆向接口的宿命。
6. 错误码与常见坑
| 错误码 | 消息 | 含义 / 触发条件 |
|---|---|---|
1001 | invalid request parameter | 参数不合法:page_size>50、tab 用了数字 id、参数拼写错误 |
1025 | 榜单不存在 | 该 tab 没有顶层榜单(小红书必须加 sub_tab=hot-search) |
1026 | 榜单快照已过期 | snapshot_id 过期:必须拿到 snapshot 后立刻翻页(同一秒内) |
血泪坑位清单(全部实测踩过)
- 父 tab 没有榜单!小红书 tab 下只有子榜「热点」(hot-search),不带 sub_tab 必报 1025「榜单不存在」——这是最隐蔽的坑。
- page_size 有上限:传 100 直接报 1001。schema 上限 50,实际每榜 20 条封顶。
- tab 用英文字符串:RSC payload 里虽然给了 id=100,但接口只认 key=
xiaohongshu。 - snapshot_id 秒级过期:先拿 page1 的 snapshot,再单独 curl page2——中间隔了几秒就报 1026。翻页必须脚本内连续请求。
- has_more=false 就是终局:榜单就 20 条,翻页也不会更多,别白费功夫。
- 必须带浏览器 UA:无 UA 或默认 python-requests UA 可能被拒。
排错套路:先单独验 tab(报 1025 → 缺 sub_tab;报 1001 → tab 写法不对),
再验 page_size(报 1001 → 超上限),最后才考虑翻页。
7. 平台 tab 结构
从首页 RSC payload 的 tab 配置可还原每个平台的 key 与子榜结构。 已确认的映射:
| 平台 | tab key | 子榜示例 |
|---|---|---|
| 小红书 | xiaohongshu(id=100,品牌色 #FF2442) | hot-search 热点 |
| 微博 | weibo(待验证) | hot(推测) |
| 知乎 | zhihu(待验证) | — |
发现新平台的正确姿势(不用猜):
# 1. 找所有 tab key
grep -o '"key":"[a-z-]*"' /tmp/rebang.html | sort -u
# 2. 找小红书的子榜结构("id":100 附近的 source_tabs / children 数组)
grep -o '.\{0,200\}"id":100.\{0,600\}' /tmp/rebang.html | head -1 | python3 -m json.tool 2>/dev/null || true
# 3. 直接试错:tab=weibo&sub_tab=hot → 200 或 1025 迭代
curl -s 'https://rebang.today/api/latest-list?tab=weibo&sub_tab=hot&page=1&page_size=20' \
-H 'User-Agent: Mozilla/5.0' | head -c 300
8. 可复用脚本
本次逆向成果已固化为 Hermes skill
rebang-today-hot-list(含完整踩坑记录),并附带可直接运行的抓取脚本:
- Skill:
~/.hermes/skills/data-fetching/rebang-today-hot-list/ - 脚本:
scripts/fetch_rebang.py(工作区副本:/Users/spark/Source/rebang-hot-list/fetch_rebang.py)
# 小红书热榜(默认输出 编号.标题(热度) + 原站链接)
python3 fetch_rebang.py --tab xiaohongshu --sub-tab hot-search
# 原始 JSON 输出(便于二次分析)
python3 fetch_rebang.py --tab xiaohongshu --sub-tab hot-search --json
# 翻页(注意:快照秒级过期,脚本内已自动处理连续请求)
python3 fetch_rebang.py --tab xiaohongshu --sub-tab hot-search --page 2
以后在对话里说「抓一下小红书热榜」即可复用该 skill——直接跑脚本,不再重新逆向,token 开销降低一个数量级。
References
-
1rebang.today — 今日热榜聚合站本笔记逆向的目标站点。首页 HTML 的 RSC payload 内含全部平台 tab 配置。
-
2小红书 xiaohongshu.com数据源头平台。聚合站数据最终来自小红书热榜(热点榜)。
-
3Hermes Agent 文档Skill 系统的官方文档——本次逆向流程以 skill 形式固化(rebang-today-hot-list)。