From 7059603d46c945de6c19b6f004472849a06004a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=A8?= Date: Tue, 18 Feb 2025 19:55:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(image):=20=E5=A2=9E=E5=8A=A0=E5=AF=B9=20JP?= =?UTF-8?q?EG=20=E5=92=8C=20HEIC=20=E5=9B=BE=E7=89=87=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在图片下载功能中添加了对 JPEG 和 HEIC 格式的支持 - 更新了相关模块和文档以支持新功能 Closes #229 --- README.md | 5 +++-- README_EN.md | 7 ++++--- example.py | 16 +++++++++++++--- source/TUI/setting.py | 2 +- source/application/app.py | 7 ++++--- source/application/image.py | 14 +++++++------- source/module/__init__.py | 1 + source/module/manager.py | 4 ++-- source/module/static.py | 4 ++-- static/Release_Notes.md | 3 ++- 10 files changed, 39 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index be87b4a..6e32748 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@

🖥 服务器模式

启动:运行命令:python .\main.py server

关闭:按下 Ctrl + C 关闭服务器

+

访问 http://127.0.0.1:8000/docs;你会看到自动生成的交互式 API 文档!

请求接口:/xhs/

请求方法:POST

请求格式:JSON

@@ -224,7 +225,7 @@ async def example(): chunk = 1024 * 1024 * 10 # 下载文件时,每次从服务器获取的数据块大小,单位:字节 max_retry = 2 # 请求数据失败时,重试的最大次数,单位:秒,默认值:5 record_data = False # 是否保存作品数据至文件 - image_format = "WEBP" # 图文作品文件下载格式,支持:PNG、WEBP + image_format = "WEBP" # 图文作品文件下载格式,支持:AUTO、PNG、WEBP、JPEG、HEIC folder_mode = False # 是否将每个作品的文件储存至单独的文件夹 image_download = True # 图文作品文件下载开关 video_download = True # 视频作品文件下载开关 @@ -341,7 +342,7 @@ async def example(): image_format str -图文作品文件下载格式,支持:PNGWEBP
该参数影响下载图片时所用的接口,并非固定图片格式! +图文作品文件下载格式,支持:AUTOPNGWEBPJPEGHEIC
部分作品没有 HEIC 格式的文件,此时下载的文件可能为 WEBP 格式!
设置为 AUTO 时表示动态格式,实际格式取决于服务器响应数据! PNG diff --git a/README_EN.md b/README_EN.md index 1c3c968..8420fd8 100644 --- a/README_EN.md +++ b/README_EN.md @@ -117,6 +117,7 @@

🖥 Server Mode

Start: Run the command: python .\main.py server

Stop: Press Ctrl + C to stop the server

+

Open http://127.0.0.1:8000/docs; you will see automatically generated interactive API documentation!

Request endpoint: /xhs/

Request method: @@ -228,7 +229,7 @@ async def example(): chunk = 1024 * 1024 * 10 # 下载文件时,每次从服务器获取的数据块大小,单位:字节 max_retry = 2 # 请求数据失败时,重试的最大次数,单位:秒,默认值:5 record_data = False # 是否保存作品数据至文件 - image_format = "WEBP" # 图文作品文件下载格式,支持:PNG、WEBP + image_format = "WEBP" # 图文作品文件下载格式,支持:AUTO、PNG、WEBP、JPEG、HEIC folder_mode = False # 是否将每个作品的文件储存至单独的文件夹 image_download = True # 图文作品文件下载开关 video_download = True # 视频作品文件下载开关 @@ -345,13 +346,13 @@ async def example(): image_format str -Download format for text and image works files, supported formats: PNG, WEBP
This parameter affects the API used when downloading images, not the fixed image format! +Download format for image works files, supported: AUTOPNGWEBPJPEGHEIC
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 PNG image_download bool -Switch for downloading text and image works files +Switch for downloading image works files true diff --git a/example.py b/example.py index 212980d..5a700af 100644 --- a/example.py +++ b/example.py @@ -1,5 +1,7 @@ from asyncio import run +from rich import print + from source import XHS @@ -19,7 +21,7 @@ async def example(): chunk = 1024 * 1024 * 10 # 下载文件时,每次从服务器获取的数据块大小,单位:字节 max_retry = 2 # 请求数据失败时,重试的最大次数,单位:秒,默认值:5 record_data = False # 是否保存作品数据至文件 - image_format = "WEBP" # 图文作品文件下载格式,支持:PNG、WEBP + image_format = "WEBP" # 图文作品文件下载格式,支持:AUTO、PNG、WEBP、JPEG、HEIC folder_mode = False # 是否将每个作品的文件储存至单独的文件夹 image_download = True # 图文作品文件下载开关 video_download = True # 视频作品文件下载开关 @@ -59,11 +61,19 @@ async def example(): async def test(): url = "" - async with XHS() as xhs: + async with XHS( + 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( url, - download=True, + # download=True, ) ) diff --git a/source/TUI/setting.py b/source/TUI/setting.py index 6822b03..827630d 100644 --- a/source/TUI/setting.py +++ b/source/TUI/setting.py @@ -173,7 +173,7 @@ class Setting(Screen): Label(), Container( Select.from_values( - ("PNG", "WEBP"), + ("AUTO", "PNG", "WEBP", "JPEG", "HEIC"), value=self.data["image_format"].upper(), allow_blank=False, id="image_format", diff --git a/source/application/app.py b/source/application/app.py index 9f26de5..1be8c10 100644 --- a/source/application/app.py +++ b/source/application/app.py @@ -34,6 +34,7 @@ from source.module import ( VERSION_MAJOR, VERSION_MINOR, VERSION_BETA, + __VERSION__ ) from source.module import logging from source.module import sleep_time @@ -47,7 +48,7 @@ from .video import Video __all__ = ["XHS"] -def _data_cache(function): +def data_cache(function): async def inner( self, data: dict, @@ -179,7 +180,7 @@ class XHS: logging(log, _("提取作品文件下载地址失败"), ERROR) await self.save_data(container) - @_data_cache + @data_cache async def save_data( self, data: dict, @@ -480,7 +481,7 @@ class XHS: self.server = FastAPI( debug=self.VERSION_BETA, title="XHS-Downloader", - version=f"{self.VERSION_MAJOR}.{self.VERSION_MINOR}", + version=__VERSION__, ) self.setup_routes() config = Config( diff --git a/source/application/image.py b/source/application/image.py index 2455f65..1d62f9f 100644 --- a/source/application/image.py +++ b/source/application/image.py @@ -14,24 +14,24 @@ class Image: for i in images ] match format_: - case "png": + case "png" | "webp" | "jpeg" | "heic" | "avif": return [ - Html.format_url(cls.__generate_png_link(i)) for i in token_list + Html.format_url(cls.__generate_fixed_link(i, format_, )) for i in token_list ], live_link - case "webp": + case "auto": return [ - Html.format_url(cls.__generate_webp_link(i)) for i in token_list + Html.format_url(cls.__generate_auto_link(i)) for i in token_list ], live_link case _: raise ValueError @staticmethod - def __generate_webp_link(token: str) -> str: + def __generate_auto_link(token: str) -> str: return f"https://sns-img-bd.xhscdn.com/{token}" @staticmethod - def __generate_png_link(token: str) -> str: - return f"https://ci.xiaohongshu.com/{token}?imageView2/format/png" + def __generate_fixed_link(token: str, format_: str, ) -> str: + return f"https://ci.xiaohongshu.com/{token}?imageView2/format/{format_}" @staticmethod def __extract_image_token(url: str) -> str: diff --git a/source/module/__init__.py b/source/module/__init__.py index abf2ba0..7bbd59f 100644 --- a/source/module/__init__.py +++ b/source/module/__init__.py @@ -29,6 +29,7 @@ from .static import ( FILE_SIGNATURES, FILE_SIGNATURES_LENGTH, MAX_WORKERS, + __VERSION__, ) from .tools import ( retry, diff --git a/source/module/manager.py b/source/module/manager.py index cdd1541..b619b63 100644 --- a/source/module/manager.py +++ b/source/module/manager.py @@ -138,8 +138,8 @@ class Manager: @staticmethod def __check_image_format(image_format) -> str: - if image_format in {"png", "PNG", "webp", "WEBP"}: - return image_format.lower() + if (i := image_format.lower()) in {"auto", "png", "webp", "jpeg", "heic", "avif", }: + return i return "png" @staticmethod diff --git a/source/module/static.py b/source/module/static.py index 64b34c2..51bd92d 100644 --- a/source/module/static.py +++ b/source/module/static.py @@ -3,7 +3,7 @@ from pathlib import Path VERSION_MAJOR = 2 VERSION_MINOR = 5 VERSION_BETA = True -__version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{'beta' if VERSION_BETA else 'stable'}" +__VERSION__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{'beta' if VERSION_BETA else 'stable'}" ROOT = Path(__file__).resolve().parent.parent.parent PROJECT = f"XHS-Downloader V{VERSION_MAJOR}.{VERSION_MINOR} { 'Beta' if VERSION_BETA else 'Stable' @@ -68,4 +68,4 @@ FILE_SIGNATURES_LENGTH = max( MAX_WORKERS: int = 4 if __name__ == "__main__": - print(__version__) + print(__VERSION__) diff --git a/static/Release_Notes.md b/static/Release_Notes.md index aad9b81..d93a92a 100644 --- a/static/Release_Notes.md +++ b/static/Release_Notes.md @@ -1,6 +1,7 @@ **项目更新内容:** -1. 支持 SOCKS 代理 +1. 增加对 `JPEG` 和 `HEIC` 图片格式的支持 +2. 支持 `SOCKS` 代理 *****