Skip to content

Commit dec2d54

Browse files
authored
v2.5.9: 新增插件【跳过下载图片数少的章节】,可过滤一些公告章节; 新增Downloadable基类,对插件扩展更友好; 修复本子名过长超出导致oserror的错误; 升级curl_cffi. (#222)
1 parent ee23037 commit dec2d54

12 files changed

+102
-48
lines changed

assets/docs/sources/option_file_syntax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ plugins:
198198
zip_enable: true # 对收藏夹进行压缩
199199
zip_filepath: ${JM_DOWNLOAD_DIR}/export.zip # 压缩文件路径
200200
zip_password: ${ZIP_PASSWORD} # 压缩密码
201+
202+
before_photo:
203+
- plugin: skip_photo_with_few_images # 跳过下载章节图片数量过少的章节。一些韩漫的章节是公告,没有实际内容,就可以用该插件来跳过下载这些章节。
204+
kwargs:
205+
at_least_image_count: 3
201206

202207
after_photo:
203208
- plugin: j2p # jpg图片合成为一个pdf插件

requirements-dev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
commonX
21
curl_cffi
2+
commonX
33
PyYAML
44
Pillow
55
psutil

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
package_dir={"": "src"},
2828
python_requires=">=3.7",
2929
install_requires=[
30-
'commonX>=0.6.4',
3130
'curl_cffi',
31+
'commonX',
3232
'PyYAML',
3333
'Pillow',
3434
'pycryptodome',

src/jmcomic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# 被依赖方 <--- 使用方
33
# config <--- entity <--- toolkit <--- client <--- option <--- downloader
44

5-
__version__ = '2.5.8'
5+
__version__ = '2.5.9'
66

77
from .api import *
88
from .jm_plugin import *

src/jmcomic/jm_client_impl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def append_params_to_url(self, url, params):
224224

225225
# noinspection PyMethodMayBeStatic
226226
def decode(self, url: str):
227-
if not JmModuleConfig.flag_decode_url_when_logging or '/search/' not in url:
227+
if not JmModuleConfig.FLAG_DECODE_URL_WHEN_LOGGING or '/search/' not in url:
228228
return url
229229

230230
from urllib.parse import unquote
@@ -767,7 +767,7 @@ def setting(self) -> JmApiResp:
767767
# 检查禁漫最新的版本号
768768
setting_ver = str(resp.model_data.version)
769769
# 禁漫接口的版本 > jmcomic库内置版本
770-
if setting_ver > JmMagicConstants.APP_VERSION and JmModuleConfig.flag_use_version_newer_if_behind:
770+
if setting_ver > JmMagicConstants.APP_VERSION and JmModuleConfig.FLAG_USE_VERSION_NEWER_IF_BEHIND:
771771
jm_log('api.setting', f'change APP_VERSION from [{JmMagicConstants.APP_VERSION}] to [{setting_ver}]')
772772
JmMagicConstants.APP_VERSION = setting_ver
773773

@@ -883,7 +883,7 @@ def decide_headers_and_ts(self, kwargs, url):
883883
ts = time_stamp()
884884
token, tokenparam = JmCryptoTool.token_and_tokenparam(ts, secret=JmMagicConstants.APP_TOKEN_SECRET_2)
885885

886-
elif JmModuleConfig.flag_use_fix_timestamp:
886+
elif JmModuleConfig.FLAG_USE_FIX_TIMESTAMP:
887887
ts, token, tokenparam = JmModuleConfig.get_fix_ts_token_tokenparam()
888888

889889
else:
@@ -954,7 +954,7 @@ def raise_if_resp_should_retry(self, resp):
954954

955955
def after_init(self):
956956
# 保证拥有cookies,因为移动端要求必须携带cookies,否则会直接跳转同一本子【禁漫娘】
957-
if JmModuleConfig.flag_api_client_require_cookies:
957+
if JmModuleConfig.FLAG_API_CLIENT_REQUIRE_COOKIES:
958958
self.ensure_have_cookies()
959959

960960
client_init_cookies_lock = Lock()

src/jmcomic/jm_config.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,25 +146,29 @@ class JmModuleConfig:
146146
REGISTRY_EXCEPTION_LISTENER = {}
147147

148148
# 执行log的函数
149-
executor_log = default_jm_logging
149+
EXECUTOR_LOG = default_jm_logging
150150

151151
# 使用固定时间戳
152-
flag_use_fix_timestamp = True
152+
FLAG_USE_FIX_TIMESTAMP = True
153153
# 移动端Client初始化cookies
154-
flag_api_client_require_cookies = True
154+
FLAG_API_CLIENT_REQUIRE_COOKIES = True
155155
# log开关标记
156-
flag_enable_jm_log = True
156+
FLAG_ENABLE_JM_LOG = True
157157
# log时解码url
158-
flag_decode_url_when_logging = True
158+
FLAG_DECODE_URL_WHEN_LOGGING = True
159159
# 当内置的版本号落后时,使用最新的禁漫app版本号
160-
flag_use_version_newer_if_behind = True
160+
FLAG_USE_VERSION_NEWER_IF_BEHIND = True
161161

162162
# 关联dir_rule的自定义字段与对应的处理函数
163163
# 例如:
164164
# Amyname -> JmModuleConfig.AFIELD_ADVICE['myname'] = lambda album: "自定义名称"
165165
AFIELD_ADVICE = dict()
166166
PFIELD_ADVICE = dict()
167167

168+
# 当发生 oserror: [Errno 36] File name too long 时,
169+
# 把文件名限制在指定个字符以内
170+
VAR_FILE_NAME_LENGTH_LIMIT = 100
171+
168172
@classmethod
169173
def downloader_class(cls):
170174
if cls.CLASS_DOWNLOADER is not None:
@@ -319,12 +323,12 @@ def get_fix_ts_token_tokenparam(cls):
319323
# noinspection PyUnusedLocal
320324
@classmethod
321325
def jm_log(cls, topic: str, msg: str):
322-
if cls.flag_enable_jm_log is True:
323-
cls.executor_log(topic, msg)
326+
if cls.FLAG_ENABLE_JM_LOG is True:
327+
cls.EXECUTOR_LOG(topic, msg)
324328

325329
@classmethod
326330
def disable_jm_log(cls):
327-
cls.flag_enable_jm_log = False
331+
cls.FLAG_ENABLE_JM_LOG = False
328332

329333
@classmethod
330334
def new_postman(cls, session=False, **kwargs):
@@ -347,7 +351,7 @@ def new_postman(cls, session=False, **kwargs):
347351
DEFAULT_CLIENT_CACHE = None # 默认关闭Client缓存。缓存的配置详见 CacheRegistry
348352
DEFAULT_PROXIES = ProxyBuilder.system_proxy() # 默认使用系统代理
349353

350-
default_option_dict: dict = {
354+
DEFAULT_OPTION_DICT: dict = {
351355
'log': None,
352356
'dir_rule': {'rule': 'Bd_Pname', 'base_dir': None},
353357
'download': {
@@ -364,7 +368,7 @@ def new_postman(cls, session=False, **kwargs):
364368
'postman': {
365369
'type': 'cffi',
366370
'meta_data': {
367-
'impersonate': 'chrome110',
371+
'impersonate': 'chrome',
368372
'headers': None,
369373
'proxies': None,
370374
}
@@ -387,11 +391,11 @@ def option_default_dict(cls) -> dict:
387391
"""
388392
from copy import deepcopy
389393

390-
option_dict = deepcopy(cls.default_option_dict)
394+
option_dict = deepcopy(cls.DEFAULT_OPTION_DICT)
391395

392396
# log
393397
if option_dict['log'] is None:
394-
option_dict['log'] = cls.flag_enable_jm_log
398+
option_dict['log'] = cls.FLAG_ENABLE_JM_LOG
395399

396400
# dir_rule.base_dir
397401
dir_rule = option_dict['dir_rule']

src/jmcomic/jm_downloader.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def after_photo(self, photo: JmPhotoDetail):
2929
f'章节下载完成: [{photo.id}] ({photo.album_id}[{photo.index}/{len(photo.from_album)}])')
3030

3131
def before_image(self, image: JmImageDetail, img_save_path):
32-
if image.is_exists:
32+
if image.exists:
3333
jm_log('image.before',
3434
f'图片已存在: {image.tag} ← [{img_save_path}]'
3535
)
@@ -63,6 +63,8 @@ def download_album(self, album_id):
6363

6464
def download_by_album_detail(self, album: JmAlbumDetail, client: JmcomicClient):
6565
self.before_album(album)
66+
if album.skip:
67+
return
6668
self.execute_by_condition(
6769
iter_objs=album,
6870
apply=lambda photo: self.download_by_photo_detail(photo, client),
@@ -80,6 +82,8 @@ def download_by_photo_detail(self, photo: JmPhotoDetail, client: JmcomicClient):
8082
client.check_photo(photo)
8183

8284
self.before_photo(photo)
85+
if photo.skip:
86+
return
8387
self.execute_by_condition(
8488
iter_objs=photo,
8589
apply=lambda image: self.download_by_image_detail(image, client),
@@ -91,16 +95,19 @@ def download_by_image_detail(self, image: JmImageDetail, client: JmcomicClient):
9195
img_save_path = self.option.decide_image_filepath(image)
9296

9397
image.save_path = img_save_path
94-
image.is_exists = file_exists(img_save_path)
98+
image.exists = file_exists(img_save_path)
9599

96100
self.before_image(image, img_save_path)
97101

102+
if image.skip:
103+
return
104+
98105
# let option decide use_cache and decode_image
99106
use_cache = self.option.decide_download_cache(image)
100107
decode_image = self.option.decide_download_image_decode(image)
101108

102109
# skip download
103-
if use_cache is True and image.is_exists:
110+
if use_cache is True and image.exists:
104111
return
105112

106113
e = None

src/jmcomic/jm_entity.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
from .jm_config import *
44

55

6+
class Downloadable:
7+
8+
def __init__(self):
9+
self.save_path: str = ''
10+
self.exists: bool = False
11+
self.skip = False
12+
13+
614
class JmBaseEntity:
715

816
def to_file(self, filepath):
@@ -117,7 +125,7 @@ def idoname(self):
117125
def __str__(self):
118126
return f'{self.__class__.__name__}' \
119127
'{' \
120-
f'{self.id}: {self.title}'\
128+
f'{self.id}: {self.title}' \
121129
'}'
122130

123131
@classmethod
@@ -156,7 +164,7 @@ def get_dirname(cls, detail: 'DetailEntity', ref: str) -> str:
156164
return getattr(detail, ref)
157165

158166

159-
class JmImageDetail(JmBaseEntity):
167+
class JmImageDetail(JmBaseEntity, Downloadable):
160168

161169
def __init__(self,
162170
aid,
@@ -167,7 +175,8 @@ def __init__(self,
167175
from_photo=None,
168176
query_params=None,
169177
index=-1,
170-
) -> None:
178+
):
179+
super().__init__()
171180
if scramble_id is None or (isinstance(scramble_id, str) and scramble_id == ''):
172181
from .jm_toolkit import ExceptionTool
173182
ExceptionTool.raises(f'图片的scramble_id不能为空')
@@ -182,10 +191,6 @@ def __init__(self,
182191
self.query_params: Optional[str] = query_params
183192
self.index = index # 从1开始
184193

185-
# temp fields, in order to simplify passing parameter
186-
self.save_path: str = ''
187-
self.is_exists: bool = False
188-
189194
@property
190195
def filename_without_suffix(self):
191196
return self.img_file_name
@@ -252,7 +257,7 @@ def is_image(cls):
252257
return True
253258

254259

255-
class JmPhotoDetail(DetailEntity):
260+
class JmPhotoDetail(DetailEntity, Downloadable):
256261

257262
def __init__(self,
258263
photo_id,
@@ -267,6 +272,7 @@ def __init__(self,
267272
author=None,
268273
from_album=None,
269274
):
275+
super().__init__()
270276
self.photo_id: str = str(photo_id)
271277
self.scramble_id: str = str(scramble_id)
272278
self.name: str = str(name).strip()
@@ -411,7 +417,7 @@ def is_photo(cls):
411417
return True
412418

413419

414-
class JmAlbumDetail(DetailEntity):
420+
class JmAlbumDetail(DetailEntity, Downloadable):
415421

416422
def __init__(self,
417423
album_id,
@@ -430,6 +436,7 @@ def __init__(self,
430436
tags,
431437
related_list=None,
432438
):
439+
super().__init__()
433440
self.album_id: str = str(album_id)
434441
self.scramble_id: str = str(scramble_id)
435442
self.name: str = name

src/jmcomic/jm_exception.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ class ExceptionTool:
7272
CONTEXT_KEY_RE_PATTERN = 'pattern'
7373
CONTEXT_KEY_MISSING_JM_ID = 'missing_jm_id'
7474

75-
# 兼容旧版本
76-
77-
EXTRA_KEY_RESP = 'resp'
78-
EXTRA_KEY_HTML = 'html'
79-
EXTRA_KEY_RE_PATTERN = 'pattern'
80-
EXTRA_KEY_MISSING_JM_ID = 'missing_jm_id'
81-
8275
@classmethod
8376
def raises(cls,
8477
msg: str,
@@ -144,7 +137,8 @@ def raise_missing(cls,
144137
:param resp: 响应对象
145138
:param jmid: 禁漫本子/章节id
146139
"""
147-
url = resp.url
140+
from .jm_toolkit import JmcomicText
141+
url = JmcomicText.format_album_url(jmid)
148142

149143
req_type = "本子" if "album" in url else "章节"
150144
cls.raises(

src/jmcomic/jm_option.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,15 @@ def decide_image_save_dir(self, photo, ensure_exists=True) -> str:
285285
)
286286

287287
if ensure_exists:
288-
mkdir_if_not_exists(save_dir)
288+
try:
289+
mkdir_if_not_exists(save_dir)
290+
except OSError as e:
291+
if e.errno == 36:
292+
# 目录名过长
293+
limit = JmModuleConfig.VAR_FILE_NAME_LENGTH_LIMIT
294+
jm_log('error', f'目录名过长,无法创建目录,强制缩短到{limit}个字符并重试')
295+
save_dir = save_dir[0:limit]
296+
mkdir_if_not_exists(save_dir)
289297

290298
return save_dir
291299

@@ -359,7 +367,7 @@ def compatible_with_old_versions(cls, dic):
359367
def deconstruct(self) -> Dict:
360368
return {
361369
'version': JmModuleConfig.JM_OPTION_VER,
362-
'log': JmModuleConfig.flag_enable_jm_log,
370+
'log': JmModuleConfig.FLAG_ENABLE_JM_LOG,
363371
'dir_rule': {
364372
'rule': self.dir_rule.rule_dsl,
365373
'base_dir': self.dir_rule.base_dir,

0 commit comments

Comments
 (0)