mirror of
https://github.com/hect0x7/JMComic-Crawler-Python.git
synced 2025-09-26 22:31:30 +08:00
v2.4.14: 更新禁漫APP端搜索接口,修复导出收藏夹插件的一些问题,优化代码。 (#189)
This commit is contained in:
parent
06237f83f9
commit
7d8fb358b7
2
.github/workflows/export_favorites.yml
vendored
2
.github/workflows/export_favorites.yml
vendored
@ -73,7 +73,7 @@ jobs:
|
||||
- name: 上传结果
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: '收藏夹导出zip'
|
||||
name: '导出的收藏夹'
|
||||
path: ${{ env.ZIP_FP }}
|
||||
if-no-files-found: error
|
||||
retention-days: 90
|
||||
|
@ -24,4 +24,4 @@ plugins:
|
||||
msg_to: ${EMAIL_TO}
|
||||
password: ${EMAIL_PASS}
|
||||
title: ${EMAIL_TITLE}
|
||||
content: ${EMAIL_CONTENT}
|
||||
content: ${EMAIL_CONTENT}
|
||||
|
@ -2,7 +2,7 @@
|
||||
# 被依赖方 <--- 使用方
|
||||
# config <--- entity <--- toolkit <--- client <--- option <--- downloader
|
||||
|
||||
__version__ = '2.4.13'
|
||||
__version__ = '2.4.14'
|
||||
|
||||
from .api import *
|
||||
from .jm_plugin import *
|
||||
|
@ -318,7 +318,7 @@ class JmModuleConfig:
|
||||
# 一般情况下,建议使用option配置文件来定制配置
|
||||
# 而如果只想修改几个简单常用的配置,也可以下方的DEFAULT_XXX属性
|
||||
JM_OPTION_VER = '2.1'
|
||||
DEFAULT_CLIENT_IMPL = 'html' # 默认Client实现类型为网页端
|
||||
DEFAULT_CLIENT_IMPL = 'api' # 默认Client实现类型为网页端
|
||||
DEFAULT_CLIENT_CACHE = True # 默认开启Client缓存,缓存级别是level_option,详见CacheRegistry
|
||||
DEFAULT_PROXIES = ProxyBuilder.system_proxy() # 默认使用系统代理
|
||||
|
||||
@ -345,7 +345,7 @@ class JmModuleConfig:
|
||||
}
|
||||
},
|
||||
'impl': None,
|
||||
'retry_times': 5
|
||||
'retry_times': 5,
|
||||
},
|
||||
'plugins': {
|
||||
# 如果插件抛出参数校验异常,只log。(全局配置,可以被插件的局部配置覆盖)
|
||||
|
@ -524,7 +524,7 @@ class JmPageContent(JmBaseEntity, IndexedEntity):
|
||||
"""
|
||||
content:
|
||||
[
|
||||
album_id, {title, tag_list, ...}
|
||||
album_id, {title, tags, ...}
|
||||
]
|
||||
:param content: 分页数据
|
||||
:param total: 总结果数
|
||||
@ -564,11 +564,11 @@ class JmPageContent(JmBaseEntity, IndexedEntity):
|
||||
|
||||
def iter_id_title_tag(self) -> Generator[Tuple[str, str, List[str]], None, None]:
|
||||
"""
|
||||
返回 album_id, album_title, album_tag_list 的迭代器
|
||||
返回 album_id, album_title, album_tags 的迭代器
|
||||
"""
|
||||
for aid, ainfo in self.content:
|
||||
ainfo.setdefault('tag_list', [])
|
||||
yield aid, ainfo['name'], ainfo['tag_list']
|
||||
ainfo.setdefault('tags', [])
|
||||
yield aid, ainfo['name'], ainfo['tags']
|
||||
|
||||
# 下面的方法实现方便的元素访问
|
||||
|
||||
@ -610,7 +610,7 @@ class JmSearchPage(JmPageContent):
|
||||
page = JmSearchPage([(
|
||||
album.album_id, {
|
||||
'name': album.name,
|
||||
'tag_list': album.tags,
|
||||
'tags': album.tags,
|
||||
}
|
||||
)], 1)
|
||||
setattr(page, 'album', album)
|
||||
|
@ -44,22 +44,17 @@ class JmOptionPlugin:
|
||||
msg=msg
|
||||
)
|
||||
|
||||
def require_true(self, case: Any, msg: str, is_param_validation=True):
|
||||
def require_param(self, case: Any, msg: str):
|
||||
"""
|
||||
独立于ExceptionTool的一套异常抛出体系
|
||||
|
||||
专门用于校验参数的方法,会抛出特定异常,由option拦截根据策略进行处理
|
||||
|
||||
:param case: 条件
|
||||
:param msg: 报错信息
|
||||
:param is_param_validation: True 表示 调用本方法是用于校验参数,则会抛出特定异常(PluginValidationException)
|
||||
"""
|
||||
if case:
|
||||
return
|
||||
|
||||
if is_param_validation:
|
||||
raise PluginValidationException(self, msg)
|
||||
else:
|
||||
ExceptionTool.raises(msg)
|
||||
raise PluginValidationException(self, msg)
|
||||
|
||||
def warning_lib_not_install(self, lib: str):
|
||||
msg = (f'插件`{self.plugin_key}`依赖库: {lib},请先安装{lib}再使用。'
|
||||
@ -94,6 +89,11 @@ class JmOptionPlugin:
|
||||
"""
|
||||
return os.system(cmd)
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
def execute_multi_line_cmd(self, cmd: str):
|
||||
import subprocess
|
||||
subprocess.run(cmd, shell=True, check=True)
|
||||
|
||||
|
||||
class JmLoginPlugin(JmOptionPlugin):
|
||||
"""
|
||||
@ -106,10 +106,10 @@ class JmLoginPlugin(JmOptionPlugin):
|
||||
password: str,
|
||||
impl=None,
|
||||
) -> None:
|
||||
self.require_true(username, '用户名不能为空')
|
||||
self.require_true(password, '密码不能为空')
|
||||
self.require_param(username, '用户名不能为空')
|
||||
self.require_param(password, '密码不能为空')
|
||||
|
||||
client = self.option.new_jm_client(impl=impl)
|
||||
client = self.option.build_jm_client(impl=impl)
|
||||
client.login(username, password)
|
||||
|
||||
cookies = dict(client['cookies'])
|
||||
@ -459,7 +459,7 @@ class SendQQEmailPlugin(JmOptionPlugin):
|
||||
album=None,
|
||||
downloader=None,
|
||||
) -> None:
|
||||
self.require_true(msg_from and msg_to and password, '发件人、收件人、授权码都不能为空')
|
||||
self.require_param(msg_from and msg_to and password, '发件人、收件人、授权码都不能为空')
|
||||
|
||||
from common import EmailConfig
|
||||
econfig = EmailConfig(msg_from, msg_to, password)
|
||||
@ -551,7 +551,7 @@ class FavoriteFolderExportPlugin(JmOptionPlugin):
|
||||
zip_password=None,
|
||||
delete_original_file=False,
|
||||
):
|
||||
self.save_dir = os.path.abspath(save_dir if save_dir is not None else os.getcwd() + '/export/')
|
||||
self.save_dir = os.path.abspath(save_dir if save_dir is not None else (os.getcwd() + '/export/'))
|
||||
self.zip_enable = zip_enable
|
||||
self.zip_filepath = os.path.abspath(zip_filepath)
|
||||
self.zip_password = zip_password
|
||||
@ -564,7 +564,7 @@ class FavoriteFolderExportPlugin(JmOptionPlugin):
|
||||
self.main()
|
||||
|
||||
def main(self):
|
||||
cl = self.option.new_jm_client(impl=JmApiClient)
|
||||
cl = self.option.build_jm_client()
|
||||
# noinspection PyAttributeOutsideInit
|
||||
self.cl = cl
|
||||
page = cl.favorite_folder()
|
||||
@ -584,7 +584,7 @@ class FavoriteFolderExportPlugin(JmOptionPlugin):
|
||||
return
|
||||
|
||||
# 压缩导出的文件
|
||||
self.require_true(self.zip_filepath, '如果开启zip,请指定zip_filepath参数(压缩文件保存路径)')
|
||||
self.require_param(self.zip_filepath, '如果开启zip,请指定zip_filepath参数(压缩文件保存路径)')
|
||||
|
||||
if self.zip_password is None:
|
||||
self.zip_folder_without_password(self.files, self.zip_filepath)
|
||||
@ -650,12 +650,16 @@ class FavoriteFolderExportPlugin(JmOptionPlugin):
|
||||
zipf.write(file, arcname=of_file_name(file))
|
||||
|
||||
def zip_with_password(self):
|
||||
os.chdir(self.save_dir)
|
||||
cmd = f'7z a "{self.zip_filepath}" "{self.save_dir}" -p{self.zip_password} -mhe=on'
|
||||
self.require_true(
|
||||
0 == self.execute_cmd(cmd),
|
||||
'加密压缩文件失败'
|
||||
)
|
||||
# 构造shell命令
|
||||
cmd_list = f'''
|
||||
cd {self.save_dir}
|
||||
7z a "{self.zip_filepath}" "./" -p{self.zip_password} -mhe=on > "../7z_output.txt"
|
||||
|
||||
'''
|
||||
self.log(f'运行命令: {cmd_list}')
|
||||
|
||||
# 执行
|
||||
self.execute_multi_line_cmd(cmd_list)
|
||||
|
||||
|
||||
class ConvertJpgToPdfPlugin(JmOptionPlugin):
|
||||
@ -726,11 +730,10 @@ class ConvertJpgToPdfPlugin(JmOptionPlugin):
|
||||
self.log(f'Execute Command: [{cmd}]')
|
||||
code = self.execute_cmd(cmd)
|
||||
|
||||
self.require_true(
|
||||
ExceptionTool.require_true(
|
||||
code == 0,
|
||||
'jpg图片合并为pdf失败!'
|
||||
'请确认你是否安装了magick,安装网站: [http://www.imagemagick.org/]',
|
||||
False,
|
||||
)
|
||||
|
||||
self.log(f'Convert Successfully: JM{photo.id} → {pdf_filepath}')
|
||||
|
@ -371,7 +371,7 @@ class JmPageTool:
|
||||
)
|
||||
|
||||
# 用来查找tag列表
|
||||
pattern_html_search_tag_list = compile(r'<a[^>]*?>(.*?)</a>')
|
||||
pattern_html_search_tags = compile(r'<a[^>]*?>(.*?)</a>')
|
||||
|
||||
# 查找错误,例如 [错误,關鍵字過短,請至少輸入兩個字以上。]
|
||||
pattern_html_search_error = compile(r'<fieldset>\n<legend>(.*?)</legend>\n<div class=.*?>\n(.*?)\n</div>\n</fieldset>')
|
||||
@ -418,11 +418,11 @@ class JmPageTool:
|
||||
album_info_list = cls.pattern_html_search_album_info_list.findall(html)
|
||||
|
||||
for (album_id, title, _, label_category, label_sub, tag_text) in album_info_list:
|
||||
tag_list = cls.pattern_html_search_tag_list.findall(tag_text)
|
||||
tags = cls.pattern_html_search_tags.findall(tag_text)
|
||||
content.append((
|
||||
album_id, {
|
||||
'name': title, # 改成name是为了兼容 parse_api_resp_to_page
|
||||
'tag_list': tag_list
|
||||
'tags': tags
|
||||
}
|
||||
))
|
||||
|
||||
@ -436,11 +436,11 @@ class JmPageTool:
|
||||
album_info_list = cls.pattern_html_category_album_info_list.findall(html)
|
||||
|
||||
for (album_id, title, tag_text) in album_info_list:
|
||||
tag_list = cls.pattern_html_search_tag_list.findall(tag_text)
|
||||
tags = cls.pattern_html_search_tags.findall(tag_text)
|
||||
content.append((
|
||||
album_id, {
|
||||
'name': title, # 改成name是为了兼容 parse_api_resp_to_page
|
||||
'tag_list': tag_list
|
||||
'tags': tags
|
||||
}
|
||||
))
|
||||
|
||||
@ -494,7 +494,7 @@ class JmPageTool:
|
||||
]
|
||||
}
|
||||
"""
|
||||
total: int = int(data.total)
|
||||
total: int = int(data.total or 0) # 2024.1.5 data.total可能为None
|
||||
content = cls.adapt_content(data.content)
|
||||
return JmSearchPage(content, total)
|
||||
|
||||
@ -546,7 +546,7 @@ class JmPageTool:
|
||||
def adapt_content(cls, content):
|
||||
def adapt_item(item: DictModel):
|
||||
item: dict = item.src_dict
|
||||
item.setdefault('tag_list', [])
|
||||
item.setdefault('tags', [])
|
||||
return item
|
||||
|
||||
content = [
|
||||
|
@ -22,8 +22,8 @@ class Test_Client(JmTestConfigurable):
|
||||
for aid, ainfo in page[0:1:1]:
|
||||
print(aid, ainfo)
|
||||
|
||||
for aid, atitle, tag_list in page.iter_id_title_tag():
|
||||
print(aid, atitle, tag_list)
|
||||
for aid, atitle, tags in page.iter_id_title_tag():
|
||||
print(aid, atitle, tags)
|
||||
|
||||
aid = '438516'
|
||||
page = self.client.search_site(aid)
|
||||
|
@ -32,6 +32,8 @@ def prepare_actions_input_and_secrets():
|
||||
|
||||
def main():
|
||||
prepare_actions_input_and_secrets()
|
||||
# 关闭logging,保证安全
|
||||
disable_jm_log()
|
||||
option = create_option('../assets/option/option_workflow_export_favorites.yml')
|
||||
option.call_all_plugin('main', safe=False)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user