mirror of
https://github.com/JoeanAmier/XHS-Downloader.git
synced 2025-12-26 04:48:05 +08:00
优化项目代码
This commit is contained in:
parent
952cf3496a
commit
d364e32473
16
README.md
16
README.md
@ -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>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
from .index import XHSDownloader
|
||||
from .app import XHSDownloader
|
||||
|
||||
__all__ = ['XHSDownloader']
|
||||
|
||||
37
source/TUI/app.py
Normal file
37
source/TUI/app.py
Normal 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")
|
||||
@ -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
0
source/TUI/server.py
Normal 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()
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 ""
|
||||
|
||||
|
||||
BIN
static/用户脚本截图.png
Normal file
BIN
static/用户脚本截图.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Loading…
x
Reference in New Issue
Block a user