diff --git a/README.md b/README.md
index 14b45d4..00b6169 100644
--- a/README.md
+++ b/README.md
@@ -458,6 +458,12 @@ async def example():
| folder_mode |
bool |
是否将每个作品的文件储存至单独的文件夹;文件夹名称与文件名称保持一致 |
diff --git a/README_EN.md b/README_EN.md
index ef235c3..cbde0fa 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -17,42 +17,42 @@
-🔥 RedNote Link Extraction/Content Collection Tool:Extract account-published, favorites, and liked works links; extract search result works links and user links; collect RedNote works information; extract RedNote works download addresses; download RedNote watermark-free works files!
+🔥 RedNote Link Extraction/Content Collection Tool:Extract account-published, favorites, and liked notes links; extract search result notes links and user links; collect RedNote notes information; extract RedNote notes download addresses; download RedNote watermark-free notes files!
🔥 "RedNote", "XiaoHongShu" and "小红书" have the same meaning, and this project is collectively referred to as "RedNote".
⭐ Due to the author's limited energy, I was unable to update the English document in a timely manner, and the content may have become outdated, partial translation is machine translation, the translation result may be incorrect, Suggest referring to Chinese documentation. If you want to contribute to translation, we warmly welcome you.
📑 Project Features
Program Features and User Script Features (Click to Expand)
Program Features
-- ✅ Collect RedNote works information
-- ✅ Extract RedNote works download addresses
-- ✅ Download RedNote watermark-free works files
+- ✅ Collect RedNote notes information
+- ✅ Extract RedNote notes download addresses
+- ✅ Download RedNote watermark-free notes files
- ✅ Download RedNote livePhoto files (watermark)
-- ✅ Automatically skip already downloaded works files
-- ✅ works file integrity handling mechanism
-- ✅ Customizable image works file download format
-- ✅ Persistently store works information to files
-- ✅ Store works files to a separate folder
-- ✅ Background clipboard monitoring for works download
-- ✅ Record downloaded works IDs
-- ✅ Support command line for downloading works files
+- ✅ Automatically skip already downloaded notes files
+- ✅ notes file integrity handling mechanism
+- ✅ Customizable image notes file download format
+- ✅ Persistently store notes information to files
+- ✅ Store notes files to a separate folder
+- ✅ Background clipboard monitoring for notes download
+- ✅ Record downloaded notes IDs
+- ✅ Support command line for downloading notes files
- ✅ Read cookies from browser
- ✅ Customizable file name format
- ✅ Support API call functionality
- ✅ Support MCP call functionality
- ✅ Support file breakpoint resume download
-- ✅ Intelligent recognition of works file types
+- ✅ Intelligent recognition of notes file types
- ✅ Supports author alias configuration
- ✅ Automatic author nickname updates
Script Features
-- ✅ Download RedNote watermark-free works files
-- ✅ Extract discovery page works links
-- ✅ Extract account-published works links
-- ✅ Extract account-favorited works links
-- ✅ Extract account-liked works links
-- ✅ Extract account-board works links
-- ✅ Extract search result works links
+- ✅ Download RedNote watermark-free notes files
+- ✅ Extract discovery page notes links
+- ✅ Extract account-published notes links
+- ✅ Extract account-favorited notes links
+- ✅ Extract account-liked notes links
+- ✅ Extract account-board notes links
+- ✅ Extract search result notes links
- ✅ Extract search result user links
@@ -65,17 +65,17 @@
🔗 Supported Links
-https://www.xiaohongshu.com/explore/WorksID?xsec_token=XXX
-https://www.xiaohongshu.com/discovery/item/WorksID?xsec_token=XXX
-https://www.xiaohongshu.com/user/profile/AuthorID/WorksID?xsec_token=XXX
+https://www.xiaohongshu.com/explore/NoteID?xsec_token=XXX
+https://www.xiaohongshu.com/discovery/item/NoteID?xsec_token=XXX
+https://www.xiaohongshu.com/user/profile/AuthorID/NoteID?xsec_token=XXX
https://xhslink.com/ShareCode
-Supports entering multiple works links at once, separated by spaces; the program will automatically extract valid links without additional processing!
+Supports entering multiple notes links at once, separated by spaces; the program will automatically extract valid links without additional processing!
🪟 About the Terminal
⭐ It is recommended to use the Windows Terminal (default terminal for Windows 11) to run the program for the best display effect!
🥣 Usage
-If you only need to download watermark-free works files, it is recommended to choose Program Run; if you have other needs, it is recommended to choose Source Code Run!
+If you only need to download watermark-free notes files, it is recommended to choose Program Run; if you have other needs, it is recommended to choose Source Code Run!
Starting from version 2.2, if there are no abnormalities in project functionality, there is no need to handle cookies separately!
🖱 Program Run
⭐ Mac OS, Windows 10 and above users can go to Releases or Actions to download the program package, unzip it, open the program folder, and double-click to run main to use.
@@ -124,10 +124,10 @@
-When running the project via Docker, the command line call mode is not supported. The clipboard reading and clipboard monitoring functions are unavailable, but pasting content works fine. Please provide feedback if other features are not functioning properly!
+When running the project via Docker, the command line call mode is not supported. The clipboard reading and clipboard monitoring functions are unavailable, but pasting content notes fine. Please provide feedback if other features are not functioning properly!
🛠 Command Line Mode
-The project supports command line mode. If you want to download specific images from a text and image works, you can use this mode to set the image sequence number you want to download!
-Note: When the --index parameter is not set, multiple works links can be passed in. All links must be enclosed in quotation marks and separated by spaces. When the --index parameter is set, multiple works links are not supported. Even if multiple links are passed in, the program will only process the first link!
+The project supports command line mode. If you want to download specific images from a text and image notes, you can use this mode to set the image sequence number you want to download!
+Note: When the --index parameter is not set, multiple notes links can be passed in. All links must be enclosed in quotation marks and separated by spaces. When the --index parameter is set, multiple notes links are not supported. Even if multiple links are passed in, the program will only process the first link!
The bool type parameters support setting with true, false, 1, 0, yes, no, on or off (case insensitive).
Read Browser Cookies
This feature is no longer available. Please refer to the Obtain Cookie tutorial!
@@ -164,19 +164,19 @@
Note: Using the XHS-Downloader user script to batch extract works links, in combination with the XHS-Downloader program, can achieve batch downloading of watermark-free works files!
+Note: Using the XHS-Downloader user script to batch extract notes links, in combination with the XHS-Downloader program, can achieve batch downloading of watermark-free notes files!
-- When downloading watermark-free works from Xiaohongshu, the script requires time to process the files. Please wait for a moment and do not click the download button multiple times.
-- When extracting links for posts, collects, likes, and board from an account, the script can automatically scroll the page until all works are loaded.
-- When extracting recommended works links, search works, and user links, the script can automatically scroll a specified number of times to load more content. The default number of page scrolls is 50.
+- When downloading watermark-free notes from Xiaohongshu, the script requires time to process the files. Please wait for a moment and do not click the download button multiple times.
+- When extracting links for posts, collects, likes, and board from an account, the script can automatically scroll the page until all notes are loaded.
+- When extracting recommended notes links, search notes, and user links, the script can automatically scroll a specified number of times to load more content. The default number of page scrolls is 50.
- The automatic scrolling page function is turned off by default; Users can freely open and modify the number of times the page is scrolled, and the modification will take effect immediately.
- If the automatic page scroll feature is not enabled, users need to manually scroll the page to load more content before performing other actions.
-- Support packaging and downloading of work files; This feature is enabled by default, and works from multiple files will be downloaded in compressed file format
+- Support packaging and downloading of work files; This feature is enabled by default, and notes from multiple files will be downloaded in compressed file format
- When pushing download tasks to the server, the file format, name rules, etc. settings will be based on the server configuration file settings
- Using global proxy tools may cause script download failures. If there are issues, please try disabling the proxy tool. If necessary, contact the author for feedback.
- XHS-Downloader userscript only implements the data collection functionality for visible content and does not include any paid or cracked features.
@@ -380,19 +380,19 @@ async def example():
| work_path |
str |
-Root path for saving works data/files |
+Root path for saving notes data/files |
Project root path/Volume |
| folder_name |
str |
-Name of the folder for storing works files |
+Name of the folder for storing notes files |
Download |
| name_format |
str |
-#Format of works file name, separated by spaces between fields, supports fields: 收藏数量、评论数量、分享数量、点赞数量、作品标签、作品ID、作品标题、作品描述、作品类型、发布时间、最后更新时间、作者昵称、作者ID |
+#Format of notes file name, separated by spaces between fields, supports fields: 收藏数量、评论数量、分享数量、点赞数量、作品标签、作品ID、作品标题、作品描述、作品类型、发布时间、最后更新时间、作者昵称、作者ID |
发布时间 作者昵称 作品标题 |
@@ -434,25 +434,25 @@ async def example():
| record_data |
bool |
-Whether to save works data to a file, saved in SQLite format |
+Whether to save notes data to a file, saved in SQLite format |
false |
| image_format |
str |
-Download format for image works files, supported: AUTO、PNG、WEBP、JPEG、HEIC Some works do not have files in HEIC format, and the downloaded files may be in WEBP format When set toAUTO, it represents dynamic format, and the actual format depends on the server's response data |
+Download format for image notes files, supported: AUTO、PNG、WEBP、JPEG、HEIC Some notes do not have files in HEIC format, and the downloaded files may be in WEBP format When set toAUTO, it represents dynamic format, and the actual format depends on the server's response data |
JPEG |
| image_download |
bool |
-Switch for downloading image and atlas works files |
+Switch for downloading image and atlas notes files |
true |
| video_download |
bool |
-Switch for downloading video works files |
+Switch for downloading video notes files |
true |
@@ -462,27 +462,33 @@ async def example():
| false |
+| video_preference |
+str |
+Video notes file download preference; Meaning: resolution: resolution priority; bitrate: bitrate priority; size: file size priority |
+resolution |
+
+
| folder_mode |
bool |
-Whether to store each works files in a separate folder; the folder name matches the file name |
+Whether to store each notes files in a separate folder; the folder name matches the file name |
false |
| download_record |
bool |
-Do record the ID of successfully downloaded works? If enabled, the program will automatically skip downloading works with records |
+Do record the ID of successfully downloaded notes? If enabled, the program will automatically skip downloading notes with records |
true |
| author_archive |
bool |
-#Whether to save each author's works into a separate folder; The folder name is authorID_nickname |
+#Whether to save each author's notes into a separate folder; The folder name is authorID_nickname |
false |
| write_mtime |
bool |
-Whether to modify the modified time attribute of the works file to the publication time of the works. |
+Whether to modify the modified time attribute of the notes file to the publication time of the notes. |
false |
@@ -507,11 +513,11 @@ async def example():
评论数量: Number of Comments
分享数量: Number of Shares
点赞数量: Number of Likes
-作品标签: Works Tags
-作品ID: Works ID
-作品标题: Works Title
-作品描述: Works Description
-作品类型: Works Type
+作品标签: Notes Tags
+作品ID: Notes ID
+作品标题: Notes Title
+作品描述: Notes Description
+作品类型: Notes Type
发布时间: Publish Time
最后更新时间: Last Updated Time
作者昵称: Author Nickname
@@ -520,7 +526,7 @@ async def example():
-
When author_archive is set to true, the program will store each author's works in dedicated folders. If an author's nickname changes, the program automatically updates the nickname portion in existing downloaded filenames!
+
When author_archive is set to true, the program will store each author's notes in dedicated folders. If an author's nickname changes, the program automatically updates the nickname portion in existing downloaded filenames!
Additionally, you can configure author aliases through the mapping_data parameter. When an alias is set, the program will use your custom alias instead of the original nickname in filenames!
@@ -536,14 +542,14 @@ async def example():
- Check
Preserve log
- In the
Filter input box, enter cookie-name:web_session
- Select the
Fetch/XHR filter
-- Click on any piece of works on the RedNote page
+- Click on any piece of notes on the RedNote page
- In the
Network tab, select any data packet (if no packets appear, repeat step 7)
- Copy and paste the entire Cookie into the program or configuration file
🗳 Download Records
-XHS-Downloader will store the IDs of downloaded works in a database. When downloading the same works again, XHS-Downloader will automatically skip the file download (even if the works file does not exist). If you want to re-download the works file, please delete the corresponding works ID from the database and then use XHS-Downloader to download the works file again!
+XHS-Downloader will store the IDs of downloaded notes in a database. When downloading the same notes again, XHS-Downloader will automatically skip the file download (even if the notes file does not exist). If you want to re-download the notes file, please delete the corresponding notes ID from the database and then use XHS-Downloader to download the notes file again!
This feature is enabled by default. If it is turned off, XHS-Downloader will check if the file exists. If the file exists, it will skip the download!
Build of Executable File Guide
@@ -710,7 +716,7 @@ repository to execute the build process
- The author of this project will not provide a paid version of the XHS-Downloader project, nor will they offer any commercial services related to the XHS-Downloader project.
- Any secondary development, modification, or compilation based on this project is unrelated to the original author. The original author assumes no liability for any consequences resulting from such secondary development. Users bear full responsibility for all outcomes arising from such modifications.
- This project grants no patent licenses; if the use of this project leads to patent disputes or infringement, the user bears all associated risks and responsibilities. Without written authorization from the author or rights holder, users may not use this project for any commercial promotion, marketing, or re-licensing.
-- The author reserves the right to terminate service to any user who violates this disclaimer at any time and may require them to destroy all obtained code and derivative works.
+- The author reserves the right to terminate service to any user who violates this disclaimer at any time and may require them to destroy all obtained code and derivative notes.
- The author reserves the right to update this disclaimer at any time without prior notice. Continued use of the project constitutes acceptance of the revised terms.
Before using the code and functionalities of this project, please carefully consider and accept the above disclaimer. If you have any questions or disagree with the statement, please do not use the code and functionalities of this project. If you use the code and functionalities of this project, it is considered that you fully understand and accept the above disclaimer, and willingly assume all risks and consequences associated with the use of this project.
diff --git a/source/CLI/main.py b/source/CLI/main.py
index 9c72232..588d2f0 100644
--- a/source/CLI/main.py
+++ b/source/CLI/main.py
@@ -289,6 +289,11 @@ class CLI:
"-ld",
type=bool,
)
+@option(
+ "--video_preference",
+ "-vp",
+ type=Choice(["resolution", "bitrate", "size"]),
+)
@option(
"--download_record",
"-dr",
diff --git a/source/TUI/setting.py b/source/TUI/setting.py
index 42716d4..ba24c3a 100644
--- a/source/TUI/setting.py
+++ b/source/TUI/setting.py
@@ -180,6 +180,10 @@ class Setting(Screen):
_("程序语言"),
classes="params",
),
+ Label(
+ _("视频下载偏好"),
+ classes="params",
+ ),
classes="horizontal-layout",
),
Label(),
@@ -196,6 +200,12 @@ class Setting(Screen):
allow_blank=False,
id="language",
),
+ Select.from_values(
+ ["resolution", "bitrate", "size"],
+ value=self.data["video_preference"],
+ allow_blank=False,
+ id="video_preference",
+ ),
classes="horizontal-layout",
),
Container(
@@ -235,7 +245,7 @@ class Setting(Screen):
"chunk": int(self.query_one("#chunk").value),
"max_retry": int(self.query_one("#max_retry").value),
"record_data": self.query_one("#record_data").value,
- "image_format": self.query_one("#image_format").value,
+ "image_format": self.query_one("#image_format").value.lower(),
"folder_mode": self.query_one("#folder_mode").value,
"language": self.query_one("#language").value,
"image_download": self.query_one("#image_download").value,
@@ -245,6 +255,7 @@ class Setting(Screen):
"author_archive": self.query_one("#author_archive").value,
"write_mtime": self.query_one("#write_mtime").value,
"script_server": self.query_one("#script_server").value,
+ "video_preference": self.query_one("#video_preference").value,
}
)
diff --git a/source/application/app.py b/source/application/app.py
index afab38e..5e91c3c 100644
--- a/source/application/app.py
+++ b/source/application/app.py
@@ -130,6 +130,7 @@ class XHS:
image_download=True,
video_download=True,
live_download=False,
+ video_preference="resolution",
folder_mode=False,
download_record=True,
author_archive=False,
@@ -160,6 +161,7 @@ class XHS:
image_download,
video_download,
live_download,
+ video_preference,
download_record,
folder_mode,
author_archive,
@@ -202,6 +204,7 @@ class XHS:
):
container["下载地址"] = self.video.deal_video_link(
data,
+ self.manager.video_preference,
)
container["动图地址"] = [
None,
diff --git a/source/application/video.py b/source/application/video.py
index fa91756..e7ac35a 100644
--- a/source/application/video.py
+++ b/source/application/video.py
@@ -46,6 +46,6 @@ class Video:
@staticmethod
def get_video_items(data: Namespace) -> list:
- h264 = data.safe_extract("video.media.stream.h264")
- h265 = data.safe_extract("video.media.stream.h265")
+ h264 = data.safe_extract("video.media.stream.h264", [])
+ h265 = data.safe_extract("video.media.stream.h265", [])
return [*h264, *h265]
diff --git a/source/module/manager.py b/source/module/manager.py
index b1c5917..6373841 100644
--- a/source/module/manager.py
+++ b/source/module/manager.py
@@ -66,6 +66,7 @@ class Manager:
image_download: bool,
video_download: bool,
live_download: bool,
+ video_preference: str,
download_record: bool,
folder_mode: bool,
author_archive: bool,
@@ -123,6 +124,7 @@ class Manager:
)
self.image_download = self.check_bool(image_download, True)
self.video_download = self.check_bool(video_download, True)
+ self.video_preference = self.check_video_preference(video_preference)
self.live_download = self.check_bool(live_download, True)
self.author_archive = self.check_bool(author_archive, False)
self.write_mtime = self.check_bool(write_mtime, False)
@@ -214,6 +216,12 @@ class Manager:
format_,
)
+ @staticmethod
+ def check_video_preference(preference: str) -> str:
+ if preference in {"resolution", "bitrate", "size"}:
+ return preference
+ return "resolution"
+
def __check_proxy(
self,
proxy: str,
diff --git a/source/module/settings.py b/source/module/settings.py
index e37170a..c3c1b50 100644
--- a/source/module/settings.py
+++ b/source/module/settings.py
@@ -27,6 +27,7 @@ class Settings:
"image_download": True, # 是否下载图文
"video_download": True, # 是否下载视频
"live_download": False, # 是否下载动图
+ "video_preference": "resolution", # 视频文件偏好
"folder_mode": False, # 文件夹归档模式
"download_record": True, # 是否记录下载历史
"author_archive": False, # 是否按作者归档
diff --git a/uv.lock b/uv.lock
index 5a082e0..fb21dbc 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1667,12 +1667,12 @@ requires-dist = [
{ name = "click", specifier = ">=8.3.1" },
{ name = "emoji", specifier = ">=2.15.0" },
{ name = "fastapi", specifier = ">=0.128.0" },
- { name = "fastmcp", specifier = ">=2.14.3" },
+ { name = "fastmcp", specifier = ">=2.14.4" },
{ name = "httpx", extras = ["socks"], specifier = ">=0.28.1" },
{ name = "lxml", specifier = ">=6.0.2" },
{ name = "pyperclip", specifier = ">=1.11.0" },
{ name = "pyyaml", specifier = ">=6.0.3" },
- { name = "textual", specifier = ">=7.3.0" },
+ { name = "textual", specifier = ">=7.4.0" },
{ name = "uvicorn", specifier = ">=0.40.0" },
{ name = "websockets", specifier = ">=16.0" },
{ name = "xhshow", specifier = ">=0.1.8" },