This post is also available in English and alternative languages.
用户使用手机客户端浏览小红书视频笔记时,所获取的视频是无水印的。但保存至本地或者通过网页端浏览时,所获取的视频是含水印的。这篇文章将介绍如何解析小红书笔记,获取含水印视频和无水印视频的 URL。
以这条笔记为例,其笔记 id 为 65e2c4fb00000000030367bd
。
获取含水印视频 URL
找到页面 Open Graph 协议的视频标签
1
| <meta name="og:video" content="">
|
里面的 content
属性就是含水印视频的 URL,格式如下
1
| https://sns-video-hw.xhscdn.com/stream/110/259/01e5e2b96c2b17eb010371038dfdd2b1c0_259.mp4
|
获取无水印视频 URL
页面源代码中搜索 originVideoKey
,找到如下 JSON 字段
1 2 3
| { "originVideoKey":"spectrum\u002F1040g35830vr3bg1860005o6qr60o57fr83a7isg" }
|
其中的 \u002F
是 Unicode 编码的 /
,你可以用 jq
命令来解码。
1 2 3 4
| ~ % echo '{"originVideoKey":"spectrum\u002F1040g35830vr3bg1860005o6qr60o57fr83a7isg"}' | jq { "originVideoKey": "spectrum/1040g35830vr3bg1860005o6qr60o57fr83a7isg" }
|
然后拼接在 https://sns-video-bd.xhscdn.com/
的尾部,得到无水印视频 URL
1
| https://sns-video-bd.xhscdn.com/spectrum/1040g35830vr3bg1860005o6qr60o57fr83a7isg
|
网上的小红书解析工具会返回一个路径为 258
的 URL,与上述 URL 不同,但是仍然有效,不知道是怎么构造出来的。对比两个 URL 的差异如下:
1 2 3
| 不同位 1 1111 1 有水印 https://sns-video-hw.xhscdn.com/stream/110/259/01e5e2b96c2b17eb010371038dfdd2b1c0_259.mp4 无水印 https://sns-video-hw.xhscdn.com/stream/110/258/01e5e2b96c2b17eb010371038dfdd239f3_258.mp4
|
简单的 Python 脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import requests import re import json
link = 'https://www.xiaohongshu.com/explore/65e2c4fb00000000030367bd'
def work(url: str) -> dict: r = requests.get(url) if r.status_code == 200:
url_with_watermark = re.findall(r'<meta name="og:video" content="(.*?)">', r.text) if url_with_watermark: url_with_watermark = url_with_watermark[0] else: url_with_watermark = None key = re.findall(r'{\"originVideoKey\":\".*?\"}', r.text) if key: url_without_watermark = "http://sns-video-bd.xhscdn.com/" + json.loads(key[0])["originVideoKey"] else: url_without_watermark = None return { "url_with_watermark": url_with_watermark, "url_without_watermark": url_without_watermark } else: print(f"status code: {r.status_code}") return { "url_with_watermark": None, "url_without_watermark": None }
print(work(link))
|