From c2fa98bb51de00e88d3c6587d80cd08825428c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=A8?= Date: Wed, 12 Mar 2025 22:01:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=8C=89=E4=BD=9C?= =?UTF-8?q?=E8=80=85=E5=BD=92=E6=A1=A3=E4=BF=9D=E5=AD=98=E4=BD=9C=E5=93=81?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: 新增配置文件参数:account_archive Closes #226 Closes #229 --- README.md | 11 +++++++ README_EN.md | 11 +++++++ example.py | 52 ++++++++++++++++++---------------- source/TUI/setting.py | 12 ++++++-- source/application/app.py | 3 ++ source/application/download.py | 19 +++++++++---- source/module/manager.py | 2 ++ source/module/settings.py | 1 + static/Release_Notes.md | 9 ++++-- 9 files changed, 84 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 24e59b7..f632935 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,7 @@ async def example(): """通过代码设置参数,适合二次开发""" # 示例链接 demo_link = "https://www.xiaohongshu.com/explore/XXX?xsec_token=XXX" + # 实例对象 work_path = "D:\\" # 作品数据/文件保存根路径,默认值:项目根路径 folder_name = "Download" # 作品文件储存文件夹名称(自动创建),默认值:Download @@ -232,9 +233,12 @@ async def example(): live_download = False # 图文动图文件下载开关 download_record = True # 是否记录下载成功的作品 ID language = "zh_CN" # 设置程序提示语言 + account_archive = True # 是否将每个作者的作品存至单独的文件夹 read_cookie = None # 读取浏览器 Cookie,支持设置浏览器名称(字符串)或者浏览器序号(整数),设置为 None 代表不读取 + # async with XHS() as xhs: # pass # 使用默认参数 + async with XHS( work_path=work_path, folder_name=folder_name, @@ -254,6 +258,7 @@ async def example(): download_record=download_record, language=language, read_cookie=read_cookie, + account_archive=account_archive, ) as xhs: # 使用自定义参数 download = True # 是否下载作品文件,默认值:False # 返回作品详细信息,包括下载地址 @@ -376,6 +381,12 @@ async def example(): true +account_archive +bool +是否将每个作者的作品储存至单独的文件夹;文件夹名称为作者昵称或者作者 ID +false + + language str 设置程序语言,目前支持:zh_CNen_US diff --git a/README_EN.md b/README_EN.md index c411d17..4241c32 100644 --- a/README_EN.md +++ b/README_EN.md @@ -218,6 +218,7 @@ async def example(): """通过代码设置参数,适合二次开发""" # 示例链接 demo_link = "https://www.xiaohongshu.com/explore/XXX?xsec_token=XXX" + # 实例对象 work_path = "D:\\" # 作品数据/文件保存根路径,默认值:项目根路径 folder_name = "Download" # 作品文件储存文件夹名称(自动创建),默认值:Download @@ -236,9 +237,12 @@ async def example(): live_download = False # 图文动图文件下载开关 download_record = True # 是否记录下载成功的作品 ID language = "zh_CN" # 设置程序提示语言 + account_archive = True # 是否将每个作者的作品存至单独的文件夹 read_cookie = None # 读取浏览器 Cookie,支持设置浏览器名称(字符串)或者浏览器序号(整数),设置为 None 代表不读取 + # async with XHS() as xhs: # pass # 使用默认参数 + async with XHS( work_path=work_path, folder_name=folder_name, @@ -258,6 +262,7 @@ async def example(): download_record=download_record, language=language, read_cookie=read_cookie, + account_archive=account_archive, ) as xhs: # 使用自定义参数 download = True # 是否下载作品文件,默认值:False # 返回作品详细信息,包括下载地址 @@ -380,6 +385,12 @@ async def example(): true +account_archive +bool +Whether to save each author's works into a separate folder; the folder name will be the author's nickname or author ID +false + + language str Set program language. Currently supported: zh_CN, en_US diff --git a/example.py b/example.py index 5a700af..247318f 100644 --- a/example.py +++ b/example.py @@ -28,30 +28,32 @@ async def example(): live_download = False # 图文动图文件下载开关 download_record = True # 是否记录下载成功的作品 ID language = "zh_CN" # 设置程序提示语言 + account_archive = True # 是否将每个作者的作品存至单独的文件夹 read_cookie = None # 读取浏览器 Cookie,支持设置浏览器名称(字符串)或者浏览器序号(整数),设置为 None 代表不读取 # async with XHS() as xhs: # pass # 使用默认参数 async with XHS( - work_path=work_path, - folder_name=folder_name, - name_format=name_format, - user_agent=user_agent, - cookie=cookie, - proxy=proxy, - timeout=timeout, - chunk=chunk, - max_retry=max_retry, - record_data=record_data, - image_format=image_format, - folder_mode=folder_mode, - image_download=image_download, - video_download=video_download, - live_download=live_download, - download_record=download_record, - language=language, - read_cookie=read_cookie, + work_path=work_path, + folder_name=folder_name, + name_format=name_format, + user_agent=user_agent, + cookie=cookie, + proxy=proxy, + timeout=timeout, + chunk=chunk, + max_retry=max_retry, + record_data=record_data, + image_format=image_format, + folder_mode=folder_mode, + image_download=image_download, + video_download=video_download, + live_download=live_download, + download_record=download_record, + language=language, + read_cookie=read_cookie, + account_archive=account_archive, ) as xhs: # 使用自定义参数 download = True # 是否下载作品文件,默认值:False # 返回作品详细信息,包括下载地址 @@ -62,13 +64,13 @@ async def example(): async def test(): url = "" async with XHS( - download_record=False, - # image_format="PNG", - # image_format="WEBP", - # image_format="JPEG", - # image_format="HEIC", - # image_format="AVIF", - # image_format="AUTO", + download_record=False, + # image_format="PNG", + # image_format="WEBP", + # image_format="JPEG", + # image_format="HEIC", + # image_format="AVIF", + # image_format="AUTO", ) as xhs: print( await xhs.extract( diff --git a/source/TUI/setting.py b/source/TUI/setting.py index 827630d..976b344 100644 --- a/source/TUI/setting.py +++ b/source/TUI/setting.py @@ -24,8 +24,8 @@ class Setting(Screen): ] def __init__( - self, - data: dict, + self, + data: dict, ): super().__init__() self.data = data @@ -129,7 +129,7 @@ class Setting(Screen): value=self.data["record_data"], ), Checkbox( - _("作品文件夹归档模式"), + _("作品归档保存模式"), id="folder_mode", value=self.data["folder_mode"], ), @@ -157,6 +157,11 @@ class Setting(Screen): id="download_record", value=self.data["download_record"], ), + Checkbox( + _("作者归档保存模式"), + id="account_archive", + value=self.data["account_archive"], + ), classes="horizontal-layout", ), Container( @@ -229,6 +234,7 @@ class Setting(Screen): "video_download": self.query_one("#video_download").value, "live_download": self.query_one("#live_download").value, "download_record": self.query_one("#download_record").value, + "account_archive": self.query_one("#account_archive").value, } ) diff --git a/source/application/app.py b/source/application/app.py index 6fccf17..3dc3326 100644 --- a/source/application/app.py +++ b/source/application/app.py @@ -100,6 +100,7 @@ class XHS: live_download=False, folder_mode=False, download_record=True, + account_archive=False, language="zh_CN", read_cookie: int | str = None, _print: bool = True, @@ -125,6 +126,7 @@ class XHS: live_download, download_record, folder_mode, + account_archive, _print, ) self.html = Html(self.manager) @@ -170,6 +172,7 @@ class XHS: u, container["动图地址"], index, + self.CLEANER.filter_name(container["作者昵称"]) or container["作者ID"], name, container["作品类型"], log, diff --git a/source/application/download.py b/source/application/download.py index 0806d9a..40a2365 100644 --- a/source/application/download.py +++ b/source/application/download.py @@ -63,23 +63,25 @@ class Download: self.image_download = manager.image_download self.video_download = manager.video_download self.live_download = manager.live_download + self.account_archive = manager.account_archive async def run( self, urls: list, lives: list, index: list | tuple | None, - name: str, + nickname: str, + filename: str, type_: str, log, bar, ) -> tuple[Path, list[Any]]: - path = self.__generate_path(name) + path = self.__generate_path(nickname, filename) if type_ == _("视频"): tasks = self.__ready_download_video( urls, path, - name, + filename, log, ) elif type_ == _("图文"): @@ -88,7 +90,7 @@ class Download: lives, index, path, - name, + filename, log, ) else: @@ -107,8 +109,13 @@ class Download: tasks = await gather(*tasks) return path, tasks - def __generate_path(self, name: str): - path = self.manager.archive(self.folder, name, self.folder_mode) + def __generate_path(self, nickname:str, filename: str): + if self.account_archive: + folder = self.folder.joinpath(nickname) + folder.mkdir(exist_ok=True) + else: + folder = self.folder + path = self.manager.archive(folder, filename, self.folder_mode) path.mkdir(exist_ok=True) return path diff --git a/source/module/manager.py b/source/module/manager.py index f9644c1..a9ffa32 100644 --- a/source/module/manager.py +++ b/source/module/manager.py @@ -65,6 +65,7 @@ class Manager: live_download: bool, download_record: bool, folder_mode: bool, + account_archive:bool, _print: bool, ): self.root = root @@ -115,6 +116,7 @@ class Manager: self.image_download = self.check_bool(image_download, True) self.video_download = self.check_bool(video_download, True) self.live_download = self.check_bool(live_download, True) + self.account_archive = self.check_bool(account_archive, False) def __check_path(self, path: str) -> Path: if not path: diff --git a/source/module/settings.py b/source/module/settings.py index f6e2e5e..b4a9704 100644 --- a/source/module/settings.py +++ b/source/module/settings.py @@ -27,6 +27,7 @@ class Settings: "live_download": False, "folder_mode": False, "download_record": True, + "account_archive": False, "language": "zh_CN", } encode = "UTF-8-SIG" if system() == "Windows" else "UTF-8" diff --git a/static/Release_Notes.md b/static/Release_Notes.md index 8a25078..e9a1c06 100644 --- a/static/Release_Notes.md +++ b/static/Release_Notes.md @@ -1,8 +1,13 @@ **项目更新内容:** 1. 增加对 `JPEG` 和 `HEIC` 图片格式的支持 -2. 优化 `headers` 处理逻辑 -3. 支持 `SOCKS` 代理 +2. 支持按作者归档保存作品文件 +3. 优化 `headers` 处理逻辑 +4. 支持 `SOCKS` 代理 + +**注意:** + +

配置文件新增参数 account_archive,旧版本更新需要手动添加配置内容:"account_archive": false;或者直接删除旧版配置文件后再运行程序!

*****