Skip to content

Commit

Permalink
🐛✨ 修复闪退和章节名为空问题,程序优化
Browse files Browse the repository at this point in the history
1. 修复搜索闪退
2. 修复第一次使用时章节名为空的问题
3. 迁移搜索API至客户端
4. 优化启动速度(启动时不扫描库存)
5. 允许删除cookie
6.下载漫画时也保存封面
7. 其他细节优化
  • Loading branch information
shadlc committed Nov 17, 2024
1 parent cc9f6c1 commit 4e98730
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 55 deletions.
11 changes: 7 additions & 4 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@
from sys import argv, exit, platform

from PySide6.QtWidgets import QApplication, QMessageBox
from PySide6.QtGui import QIcon

from src.ui.MainGUI import MainGUI
from src.Utils import __main_window_title__, logger
from src.Utils import __main_window_title__, logger, getRamdomKaomojis

if __name__ == "__main__":
app = QApplication.instance() or QApplication(argv)

if platform == "win32" and ctypes.windll.user32.FindWindowW(None, __main_window_title__) != 0:
_box = QMessageBox.information(
None, "提示", "有一个我已经满足不了你吗?\n\t...(。•ˇ‸ˇ•。) ..."
)
box = QMessageBox()
box.setWindowTitle("提示")
box.setText(f"有一个我已经满足不了你吗?\n{getRamdomKaomojis("sad")}")
box.setWindowIcon(QIcon(":/imgs/BiliBili_favicon.ico"))
box.exec()
exit(0)
elif platform == "darwin":
script = """
Expand Down
22 changes: 21 additions & 1 deletion src/BiliPlus.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,29 @@ def __init__(self, comic_id: int, mainGUI: MainGUI) -> None:
self.biliplus_detail_url = 'https://www.biliplus.com/manga/?act=detail&mangaid='
self.headers = {
"User-Agent": f"{__app_name__}/{__version__}",
"cookie": f"{self.cookie};manga_sharing=on;manga_pic_format=jpg-full;",
"cookie": f"{self.cookie};manga_sharing=on;",
}

# ?###########################################################
# ? 配置图片下载格式
img_format_list = {
"default": "jpg-full",
"jpg": "jpg-full",
"webp": "webp-full",
"avif": "avif-full",
"1700jpg": "jpg-1700w",
"1400jpg": "jpg-1400w",
"1100jpg": "jpg-1100w",
"1400webp": "webp-1700w",
"1700webp": "webp-1400w",
"1700webp": "webp-1100w",
"1700avif": "avif-1700w",
"1400avif": "avif-1400w",
"1100avif": "avif-1700w",
}
img_format = self.mainGUI.getConfig("img_format")
self.headers["cookie"] += f"manga_pic_format_http={img_format_list.get("img_format", "jpg-full")};"

############################################################
def getComicInfo(self) -> dict:
"""使用BiliPlus 页面爬取得到的漫画数据
Expand Down
2 changes: 2 additions & 0 deletions src/Comic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from __future__ import annotations

import os
from typing import TYPE_CHECKING

import requests
Expand Down Expand Up @@ -152,6 +153,7 @@ def _() -> bytes:
fail_img.open(QFile.ReadOnly)
return bytes(fail_img.readAll())


############################################################
def getEpisodesInfo(self) -> list[Episode]:
"""获取章节信息
Expand Down
3 changes: 2 additions & 1 deletion src/Episode.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def rename_title(self) -> None:
"""

rename_rule = self.mainGUI.getConfig("rename_rule")
if "default" == rename_rule:
if not rename_rule or "default" == rename_rule:
return

rules = str(rename_rule).split("&")
Expand Down Expand Up @@ -243,6 +243,7 @@ def _() -> list[dict]:
"1100jpg": "@1100w.jpg",
"1700webp": "@1700w.webp",
"1400webp": "@1400w.webp",
"1400webp": "@1100w.webp",
"1700avif": "@1700w.avif",
"1400avif": "@1400w.avif",
"1100avif": "@1100w.avif",
Expand Down
21 changes: 11 additions & 10 deletions src/SearchComic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@

from __future__ import annotations

import json
from typing import TYPE_CHECKING

import requests
from PySide6.QtCore import QUrl
from PySide6.QtGui import QDesktopServices
from PySide6.QtWidgets import QMessageBox
from retrying import retry

from src.Utils import MAX_RETRY_SMALL, RETRY_WAIT_EX, TIMEOUT_SMALL, getRamdomKaomojis, logger
Expand All @@ -24,16 +22,17 @@ class SearchComic:
def __init__(self, comic_name: str, sessdata: str) -> None:
self.comic_name = comic_name
self.sessdata = sessdata
self.detail_url = (
"https://manga.bilibili.com/twirp/comic.v1.Comic/Search?device=pc&platform=web"
)
# self.detail_url = ("https://manga.bilibili.com/twirp/comic.v1.Comic/Search?device=pc&platform=web")
# self.payload = {"key_word": comic_name, "page_num": 1, "page_size": 99}
self.detail_url = ("https://manga.bilibili.com/twirp/search.v1.Search/SearchKeyword")
self.payload = json.dumps({"keyword": self.comic_name, "pageNum": 1, "pageSize": 99})
self.headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
"Content-Type": "application/json",
"origin": "https://manga.bilibili.com",
"referer": "https://manga.bilibili.com/search?from=manga_homepage",
"cookie": f"SESSDATA={sessdata}",
# "cookie": f"SESSDATA={sessdata}", # 使用客户端搜索API无需cookie
}
self.payload = {"key_word": comic_name, "page_num": 1, "page_size": 99}

############################################################
def getResults(self, mainGUI: MainGUI) -> list:
Expand Down Expand Up @@ -64,7 +63,9 @@ def _() -> list:
mainGUI.signal_confirm_box.emit(
f"搜索次数过多,需要人机验证,验证完毕关闭即可~ {getRamdomKaomojis("sad")}\n"
f"点击确定打开打开网页完成滑动验证",
lambda: mainGUI.signal_open_web_view.emit("风险验证", "https://manga.bilibili.com/search?keyword=%10")
lambda: mainGUI.signal_open_web_view.emit(
"风险验证", "https://manga.bilibili.com/search?keyword=%10"
)
)
return []
elif res.json().get("code") == 403:
Expand All @@ -77,7 +78,7 @@ def _() -> list:
f"获取搜索结果失败! 理由: {res.json().get("msg")} "
)
return []
return res.json()["data"]["list"]
return res.json()["data"]["comic_data"]["list"]

logger.info(f"正在搜索漫画:《{self.comic_name}》中...")

Expand Down
5 changes: 3 additions & 2 deletions src/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,9 @@ def getRamdomKaomojis(select_type: str = "") -> str:
"angry": [r",,Ծ‸Ծ,,", r"(╯‵□′)╯︵┻━┻", r"╰(‵□′)╯"],
"happy": [r"=‿=✧", r"●ω●", r"(°▽°)ノ", r"(/ ▽ \\)", r"(=・ω・=)", r"(●'◡'●)ノ♥", r"<(▰˘◡˘▰)>", r"(⁄ ⁄•⁄ω⁄•⁄ ⁄)", r"(ง,,• ᴗ •,,)ง ✧", r">ㅂ<ノ ☆", r"ヽ(✿゚▽゚)ノ", r"✪ ω ✪", r"(*゚▽゚*)"],
"shock": [r"Σ( ° △ °|||)︴", r"(゚Д゚≡゚д゚)!?", r"∑(っ °Д °;)っ", r"Σ(゚д゚;)"],
"sad": [r">︿<", r">△<", r"●︿●", r"(´;ω;`)", r"( ´・_・)ノ(._.`)"],
"helpless": [r"◐▽◑", r"ʅ(´◔౪◔)ʃ", r"_(:3 」∠)_", r"_(:3」∠ ❀)_", r"_(┐「ε:)_", r"←◡←", r"_(•̀ᴗ•́ 」∠ ❀)_", r"_φ(・ω・` )", r"¯\\_(ツ)_/¯"]
"sad": [r">︿<", r">△<", r"●︿●", r"(´;ω;`)", r"( ´・_・)ノ(._.`)", r"...(。•ˇ‸ˇ•。) ...", r"...(。•ˇ‸ˇ•。) ...", r"...(。•ˇ‸ˇ•。) ..."],
"helpless": [r"◐▽◑", r"ʅ(´◔౪◔)ʃ", r"_(:3 」∠)_", r"_(:3」∠ ❀)_", r"_(┐「ε:)_", r"←◡←", r"_(•̀ᴗ•́ 」∠ ❀)_", r"_φ(・ω・` )", r"¯\\_(ツ)_/¯"],
"": []
}
if select_type:
return random.choice(kaomojis[select_type])
Expand Down
81 changes: 53 additions & 28 deletions src/ui/MangaUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class MangaUI(QObject):
"""漫画UI类,用于搜索、下载、管理漫画"""

# ?###########################################################
# ? 用于多线程更新搜索结果
signal_search_result = Signal()

# ? 用于多线程更新我的库存
signal_my_library_add_widget = Signal(dict)

Expand Down Expand Up @@ -71,10 +74,13 @@ def __init__(self, mainGUI: MainGUI):
def init_mangaSearch(self) -> None:
"""链接搜索漫画功能"""

self.signal_search_result.connect(self.updateSearchResult)

def _() -> None:
if not self.mainGUI.getConfig("cookie"):
QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
return
# 使用客户端搜索API无需cookie
# if not self.mainGUI.getConfig("cookie"):
# QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
# return
# ? 如果输入框为空,只有空格,提示用户输入
if not self.mainGUI.lineEdit_manga_search_name.text().strip():
QMessageBox.critical(self.mainGUI, "警告", "请输入漫画名!")
Expand All @@ -93,6 +99,9 @@ def mangaSearch(self) -> None:
self.mainGUI.lineEdit_manga_search_name.text(),
self.mainGUI.getConfig("cookie"),
).getResults(self.mainGUI)
self.signal_search_result.emit()

def updateSearchResult(self) -> None:
self.mainGUI.listWidget_manga_search.clear()
self.mainGUI.label_manga_search.setText(f"{len(self.search_info)}条结果")
for item in self.search_info:
Expand All @@ -114,7 +123,6 @@ def mangaSearch(self) -> None:
),
)
self.mainGUI.pushButton_manga_search_name.setEnabled(True)



############################################################
Expand Down Expand Up @@ -180,19 +188,20 @@ def _(item: QListWidgetItem) -> None:
def init_myLibrary(self) -> None:
"""初始化我的库存"""

# ?###########################################################
# ? 检测cookie有效性并初始化我的库存漫画元数据
stored_cookie = self.mainGUI.getConfig("cookie")
# 获取漫画详情不需要登陆
# # ?###########################################################
# # ? 检测cookie有效性并初始化我的库存漫画元数据
# stored_cookie = self.mainGUI.getConfig("cookie")

def _() -> None:
self.mainGUI.lineEdit_my_cookie.setEnabled(False)
self.mainGUI.pushButton_my_cookie.setEnabled(False)
if self.mainGUI.settingUI.check_cookie_valid(stored_cookie):
self.updateMyLibrary()
# def _() -> None:
# self.mainGUI.lineEdit_my_cookie.setEnabled(False)
# self.mainGUI.pushButton_my_cookie.setEnabled(False)
# if self.mainGUI.settingUI.check_cookie_valid(stored_cookie):
# self.updateMyLibrary()

self.readMyLibrary()
if stored_cookie:
self.executor.submit(_)
# self.readMyLibrary()
# if stored_cookie:
# self.executor.submit(_)

# ?###########################################################
# ? 绑定更新我的库存事件
Expand All @@ -201,9 +210,10 @@ def _() -> None:
self.signal_my_library_add_widget.connect(self.updateMyLibrarySingleAdd)

def _() -> None:
if not self.mainGUI.getConfig("cookie"):
QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
return
# 使用客户端搜索API无需cookie
# if not self.mainGUI.getConfig("cookie"):
# QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
# return
self.readMyLibrary()
self.updateMyLibrary(notice=True)

Expand Down Expand Up @@ -789,9 +799,10 @@ def _() -> None:
if self.present_comic_id == 0:
QMessageBox.critical(self.mainGUI, "警告", "请先在搜索或库存列表选择一个漫画!")
return
if not self.mainGUI.getConfig("cookie"):
QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
return
# 使用客户端搜索API无需cookie
# if not self.mainGUI.getConfig("cookie"):
# QMessageBox.critical(self.mainGUI, "警告", "请先在设置界面填写自己的Cookie!")
# return
self.resolveEnable(False)
comic = Comic(self.present_comic_id, self.mainGUI)
self.updateComicInfoEvent(comic)
Expand Down Expand Up @@ -844,12 +855,27 @@ def _() -> None:
os.makedirs(save_path)

# ?###########################################################
# ? 保存元数据
if self.mainGUI.getConfig("save_meta") and not os.path.exists(
os.path.join(save_path, "元数据.json")
):
comic = BiliPlusComic(self.present_comic_id, self.mainGUI)
self.save_meta(comic.getComicInfo())
# ? 初始漫画对象
comic = BiliPlusComic(self.present_comic_id, self.mainGUI)

if self.mainGUI.getConfig("save_meta"):
# ?###########################################################
# ? 保存元数据
try:
if not os.path.exists(os.path.join(save_path, "元数据.json")):
self.save_meta(comic.getComicInfo())
except Exception as e:
logger.error(f"保存封面元数据失败, 跳过!\n{e}")

# ?###########################################################
# ? 保存漫画封面
try:
cover_path = os.path.join(save_path, "cover.jpg")
if not os.path.exists(cover_path):
cover = comic.getComicCover(comic.getComicInfo())
open(cover_path, "wb").write(cover)
except Exception as e:
logger.error(f"保存封面图片失败, 跳过!\n{e}")

# ?###########################################################
# ? 开始下载选中章节
Expand All @@ -860,7 +886,6 @@ def _() -> None:
item.flags() != Qt.ItemFlag.NoItemFlags
and item.checkState() == Qt.CheckState.Checked
):
comic = BiliPlusComic(self.present_comic_id, self.mainGUI)
self.mainGUI.need_sms_verify = False
self.mainGUI.downloadUI.addTask(self.mainGUI, self.epi_list[i])
item.setFlags(Qt.ItemFlag.NoItemFlags)
Expand Down
2 changes: 1 addition & 1 deletion src/ui/PySide_src/mainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,7 @@ li.checked::marker { content: &quot;\2612&quot;; }
<item>
<widget class="QCheckBox" name="checkBox_save_meta">
<property name="text">
<string>是否创建漫画元数据文件</string>
<string>是否创建漫画元数据文件和封面</string>
</property>
<property name="checked">
<bool>true</bool>
Expand Down
2 changes: 1 addition & 1 deletion src/ui/PySide_src/mainWindow_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ def retranslateUi(self, MainWindow):
self.checkBox_recursive_read.setText(QCoreApplication.translate("MainWindow", u"\u9012\u5f52\u8bfb\u53d6\u672c\u5730\u6f2b\u753b\u4ed3\u5e93", None))
self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u6587\u4ef6\u9644\u52a0\u4fe1\u606f\uff1a", None))
self.checkBox_exif_info.setText(QCoreApplication.translate("MainWindow", u"\u662f\u5426\u5728\u4fdd\u5b58\u6587\u4ef6\u5c5e\u6027\u4e2d\u8bb0\u5f55\u7ae0\u8282\u6807\u9898\u3001\u4f5c\u8005\u3001\u51fa\u7248\u793e\u7b49\u9644\u52a0\u4fe1\u606f", None))
self.checkBox_save_meta.setText(QCoreApplication.translate("MainWindow", u"\u662f\u5426\u521b\u5efa\u6f2b\u753b\u5143\u6570\u636e\u6587\u4ef6", None))
self.checkBox_save_meta.setText(QCoreApplication.translate("MainWindow", u"\u662f\u5426\u521b\u5efa\u6f2b\u753b\u5143\u6570\u636e\u6587\u4ef6\u548c\u5c01\u9762", None))
self.label_epi_rename_rule.setText(QCoreApplication.translate("MainWindow", u"\u7ae0\u8282\u547d\u540d\u89c4\u5219\uff1a", None))
self.comboBox_epi_rename_rule.setItemText(0, QCoreApplication.translate("MainWindow", u"\u9ed8\u8ba4\u547d\u540d", None))
self.comboBox_epi_rename_rule.setItemText(1, QCoreApplication.translate("MainWindow", u"\u5e8f\u53f7+\u9ed8\u8ba4\u547d\u540d", None))
Expand Down
11 changes: 5 additions & 6 deletions src/ui/SettingUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,9 @@ def init_cookie(self) -> None:

def _() -> None:
new_cookie = self.mainGUI.lineEdit_my_cookie.text().strip()
if new_cookie == "":
QMessageBox.information(self.mainGUI, "提示", "请输入Cookie!")
return
self.mainGUI.updateConfig("cookie", new_cookie)
if "" == new_cookie:
return
self.mainGUI.lineEdit_my_cookie.setEnabled(False)
self.mainGUI.pushButton_my_cookie.clearFocus()
self.mainGUI.pushButton_my_cookie.setEnabled(False)
Expand Down Expand Up @@ -238,10 +237,9 @@ def init_biliplus_cookie(self) -> None:

def _() -> None:
new_cookie = self.mainGUI.lineEdit_biliplus_cookie.text().strip()
if new_cookie == "":
QMessageBox.information(self.mainGUI, "提示", "请输入Cookie!")
return
self.mainGUI.updateConfig("biliplus_cookie", new_cookie)
if "" == new_cookie:
return
self.mainGUI.lineEdit_biliplus_cookie.setEnabled(False)
self.mainGUI.pushButton_biliplus_cookie.clearFocus()
self.mainGUI.pushButton_biliplus_cookie.setEnabled(False)
Expand Down Expand Up @@ -617,6 +615,7 @@ def init_img_format_setting(self) -> None:
"1100jpg": "1100宽jpg",
"1700webp": "1700宽webp",
"1400webp": "1400宽webp",
"1400webp": "1100宽webp",
"1700avif": "1700宽avif",
"1400avif": "1400宽avif",
"1100avif": "1100宽avif",
Expand Down
5 changes: 4 additions & 1 deletion src/ui/WebUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
from PySide6.QtGui import QIcon


if TYPE_CHECKING:
from src.ui.MainGUI import MainGUI

class WebWindow(QMainWindow):
def __init__(self, mainGUI, title: str, url: str, cookie: str):
def __init__(self, mainGUI: MainGUI, title: str, url: str, cookie: str):
self.mainGUI = mainGUI
mainGUI.web_ui = self
super().__init__()
Expand Down

0 comments on commit 4e98730

Please sign in to comment.