优化项目代码

This commit is contained in:
JoeamAmier 2024-01-07 21:31:59 +08:00
parent 952cf3496a
commit d364e32473
9 changed files with 89 additions and 54 deletions

View File

@ -57,6 +57,19 @@
<li>下载本项目最新的源码或 <a href="https://github.com/JoeanAmier/XHS-Downloader/releases/latest">Releases</a> 发布的源码至本地</li>
<li>运行 <code>main.py</code> 即可使用</li>
</ol>
<h1>🕹 用户脚本</h1>
<p>如果您的浏览器安装了 <a href="https://www.tampermonkey.net/">Tampermonkey</a> 浏览器扩展程序,可以添加 <a href="https://raw.githubusercontent.com/JoeanAmier/XHS-Downloader/master/static/XHS-Downloader.js">用户脚本</a>,无需下载即可体验!</p>
<p>使用 XHS-Downloader 用户脚本批量获取作品链接,搭配 XHS-Downloader 程序可以实现批量下载无水印作品文件!</p>
<h2>脚本功能</h2>
<ul>
<li>下载无水印作品文件</li>
<li>提取发现页面作品链接</li>
<li>提取账号发布作品链接</li>
<li>提取账号收藏作品链接</li>
<li>提取账号点赞作品链接</li>
</ul>
<h2>脚本截图</h2>
<img src="static/用户脚本截图.png" alt="">
<h1>💻 二次开发</h1>
<p>如果有其他需求,可以根据 <code>main.py</code> 的注释提示进行代码调用或修改!</p>
<pre>
@ -193,9 +206,6 @@ async with XHS(work_path=work_path,
</ol>
<br>
<img src="static/获取Cookie示意图.png" alt="">
<h1>🕹 用户脚本</h1>
<p>如果您的浏览器安装了 Tampermonkey 浏览器扩展程序,可以 <a href="https://raw.githubusercontent.com/JoeanAmier/XHS-Downloader/master/static/XHS-Downloader.js">点击获取</a> 用户脚本,无需下载即可体验!</p>
<p>可以使用 XHS-Downloader 用户脚本批量获取账号作品链接,搭配 XHS-Downloader 程序实现批量下载账号作品文件!</p>
<h1>♥️ 支持项目</h1>
<p>如果 <b>XHS-Downloader</b> 对您有帮助,请考虑为它点个 <b>Star</b> ⭐,感谢您的支持!</p>
<table>

View File

@ -1,3 +1,3 @@
from .index import XHSDownloader
from .app import XHSDownloader
__all__ = ['XHSDownloader']

37
source/TUI/app.py Normal file
View File

@ -0,0 +1,37 @@
from textual.app import App
from source.application import XHS
from source.module import (
ROOT,
)
from source.module import Settings
from source.translator import Chinese
from source.translator import LANGUAGE
from .index import Index
from .setting import Setting
__all__ = ["XHSDownloader"]
class XHSDownloader(App):
def __init__(self):
super().__init__()
self.settings = Settings(ROOT)
self.parameter = self.settings.run()
self.prompt = LANGUAGE.get(self.parameter["language"], Chinese)
self.APP = XHS(**self.parameter, language_object=self.prompt)
async def __aenter__(self):
await self.APP.__aenter__()
return self
async def __aexit__(self, exc_type, exc_value, traceback):
await self.APP.__aexit__(exc_type, exc_value, traceback)
async def on_mount(self) -> None:
self.install_screen(Setting(), name="setting")
self.install_screen(Index(self.APP, self.prompt), name="index")
await self.push_screen("index")
async def action_settings(self):
await self.push_screen("setting")

View File

@ -1,13 +1,15 @@
from webbrowser import open
# from asyncio import sleep
from pyperclip import paste
from rich.text import Text
from textual.app import App
from textual import on
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Center
from textual.containers import HorizontalScroll
from textual.containers import ScrollableContainer
from textual.screen import Screen
from textual.widgets import Button
from textual.widgets import Footer
from textual.widgets import Header
@ -17,12 +19,11 @@ from textual.widgets import ProgressBar
from textual.widgets import RichLog
from source.application import XHS
from source.module import Settings
from source.module import ROOT
from source.module import (
VERSION_MAJOR,
VERSION_MINOR,
VERSION_BETA,
ROOT,
PROMPT,
MASTER,
ERROR,
@ -34,11 +35,9 @@ from source.module import (
GENERAL,
USERSCRIPT,
)
from source.translator import Chinese
from source.translator import LANGUAGE
from .setting import Setting
from source.translator import (English, Chinese)
__all__ = ["XHSDownloader"]
__all__ = ["Index"]
def show_state(function):
@ -53,7 +52,7 @@ def show_state(function):
return inner
class XHSDownloader(App):
class Index(Screen):
CSS_PATH = ROOT.joinpath(
"static/css/index.tcss")
BINDINGS = [
@ -61,28 +60,18 @@ class XHSDownloader(App):
# ("d", "toggle_dark", "切换主题"),
Binding(key="u", action="check_update", description="检查更新"),
Binding(key="m", action="user_script", description="获取脚本"),
# Binding(key="l", action="choose_language", description="切换语言"),
# Binding(key="s", action="settings", description="程序设置"),
Binding(key="s", action="settings", description="程序设置"),
]
def __init__(self):
def __init__(self, app: XHS, language: Chinese | English):
super().__init__()
settings = Settings(ROOT).run()
self.prompt = LANGUAGE.get(settings["language"], Chinese)
self.APP = XHS(**settings, language_object=self.prompt)
self.app_ = app
self.prompt = language
self.url = None
self.tip = None
self.bar = None
self.setting = None
self.disclaimer = True
async def __aenter__(self):
await self.APP.__aenter__()
return self
async def __aexit__(self, exc_type, exc_value, traceback):
await self.APP.__aexit__(exc_type, exc_value, traceback)
def compose(self) -> ComposeResult:
yield Header()
yield ScrollableContainer(Label(Text(f"{self.prompt.open_source_protocol}{LICENCE}", style=MASTER)),
@ -96,7 +85,6 @@ class XHSDownloader(App):
HorizontalScroll(Button(self.prompt.download_button, id="deal"),
Button(self.prompt.paste_button, id="paste"),
Button(self.prompt.reset_button, id="reset"), ),
id="index",
)
with Center():
yield ProgressBar(total=None, show_percentage=False, show_eta=False)
@ -106,8 +94,6 @@ class XHSDownloader(App):
def on_mount(self) -> None:
self.title = f"XHS-Downloader V{VERSION_MAJOR}.{
VERSION_MINOR}{" Beta" if VERSION_BETA else ""}"
def on_ready(self) -> None:
self.url = self.query_one(Input)
self.tip = self.query_one(RichLog)
self.bar = self.query_one(ProgressBar)
@ -118,20 +104,26 @@ class XHSDownloader(App):
self.tip.clear()
self.disclaimer = False
async def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "deal":
await self.deal()
elif event.button.id == "reset":
self.query_one(Input).value = ""
elif event.button.id == "paste":
self.query_one(Input).value = paste()
@on(Button.Pressed, "#deal")
async def deal_button(self):
await self.deal()
@on(Button.Pressed, "#reset")
def reset_button(self):
self.query_one(Input).value = ""
@on(Button.Pressed, "#paste")
def paste_button(self):
self.query_one(Input).value = paste()
@show_state
async def deal(self):
# TODO: 处理过程中,进度条异常卡顿,待排查!
# await sleep(2)
if not self.url.value:
self.tip.write(Text(self.prompt.invalid_link, style=WARNING))
return
if any(await self.APP.extract(self.url.value, True, log=self.tip)):
if any(await self.app_.extract(self.url.value, True, log=self.tip)):
self.url.value = ""
else:
self.tip.write(Text(self.prompt.download_failure, style=ERROR))
@ -143,7 +135,7 @@ class XHSDownloader(App):
self.prompt.check_update_notification,
style=WARNING))
try:
url = await self.APP.html.request_url(RELEASES, False, self.tip)
url = await self.app_.html.request_url(RELEASES, False, self.tip)
latest_major, latest_minor = map(
int, url.split("/")[-1].split(".", 1))
if latest_major > VERSION_MAJOR or latest_minor > VERSION_MINOR:
@ -176,14 +168,3 @@ class XHSDownloader(App):
@staticmethod
def action_user_script():
open(USERSCRIPT)
def action_choose_language(self):
pass
def action_settings(self):
if self.setting:
self.setting.remove()
self.setting = None
else:
self.setting = Setting()
self.query_one("#index").mount(self.setting)

0
source/TUI/server.py Normal file
View File

View File

@ -1,16 +1,23 @@
from textual.app import ComposeResult
from textual.binding import Binding
from textual.screen import Screen
from textual.widgets import Footer
from textual.widgets import Header
from textual.widgets import Label
from textual.widgets import Static
from source.module import ROOT
__all__ = ["Setting"]
class Setting(Static):
class Setting(Screen):
CSS_PATH = ROOT.joinpath(
"static/css/setting.tcss")
BINDINGS = [
Binding(key="q", action="quit", description="退出程序"),
]
def compose(self) -> ComposeResult:
"""Create child widgets for the app."""
yield Header()
yield Label("我是设置页")
yield Footer()

View File

@ -68,7 +68,7 @@ class Download:
except ClientError as error:
self.manager.delete(temp)
# self.__create_progress(bar, None)
logging(log, error, ERROR)
logging(log, str(error), ERROR)
logging(log, self.prompt.download_error(name), ERROR)
return False

View File

@ -29,7 +29,7 @@ class Html:
) as response:
return await response.text() if content else str(response.url)
except ClientError as error:
logging(log, error, ERROR)
logging(log, str(error), ERROR)
logging(log, self.prompt.request_error(url), ERROR)
return ""

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB