jmcomic 2.5.36__py3-none-any.whl → 2.5.38__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jmcomic/__init__.py +1 -1
- jmcomic/jm_option.py +51 -85
- jmcomic/jm_plugin.py +1 -1
- jmcomic/jm_toolkit.py +1 -1
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/METADATA +1 -1
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/RECORD +10 -10
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/WHEEL +1 -1
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/entry_points.txt +0 -0
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/licenses/LICENSE +0 -0
- {jmcomic-2.5.36.dist-info → jmcomic-2.5.38.dist-info}/top_level.txt +0 -0
jmcomic/__init__.py
CHANGED
jmcomic/jm_option.py
CHANGED
|
@@ -58,90 +58,85 @@ class CacheRegistry:
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class DirRule:
|
|
61
|
-
|
|
62
|
-
# 根目录 / Album-id / Photo-序号 /
|
|
63
|
-
'Bd_Aid_Pindex', # 禁漫网站的默认下载方式
|
|
64
|
-
# 根目录 / Album-作者 / Album-标题 / Photo-序号 /
|
|
65
|
-
'Bd_Aauthor_Atitle_Pindex',
|
|
66
|
-
# 根目录 / Photo-序号&标题 /
|
|
67
|
-
'Bd_Pindextitle',
|
|
68
|
-
# 根目录 / Photo-自定义类属性 /
|
|
69
|
-
'Bd_Aauthor_Atitle_Pcustomfield',
|
|
70
|
-
# 需要替换JmModuleConfig.CLASS_ALBUM / CLASS_PHOTO才能让自定义属性生效
|
|
71
|
-
]
|
|
72
|
-
|
|
73
|
-
Detail = Union[JmAlbumDetail, JmPhotoDetail, None]
|
|
74
|
-
RuleFunc = Callable
|
|
75
|
-
RuleSolver = Tuple[str, RuleFunc, str]
|
|
76
|
-
RuleSolverList = List[RuleSolver]
|
|
61
|
+
RULE_BASE_DIR = 'Bd'
|
|
77
62
|
|
|
78
63
|
def __init__(self, rule: str, base_dir=None):
|
|
79
64
|
base_dir = JmcomicText.parse_to_abspath(base_dir)
|
|
80
65
|
self.base_dir = base_dir
|
|
81
66
|
self.rule_dsl = rule
|
|
82
|
-
self.
|
|
67
|
+
self.parser_list: List[Tuple[str, Callable]] = self.get_rule_parser_list(rule)
|
|
83
68
|
|
|
84
69
|
def decide_image_save_dir(self,
|
|
85
70
|
album: JmAlbumDetail,
|
|
86
71
|
photo: JmPhotoDetail,
|
|
87
72
|
) -> str:
|
|
88
|
-
|
|
89
|
-
for solver in self.solver_list:
|
|
90
|
-
try:
|
|
91
|
-
ret = self.apply_rule_solver(album, photo, solver)
|
|
92
|
-
except BaseException as e:
|
|
93
|
-
# noinspection PyUnboundLocalVariable
|
|
94
|
-
jm_log('dir_rule', f'路径规则"{solver[2]}"的解析出错: {e}, album={album}, photo={photo}')
|
|
95
|
-
raise e
|
|
96
|
-
|
|
97
|
-
path_ls.append(str(ret))
|
|
98
|
-
|
|
99
|
-
return fix_filepath('/'.join(path_ls), is_dir=True)
|
|
73
|
+
return self._build_path_from_rules(album, photo)
|
|
100
74
|
|
|
101
75
|
def decide_album_root_dir(self, album: JmAlbumDetail) -> str:
|
|
102
|
-
|
|
103
|
-
for solver in self.solver_list:
|
|
104
|
-
key, _, rule = solver
|
|
76
|
+
return self._build_path_from_rules(album, None, True)
|
|
105
77
|
|
|
106
|
-
|
|
78
|
+
def _build_path_from_rules(self, album, photo, only_album_rules=False) -> str:
|
|
79
|
+
path_ls = []
|
|
80
|
+
for rule, parser in self.parser_list:
|
|
81
|
+
if only_album_rules and not (rule == self.RULE_BASE_DIR or rule.startswith('A')):
|
|
107
82
|
continue
|
|
108
83
|
|
|
109
84
|
try:
|
|
110
|
-
|
|
85
|
+
path = parser(album, photo, rule)
|
|
111
86
|
except BaseException as e:
|
|
112
87
|
# noinspection PyUnboundLocalVariable
|
|
113
|
-
jm_log('dir_rule', f'路径规则"{rule}"的解析出错: {e}, album={album}')
|
|
88
|
+
jm_log('dir_rule', f'路径规则"{rule}"的解析出错: {e}, album={album}, photo={photo}')
|
|
114
89
|
raise e
|
|
90
|
+
if parser != self.parse_bd_rule:
|
|
91
|
+
path = fix_windir_name(str(path)).strip()
|
|
115
92
|
|
|
116
|
-
path_ls.append(
|
|
93
|
+
path_ls.append(path)
|
|
117
94
|
|
|
118
95
|
return fix_filepath('/'.join(path_ls), is_dir=True)
|
|
119
96
|
|
|
120
|
-
def
|
|
97
|
+
def get_rule_parser_list(self, rule_dsl: str):
|
|
121
98
|
"""
|
|
122
99
|
解析下载路径dsl,得到一个路径规则解析列表
|
|
123
100
|
"""
|
|
124
101
|
|
|
125
102
|
rule_list = self.split_rule_dsl(rule_dsl)
|
|
126
|
-
|
|
103
|
+
parser_list: list = []
|
|
127
104
|
|
|
128
105
|
for rule in rule_list:
|
|
129
106
|
rule = rule.strip()
|
|
130
|
-
if rule ==
|
|
131
|
-
|
|
107
|
+
if rule == self.RULE_BASE_DIR:
|
|
108
|
+
parser_list.append((rule, self.parse_bd_rule))
|
|
132
109
|
continue
|
|
133
110
|
|
|
134
|
-
|
|
135
|
-
if
|
|
111
|
+
parser = self.get_rule_parser(rule)
|
|
112
|
+
if parser is None:
|
|
136
113
|
ExceptionTool.raises(f'不支持的dsl: "{rule}" in "{rule_dsl}"')
|
|
137
114
|
|
|
138
|
-
|
|
115
|
+
parser_list.append((rule, parser))
|
|
116
|
+
|
|
117
|
+
return parser_list
|
|
118
|
+
|
|
119
|
+
# noinspection PyUnusedLocal
|
|
120
|
+
def parse_bd_rule(self, album, photo, rule):
|
|
121
|
+
return self.base_dir
|
|
122
|
+
|
|
123
|
+
@classmethod
|
|
124
|
+
def parse_f_string_rule(cls, album, photo, rule: str):
|
|
125
|
+
properties = {}
|
|
126
|
+
if album:
|
|
127
|
+
properties.update(album.get_properties_dict())
|
|
128
|
+
if photo:
|
|
129
|
+
properties.update(photo.get_properties_dict())
|
|
130
|
+
return rule.format(**properties)
|
|
139
131
|
|
|
140
|
-
|
|
132
|
+
@classmethod
|
|
133
|
+
def parse_detail_rule(cls, album, photo, rule: str):
|
|
134
|
+
detail = album if rule.startswith('A') else photo
|
|
135
|
+
return str(DetailEntity.get_dirname(detail, rule[1:]))
|
|
141
136
|
|
|
142
137
|
# noinspection PyMethodMayBeStatic
|
|
143
|
-
def split_rule_dsl(self, rule_dsl: str)
|
|
144
|
-
if rule_dsl ==
|
|
138
|
+
def split_rule_dsl(self, rule_dsl: str):
|
|
139
|
+
if rule_dsl == self.RULE_BASE_DIR:
|
|
145
140
|
return [rule_dsl]
|
|
146
141
|
|
|
147
142
|
if '/' in rule_dsl:
|
|
@@ -153,50 +148,21 @@ class DirRule:
|
|
|
153
148
|
ExceptionTool.raises(f'不支持的rule配置: "{rule_dsl}"')
|
|
154
149
|
|
|
155
150
|
@classmethod
|
|
156
|
-
def
|
|
151
|
+
def get_rule_parser(cls, rule: str):
|
|
157
152
|
if '{' in rule:
|
|
158
|
-
|
|
159
|
-
return fix_windir_name(rule.format(**album.get_properties_dict(), **photo.get_properties_dict())).strip()
|
|
160
|
-
|
|
161
|
-
return 'F', format_path, rule
|
|
153
|
+
return cls.parse_f_string_rule
|
|
162
154
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return None
|
|
155
|
+
if rule.startswith(('A', 'P')):
|
|
156
|
+
return cls.parse_detail_rule
|
|
166
157
|
|
|
167
|
-
|
|
168
|
-
return fix_windir_name(str(DetailEntity.get_dirname(detail, rule[1:]))).strip()
|
|
169
|
-
|
|
170
|
-
return rule[0], solve_func, rule
|
|
171
|
-
|
|
172
|
-
@classmethod
|
|
173
|
-
def apply_rule_solver(cls, album, photo, rule_solver: RuleSolver) -> str:
|
|
174
|
-
"""
|
|
175
|
-
应用规则解析器(RuleSolver)
|
|
176
|
-
|
|
177
|
-
:param album: JmAlbumDetail
|
|
178
|
-
:param photo: JmPhotoDetail
|
|
179
|
-
:param rule_solver: Ptitle
|
|
180
|
-
:returns: photo.title
|
|
181
|
-
"""
|
|
182
|
-
|
|
183
|
-
def choose_detail(key):
|
|
184
|
-
if key == 'Bd':
|
|
185
|
-
return None,
|
|
186
|
-
if key == 'A':
|
|
187
|
-
return album,
|
|
188
|
-
if key == 'P':
|
|
189
|
-
return photo,
|
|
190
|
-
if key == 'F':
|
|
191
|
-
return album, photo
|
|
192
|
-
|
|
193
|
-
key, func, _ = rule_solver
|
|
194
|
-
detail = choose_detail(key)
|
|
195
|
-
return func(*detail)
|
|
158
|
+
ExceptionTool.raises(f'不支持的rule配置: "{rule}"')
|
|
196
159
|
|
|
197
160
|
@classmethod
|
|
198
161
|
def apply_rule_directly(cls, album, photo, rule: str) -> str:
|
|
199
|
-
|
|
162
|
+
if album is None:
|
|
163
|
+
album = photo.from_album
|
|
164
|
+
# noinspection PyArgumentList
|
|
165
|
+
return fix_windir_name(cls.get_rule_parser(rule)(album, photo, rule)).strip()
|
|
200
166
|
|
|
201
167
|
|
|
202
168
|
class JmOption:
|
|
@@ -471,7 +437,7 @@ class JmOption:
|
|
|
471
437
|
orig_cookies.update(cookies)
|
|
472
438
|
metadata['cookies'] = orig_cookies
|
|
473
439
|
|
|
474
|
-
# noinspection PyMethodMayBeStatic
|
|
440
|
+
# noinspection PyMethodMayBeStatic,PyTypeChecker
|
|
475
441
|
def decide_client_domain(self, client_key: str) -> List[str]:
|
|
476
442
|
def is_client_type(ctype) -> bool:
|
|
477
443
|
return self.client_key_is_given_type(client_key, ctype)
|
jmcomic/jm_plugin.py
CHANGED
|
@@ -307,7 +307,7 @@ class ZipPlugin(JmOptionPlugin):
|
|
|
307
307
|
|
|
308
308
|
elif level == 'photo':
|
|
309
309
|
for photo, image_list in photo_dict.items():
|
|
310
|
-
zip_path = self.get_zip_path(
|
|
310
|
+
zip_path = self.get_zip_path(photo.from_album, photo, filename_rule, suffix, zip_dir)
|
|
311
311
|
self.zip_photo(photo, image_list, zip_path, path_to_delete)
|
|
312
312
|
|
|
313
313
|
else:
|
jmcomic/jm_toolkit.py
CHANGED
|
@@ -24,7 +24,7 @@ class JmcomicText:
|
|
|
24
24
|
|
|
25
25
|
pattern_html_album_album_id = compile(r'<span class="number">.*?:JM(\d+)</span>')
|
|
26
26
|
pattern_html_album_scramble_id = compile(r'var scramble_id = (\d+);')
|
|
27
|
-
pattern_html_album_name = compile(r'<
|
|
27
|
+
pattern_html_album_name = compile(r'<h2 class="book-name" id="book-name"[^>]*?>([\s\S]*?)</h2>')
|
|
28
28
|
pattern_html_album_episode_list = compile(r'data-album="(\d+)"[^>]*>\s*?<li.*?>\s*?第(\d+)[话話]([\s\S]*?)<[\s\S]*?>')
|
|
29
29
|
pattern_html_album_page_count = compile(r'<span class="pagecount">.*?:(\d+)</span>')
|
|
30
30
|
pattern_html_album_pub_date = compile(r'>上架日期 : (.*?)</span>')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
jmcomic/__init__.py,sha256=
|
|
1
|
+
jmcomic/__init__.py,sha256=y1Ks64A8KjMmgD_7AQCGKpyRjU6iIFox28YgBz03_P4,903
|
|
2
2
|
jmcomic/api.py,sha256=ZduhXDmh4lg1dkXHs7UTAaPpYNO7kcdPCDH5JJT9KSI,4253
|
|
3
3
|
jmcomic/cl.py,sha256=PBSh0JndNFZw3B7WJPj5Y8SeFdKzHE00jIwYo9An-K0,3475
|
|
4
4
|
jmcomic/jm_client_impl.py,sha256=m8-e_TA3vIXdUkXJcuJ0uzek4GM48y4QvBRXrT6JqUc,39633
|
|
@@ -7,12 +7,12 @@ jmcomic/jm_config.py,sha256=p7g2FQMVXBnejz1sSzM15YAtJ5f91fZZeNMqFeYum5I,16772
|
|
|
7
7
|
jmcomic/jm_downloader.py,sha256=6w9D7eoL2M85-ScH745-OZBvaC0uwGkHi6awTUzq-3E,11036
|
|
8
8
|
jmcomic/jm_entity.py,sha256=x-3yUvM74C_Gof20mJw2SmZq7sSSsGNg0Cp47oZ-dFg,19968
|
|
9
9
|
jmcomic/jm_exception.py,sha256=x3KGMLlQS2zi1GX7z5G58zJN2EwLkI4mAURkxZYjEvA,5055
|
|
10
|
-
jmcomic/jm_option.py,sha256=
|
|
11
|
-
jmcomic/jm_plugin.py,sha256=
|
|
12
|
-
jmcomic/jm_toolkit.py,sha256=
|
|
13
|
-
jmcomic-2.5.
|
|
14
|
-
jmcomic-2.5.
|
|
15
|
-
jmcomic-2.5.
|
|
16
|
-
jmcomic-2.5.
|
|
17
|
-
jmcomic-2.5.
|
|
18
|
-
jmcomic-2.5.
|
|
10
|
+
jmcomic/jm_option.py,sha256=6hwnm4UPnQPujsA3Gkt17krnJfUF435b-272hVLqlTk,21167
|
|
11
|
+
jmcomic/jm_plugin.py,sha256=1sSPbo2ieXW-asmXapJ0ZaB1Lx5co7SS5dfbYchJ1X4,39914
|
|
12
|
+
jmcomic/jm_toolkit.py,sha256=YdzCq2QwO4NjKZickjJWVLvksmxzOf_qlcGUAua6HFs,29172
|
|
13
|
+
jmcomic-2.5.38.dist-info/licenses/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
|
|
14
|
+
jmcomic-2.5.38.dist-info/METADATA,sha256=FAnf3tUCnAmgzk91jG_o8EsN9qpccupVe7E8OyvkQgM,8161
|
|
15
|
+
jmcomic-2.5.38.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
|
16
|
+
jmcomic-2.5.38.dist-info/entry_points.txt,sha256=tRbQltaGSBjejI0c9jYt-4SXQMd5nSDHcMvHmuTy4ow,44
|
|
17
|
+
jmcomic-2.5.38.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
|
|
18
|
+
jmcomic-2.5.38.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|