feat(app): 新增视频下载偏好设置

Closes #262
This commit is contained in:
Quan
2026-01-31 15:02:07 +08:00
parent c88bf2229e
commit fcb58e3c44
9 changed files with 106 additions and 66 deletions

View File

@@ -458,6 +458,12 @@ async def example():
<td align="center">false</td>
</tr>
<tr>
<td align="center">video_preference</td>
<td align="center">str</td>
<td align="center">视频作品文件下载偏好;含义:<code>resolution</code>:分辨率优先;<code>bitrate</code>:码率优先;<code>size</code>:文件大小优先</td>
<td align="center">resolution</td>
</tr>
<tr>
<td align="center">folder_mode</td>
<td align="center">bool</td>
<td align="center">是否将每个作品的文件储存至单独的文件夹;文件夹名称与文件名称保持一致</td>

View File

@@ -17,42 +17,42 @@
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/JoeanAmier/XHS-Downloader/total?style=flat-square&color=ffdd59">
</div>
<br>
<p>🔥 <b>RedNote Link Extraction/Content Collection Tool</b>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!</p>
<p>🔥 <b>RedNote Link Extraction/Content Collection Tool</b>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!</p>
<p>🔥 "RedNote", "XiaoHongShu" and "小红书" have the same meaning, and this project is collectively referred to as "RedNote".</p>
<p>⭐ 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.</p>
<h1>📑 Project Features</h1>
<details>
<summary>Program Features and User Script Features (Click to Expand)</summary>
<ul><b>Program Features</b>
<li>✅ Collect RedNote works information</li>
<li>✅ Extract RedNote works download addresses</li>
<li>✅ Download RedNote watermark-free works files</li>
<li>✅ Collect RedNote notes information</li>
<li>✅ Extract RedNote notes download addresses</li>
<li>✅ Download RedNote watermark-free notes files</li>
<li>✅ Download RedNote livePhoto files (watermark)</li>
<li>✅ Automatically skip already downloaded works files</li>
<li>works file integrity handling mechanism</li>
<li>✅ Customizable image works file download format</li>
<li>✅ Persistently store works information to files</li>
<li>✅ Store works files to a separate folder</li>
<li>✅ Background clipboard monitoring for works download</li>
<li>✅ Record downloaded works IDs</li>
<li>✅ Support command line for downloading works files</li>
<li>✅ Automatically skip already downloaded notes files</li>
<li>notes file integrity handling mechanism</li>
<li>✅ Customizable image notes file download format</li>
<li>✅ Persistently store notes information to files</li>
<li>✅ Store notes files to a separate folder</li>
<li>✅ Background clipboard monitoring for notes download</li>
<li>✅ Record downloaded notes IDs</li>
<li>✅ Support command line for downloading notes files</li>
<li>✅ Read cookies from browser</li>
<li>✅ Customizable file name format</li>
<li>✅ Support API call functionality</li>
<li>✅ Support MCP call functionality</li>
<li>✅ Support file breakpoint resume download</li>
<li>✅ Intelligent recognition of works file types</li>
<li>✅ Intelligent recognition of notes file types</li>
<li>✅ Supports author alias configuration</li>
<li>✅ Automatic author nickname updates</li>
</ul>
<ul><a href="#user-scripts"><b>Script Features</b></a>
<li>✅ Download RedNote watermark-free works files</li>
<li>✅ Extract discovery page works links</li>
<li>✅ Extract account-published works links</li>
<li>✅ Extract account-favorited works links</li>
<li>✅ Extract account-liked works links</li>
<li>✅ Extract account-board works links</li>
<li>✅ Extract search result works links</li>
<li>✅ Download RedNote watermark-free notes files</li>
<li>✅ Extract discovery page notes links</li>
<li>✅ Extract account-published notes links</li>
<li>✅ Extract account-favorited notes links</li>
<li>✅ Extract account-liked notes links</li>
<li>✅ Extract account-board notes links</li>
<li>✅ Extract search result notes links</li>
<li>✅ Extract search result user links</li>
</ul>
</details>
@@ -65,17 +65,17 @@
<img src="static/screenshot/程序运行截图EN3.png" alt="">
<h1>🔗 Supported Links</h1>
<ul>
<li><code>https://www.xiaohongshu.com/explore/WorksID?xsec_token=XXX</code></li>
<li><code>https://www.xiaohongshu.com/discovery/item/WorksID?xsec_token=XXX</code></li>
<li><code>https://www.xiaohongshu.com/user/profile/AuthorID/WorksID?xsec_token=XXX</code></li>
<li><code>https://www.xiaohongshu.com/explore/NoteID?xsec_token=XXX</code></li>
<li><code>https://www.xiaohongshu.com/discovery/item/NoteID?xsec_token=XXX</code></li>
<li><code>https://www.xiaohongshu.com/user/profile/AuthorID/NoteID?xsec_token=XXX</code></li>
<li><code>https://xhslink.com/ShareCode</code></li>
<br/>
<p><b>Supports entering multiple works links at once, separated by spaces; the program will automatically extract valid links without additional processing!</b></p>
<p><b>Supports entering multiple notes links at once, separated by spaces; the program will automatically extract valid links without additional processing!</b></p>
</ul>
<h1>🪟 About the Terminal</h1>
<p>⭐ It is recommended to use the <a href="https://learn.microsoft.com/en-us/windows/terminal/install">Windows Terminal</a> (default terminal for Windows 11) to run the program for the best display effect!</p>
<h1>🥣 Usage</h1>
<p>If you only need to download watermark-free works files, it is recommended to choose <b>Program Run</b>; if you have other needs, it is recommended to choose <b>Source Code Run</b>!</p>
<p>If you only need to download watermark-free notes files, it is recommended to choose <b>Program Run</b>; if you have other needs, it is recommended to choose <b>Source Code Run</b>!</p>
<p>Starting from version <code>2.2</code>, if there are no abnormalities in project functionality, there is no need to handle cookies separately!</p>
<h2>🖱 Program Run</h2>
<p>⭐ Mac OS, Windows 10 and above users can go to <a href="https://github.com/JoeanAmier/XHS-Downloader/releases/latest">Releases</a> or <a href="https://github.com/JoeanAmier/XHS-Downloader/actions">Actions</a> to download the program package, unzip it, open the program folder, and double-click to run <code>main</code> to use.</p>
@@ -124,10 +124,10 @@
</ul>
</li>
</ol>
<p>When running the project via Docker, the <b>command line call mode</b> is not supported. The <b>clipboard reading</b> and <b>clipboard monitoring</b> functions are unavailable, but pasting content works fine. Please provide feedback if other features are not functioning properly!</p>
<p>When running the project via Docker, the <b>command line call mode</b> is not supported. The <b>clipboard reading</b> and <b>clipboard monitoring</b> functions are unavailable, but pasting content notes fine. Please provide feedback if other features are not functioning properly!</p>
<h1>🛠 Command Line Mode</h1>
<p>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!</p>
<p><strong>Note:</strong> When the <code>--index</code> 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 <code>--index</code> parameter is set, multiple works links are not supported. Even if multiple links are passed in, the program will only process the first link!</p>
<p>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!</p>
<p><strong>Note:</strong> When the <code>--index</code> 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 <code>--index</code> parameter is set, multiple notes links are not supported. Even if multiple links are passed in, the program will only process the first link!</p>
<p>The <code>bool</code> type parameters support setting with <code>true</code>, <code>false</code>, <code>1</code>, <code>0</code>, <code>yes</code>, <code>no</code>, <code>on</code> or <code>off</code> (case insensitive).</p>
<h2>Read Browser Cookies</h2>
<p>This feature is no longer available. Please refer to the <a href="#cookie">Obtain Cookie</a> tutorial!</p>
@@ -164,19 +164,19 @@
<tr>
<td align="center">url</td>
<td align="center">str</td>
<td align="center">RedNote works link, auto-extraction, does not support multiple links; Required parameter</td>
<td align="center">RedNote notes link, auto-extraction, does not support multiple links; Required parameter</td>
<td align="center">None</td>
</tr>
<tr>
<td align="center">download</td>
<td align="center">bool</td>
<td align="center">Whether to download the works file; set to <code>true</code> will take more time; Optional parameter</td>
<td align="center">Whether to download the notes file; set to <code>true</code> will take more time; Optional parameter</td>
<td align="center">false</td>
</tr>
<tr>
<td align="center">index</td>
<td align="center">list[int]</td>
<td align="center">Download specific image files by index, only effective for text and image works; not effective when the <code>download</code> parameter is set to <code>false</code>; Optional parameter</td>
<td align="center">Download specific image files by index, only effective for text and image notes; not effective when the <code>download</code> parameter is set to <code>false</code>; Optional parameter</td>
<td align="center">null</td>
</tr>
<tr>
@@ -194,7 +194,7 @@
<tr>
<td align="center">skip</td>
<td align="center">bool</td>
<td align="center">Whether to skip works with download records; set to <code>true</code> will not return works data with download records; Optional parameter</td>
<td align="center">Whether to skip notes with download records; set to <code>true</code> will not return notes data with download records; Optional parameter</td>
<td align="center">false</td>
</tr>
</tbody>
@@ -229,10 +229,10 @@ async def example_api():
<h3>MCP Invocation Example</h3>
<details>
<summary>MCP Function and Call Example (Click to Expand)</summary>
<h4><strong>Retrieve RedNote Works Information</strong></h4>
<h4><strong>Retrieve RedNote Notes Information</strong></h4>
<img src="static/screenshot/MCP获取数据.png" alt="MCP Data Retrieval">
<hr>
<h4><strong>Download RedNote Works Files</strong></h4>
<h4><strong>Download RedNote Notes Files</strong></h4>
<p>When downloading images, you can specify the sequence numbers of the images to download. By default, post information is not returned. If you need the post information, please explicitly state so during the conversation.</p>
<img src="static/screenshot/MCP下载文件1.png" alt="MCP File Download">
<hr>
@@ -240,9 +240,9 @@ async def example_api():
</details>
<h1>📜 Others</h1>
<ul>
<li>Due to the date information carried in the links of RedNote works, using links obtained from previous dates may be subject to risk control. It is recommended to use the latest RedNote works links when downloading RedNote work files</li>
<li>Due to the date information carried in the links of RedNote notes, using links obtained from previous dates may be subject to risk control. It is recommended to use the latest RedNote notes links when downloading RedNote work files</li>
<li>Windows system requires running programs as an administrator to read Chromium, Chrome, Edge browser cookies</li>
<li>If the function to save works data to a file is enabled, the works data will be stored by default in the <code>./Volume/Download/ExploreData.db</code> file</li>
<li>If the function to save notes data to a file is enabled, the notes data will be stored by default in the <code>./Volume/Download/ExploreData.db</code> file</li>
<li>The program's download records will be stored in the <code>./Volume/ExploreID.db</code> file</li>
<li>To prevent high-frequency requests from impacting the platform's servers, this project includes a built-in request delay mechanism</li>
</ul>
@@ -261,7 +261,7 @@ async def example_api():
<hr>
<img src="static/screenshot/用户脚本截图4.png" alt="">
</details>
<p>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!</p>
<p>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!</p>
<p><b>Modify user script language</b></p>
<img src="static/screenshot/脚本切换语言.png" alt="切换语言">
<h2>🌐 Connect to Server</h2>
@@ -274,12 +274,12 @@ async def example_api():
</ul>
<h2>📜 Script Instructions</h2>
<ul>
<li>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.</li>
<li>When extracting links for posts, collects, likes, and board from an account, the script can automatically scroll the page until all works are loaded.</li>
<li>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.</li>
<li>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.</li>
<li>When extracting links for posts, collects, likes, and board from an account, the script can automatically scroll the page until all notes are loaded.</li>
<li>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.</li>
<li>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.</li>
<li>If the automatic page scroll feature is not enabled, users need to manually scroll the page to load more content before performing other actions.</li>
<li>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</li>
<li>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</li>
<li>When pushing download tasks to the server, the file format, name rules, etc. settings will be based on the server configuration file settings</li>
<li>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.</li>
<li>XHS-Downloader userscript only implements the data collection functionality for visible content and does not include any paid or cracked features.</li>
@@ -380,19 +380,19 @@ async def example():
<tr>
<td align="center">work_path</td>
<td align="center">str</td>
<td align="center">Root path for saving works data/files</td>
<td align="center">Root path for saving notes data/files</td>
<td align="center">Project root path/Volume</td>
</tr>
<tr>
<td align="center">folder_name</td>
<td align="center">str</td>
<td align="center">Name of the folder for storing works files</td>
<td align="center">Name of the folder for storing notes files</td>
<td align="center">Download</td>
</tr>
<tr>
<td align="center">name_format</td>
<td align="center">str</td>
<td align="center"><sup><a href="#fields">#</a></sup>Format of works file name, separated by spaces between fields, supports fields: <code>收藏数量</code><code>评论数量</code><code>分享数量</code><code>点赞数量</code><code>作品标签</code><code>作品ID</code><code>作品标题</code><code>作品描述</code><code>作品类型</code><code>发布时间</code><code>最后更新时间</code><code>作者昵称</code><code>作者ID</code></td>
<td align="center"><sup><a href="#fields">#</a></sup>Format of notes file name, separated by spaces between fields, supports fields: <code>收藏数量</code><code>评论数量</code><code>分享数量</code><code>点赞数量</code><code>作品标签</code><code>作品ID</code><code>作品标题</code><code>作品描述</code><code>作品类型</code><code>发布时间</code><code>最后更新时间</code><code>作者昵称</code><code>作者ID</code></td>
<td align="center"><code>发布时间 作者昵称 作品标题</code></td>
</tr>
<tr>
@@ -434,25 +434,25 @@ async def example():
<tr>
<td align="center">record_data</td>
<td align="center">bool</td>
<td align="center">Whether to save works data to a file, saved in <code>SQLite</code> format</td>
<td align="center">Whether to save notes data to a file, saved in <code>SQLite</code> format</td>
<td align="center">false</td>
</tr>
<tr>
<td align="center">image_format</td>
<td align="center">str</td>
<td align="center">Download format for image works files, supported: <code>AUTO</code><code>PNG</code><code>WEBP</code><code>JPEG</code><code>HEIC</code><br><strong>Some works do not have files in HEIC format, and the downloaded files may be in WEBP format</strong><br><strong>When set to<code>AUTO</code>, it represents dynamic format, and the actual format depends on the server's response data</strong></td>
<td align="center">Download format for image notes files, supported: <code>AUTO</code><code>PNG</code><code>WEBP</code><code>JPEG</code><code>HEIC</code><br><strong>Some notes do not have files in HEIC format, and the downloaded files may be in WEBP format</strong><br><strong>When set to<code>AUTO</code>, it represents dynamic format, and the actual format depends on the server's response data</strong></td>
<td align="center">JPEG</td>
</tr>
<tr>
<td align="center">image_download</td>
<td align="center">bool</td>
<td align="center">Switch for downloading image and atlas works files</td>
<td align="center">Switch for downloading image and atlas notes files</td>
<td align="center">true</td>
</tr>
<tr>
<td align="center">video_download</td>
<td align="center">bool</td>
<td align="center">Switch for downloading video works files</td>
<td align="center">Switch for downloading video notes files</td>
<td align="center">true</td>
</tr>
<tr>
@@ -462,27 +462,33 @@ async def example():
<td align="center">false</td>
</tr>
<tr>
<td align="center">video_preference</td>
<td align="center">str</td>
<td align="center">Video notes file download preference; Meaning: <code>resolution</code>: resolution priority; <code>bitrate</code>: bitrate priority; <code>size</code>: file size priority</td>
<td align="center">resolution</td>
</tr>
<tr>
<td align="center">folder_mode</td>
<td align="center">bool</td>
<td align="center">Whether to store each works files in a separate folder; the folder name matches the file name</td>
<td align="center">Whether to store each notes files in a separate folder; the folder name matches the file name</td>
<td align="center">false</td>
</tr>
<tr>
<td align="center">download_record</td>
<td align="center">bool</td>
<td align="center">Do record the ID of successfully downloaded works? If enabled, the program will automatically skip downloading works with records</td>
<td align="center">Do record the ID of successfully downloaded notes? If enabled, the program will automatically skip downloading notes with records</td>
<td align="center">true</td>
</tr>
<tr>
<td align="center">author_archive</td>
<td align="center">bool</td>
<td align="center"><sup><a href="#author_archive">#</a></sup>Whether to save each author's works into a separate folder; The folder name is <code>authorID_nickname</code></td>
<td align="center"><sup><a href="#author_archive">#</a></sup>Whether to save each author's notes into a separate folder; The folder name is <code>authorID_nickname</code></td>
<td align="center">false</td>
</tr>
<tr>
<td align="center">write_mtime</td>
<td align="center">bool</td>
<td align="center">Whether to modify the <code>modified time</code> attribute of the works file to the publication time of the works.</td>
<td align="center">Whether to modify the <code>modified time</code> attribute of the notes file to the publication time of the notes.</td>
<td align="center">false</td>
</tr>
<tr>
@@ -507,11 +513,11 @@ async def example():
<li><code>评论数量</code>: Number of Comments</li>
<li><code>分享数量</code>: Number of Shares</li>
<li><code>点赞数量</code>: Number of Likes</li>
<li><code>作品标签</code>: Works Tags</li>
<li><code>作品ID</code>: Works ID</li>
<li><code>作品标题</code>: Works Title</li>
<li><code>作品描述</code>: Works Description</li>
<li><code>作品类型</code>: Works Type</li>
<li><code>作品标签</code>: Notes Tags</li>
<li><code>作品ID</code>: Notes ID</li>
<li><code>作品标题</code>: Notes Title</li>
<li><code>作品描述</code>: Notes Description</li>
<li><code>作品类型</code>: Notes Type</li>
<li><code>发布时间</code>: Publish Time</li>
<li><code>最后更新时间</code>: Last Updated Time</li>
<li><code>作者昵称</code>: Author Nickname</li>
@@ -520,7 +526,7 @@ async def example():
</div>
<hr>
<div id="author_archive">
<p>When <code>author_archive</code> is set to <code>true</code>, 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!</p>
<p>When <code>author_archive</code> is set to <code>true</code>, 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!</p>
<p>Additionally, you can configure author aliases through the <code>mapping_data</code> parameter. When an alias is set, the program will use your custom alias instead of the original nickname in filenames!</p>
</div>
<hr>
@@ -536,14 +542,14 @@ async def example():
<li>Check <code>Preserve log</code></li>
<li>In the <code>Filter</code> input box, enter <code>cookie-name:web_session</code></li>
<li>Select the <code>Fetch/XHR</code> filter</li>
<li>Click on any piece of works on the RedNote page</li>
<li>Click on any piece of notes on the RedNote page</li>
<li>In the <code>Network</code> tab, select any data packet (if no packets appear, repeat step 7)</li>
<li>Copy and paste the entire Cookie into the program or configuration file</li>
</ol>
<br>
<img src="static/screenshot/获取Cookie示意图.png" alt="">
<h1>🗳 Download Records</h1>
<p>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!</p>
<p>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!</p>
<p>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!</p>
<h2>Build of Executable File Guide</h2>
<details>
@@ -710,7 +716,7 @@ repository to execute the build process
<li>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.</li>
<li>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.</li>
<li>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.</li>
<li>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.</li>
<li>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.</li>
<li>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.</li>
</ol>
<b>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.</b>

View File

@@ -289,6 +289,11 @@ class CLI:
"-ld",
type=bool,
)
@option(
"--video_preference",
"-vp",
type=Choice(["resolution", "bitrate", "size"]),
)
@option(
"--download_record",
"-dr",

View File

@@ -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,
}
)

View File

@@ -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,

View File

@@ -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]

View File

@@ -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,

View File

@@ -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, # 是否按作者归档

4
uv.lock generated
View File

@@ -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" },