jmcomic 2.3.15__py3-none-any.whl → 2.3.16__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 CHANGED
@@ -2,7 +2,7 @@
2
2
  # 被依赖方 <--- 使用方
3
3
  # config <--- entity <--- toolkit <--- client <--- option <--- downloader
4
4
 
5
- __version__ = '2.3.15'
5
+ __version__ = '2.3.16'
6
6
 
7
7
  from .api import *
8
8
  from .jm_plugin import *
jmcomic/jm_client_impl.py CHANGED
@@ -493,13 +493,13 @@ class JmApiClient(AbstractJmClient):
493
493
  }
494
494
  )
495
495
 
496
- match = JmcomicText.pattern_html_album_scramble_id.search(resp.text)
497
-
498
- if match is not None:
499
- scramble_id = match[1]
500
- else:
501
- jm_debug('api.scramble', '未从响应中匹配到scramble_id,返回默认值220980')
502
- scramble_id = '220980'
496
+ scramble_id = PatternTool.match_or_default(resp.text,
497
+ JmcomicText.pattern_html_album_scramble_id,
498
+ None,
499
+ )
500
+ if scramble_id is None:
501
+ jm_debug('api.scramble', f'未匹配到scramble_id,响应文本:{resp.text}')
502
+ scramble_id = str(JmModuleConfig.SCRAMBLE_220980)
503
503
 
504
504
  return scramble_id
505
505
 
@@ -610,15 +610,12 @@ class JmApiClient(AbstractJmClient):
610
610
  # 2. 是否是特殊的内容
611
611
  # 暂无
612
612
 
613
- @classmethod
614
- @field_cache('__init_cookies__')
615
- def fetch_init_cookies(cls, client: 'JmApiClient'):
616
- resp = client.setting()
617
- return dict(resp.resp.cookies)
618
-
619
613
  def after_init(self):
620
- cookies = self.__class__.fetch_init_cookies(self)
621
- self.get_root_postman().get_meta_data()['cookies'] = cookies
614
+ # cookies = self.__class__.fetch_init_cookies(self)
615
+ # self.get_root_postman().get_meta_data()['cookies'] = cookies
616
+
617
+ self.get_root_postman().get_meta_data()['cookies'] = JmModuleConfig.get_cookies(self)
618
+ pass
622
619
 
623
620
 
624
621
  class FutureClientProxy(JmcomicClient):
jmcomic/jm_config.py CHANGED
@@ -3,7 +3,7 @@ def field_cache(*args, **kwargs):
3
3
  return field_cache(*args, **kwargs)
4
4
 
5
5
 
6
- def default_jm_debug(topic: str, msg: str):
6
+ def default_jm_debug_logging(topic: str, msg: str):
7
7
  from common import format_ts
8
8
  print(f'{format_ts()}:【{topic}】{msg}')
9
9
 
@@ -62,13 +62,14 @@ class JmModuleConfig:
62
62
  SCRAMBLE_421926 = 421926 # 2023-02-08后改了图片切割算法
63
63
  SCRAMBLE_CACHE = {}
64
64
 
65
- # 移动端API的相关配置
66
- # API密钥
67
- APP_SECRET = '18comicAPP'
65
+ # 移动端API密钥
66
+ APP_SECRET = '18comicAPPContent'
68
67
 
69
- # 域名配置 - 移动端
70
- # 图片域名
71
- DOMAIN_API_IMAGE_LIST = str_to_list('''
68
+ # cookies,目前只在移动端使用,因为移动端请求接口须携带,但不会校验cookies的内容。
69
+ APP_COOKIES = None
70
+
71
+ # 移动端图片域名
72
+ DOMAIN_IMAGE_LIST = str_to_list('''
72
73
  cdn-msp.jmapiproxy1.monster
73
74
  cdn-msp2.jmapiproxy1.monster
74
75
  cdn-msp.jmapiproxy1.cc
@@ -78,7 +79,7 @@ class JmModuleConfig:
78
79
 
79
80
  ''')
80
81
 
81
- # API域名
82
+ # 移动端API域名
82
83
  DOMAIN_API_LIST = str_to_list('''
83
84
  www.jmapinode1.top
84
85
  www.jmapinode2.top
@@ -88,8 +89,11 @@ class JmModuleConfig:
88
89
 
89
90
  ''')
90
91
 
91
- # 域名配置 - 网页端
92
+ # 网页端域名配置
92
93
  # 无需配置,默认为None,需要的时候会发起请求获得
94
+ # 使用优先级:
95
+ # 1. DOMAIN_HTML_LIST
96
+ # 2. [DOMAIN_HTML]
93
97
  DOMAIN_HTML = None
94
98
  DOMAIN_HTML_LIST = None
95
99
 
@@ -106,7 +110,7 @@ class JmModuleConfig:
106
110
  REGISTRY_PLUGIN = {}
107
111
 
108
112
  # 执行debug的函数
109
- debug_executor = default_jm_debug
113
+ debug_executor = default_jm_debug_logging
110
114
  # postman构造函数
111
115
  postman_constructor = default_postman_constructor
112
116
  # 网页正则表达式解析失败时,执行抛出异常的函数,可以替换掉用于debug
@@ -190,7 +194,7 @@ class JmModuleConfig:
190
194
  postman = postman or cls.new_postman(session=True)
191
195
 
192
196
  url = postman.with_redirect_catching().get(cls.JM_REDIRECT_URL)
193
- cls.jm_debug('获取禁漫网页URL', f'[{cls.JM_REDIRECT_URL}] → [{url}]')
197
+ cls.jm_debug('module.html_url', f'获取禁漫网页URL: [{cls.JM_REDIRECT_URL}] → [{url}]')
194
198
  return url
195
199
 
196
200
  @classmethod
@@ -211,9 +215,22 @@ class JmModuleConfig:
211
215
  from .jm_toolkit import JmcomicText
212
216
  domain_list = JmcomicText.analyse_jm_pub_html(resp.text)
213
217
 
214
- cls.jm_debug('获取禁漫网页全部域名', f'[{resp.url}] → {domain_list}')
218
+ cls.jm_debug('module.html_domain_all', f'获取禁漫网页全部域名: [{resp.url}] → {domain_list}')
215
219
  return domain_list
216
220
 
221
+ @classmethod
222
+ @field_cache("APP_COOKIES")
223
+ def get_cookies(cls, postman=None):
224
+ from .jm_toolkit import JmcomicText
225
+ url = JmcomicText.format_url('/setting', cls.DOMAIN_API_LIST[0])
226
+ postman = postman or cls.new_postman()
227
+
228
+ resp = postman.get(url)
229
+ cookies = dict(resp.cookies)
230
+
231
+ cls.jm_debug('module.cookies', f'获取cookies: [{url}] → {cookies}')
232
+ return cookies
233
+
217
234
  @classmethod
218
235
  def new_html_headers(cls, domain='18comic.vip'):
219
236
  """
@@ -247,7 +264,7 @@ class JmModuleConfig:
247
264
  key_ts = time_stamp()
248
265
 
249
266
  import hashlib
250
- token = hashlib.md5(f"{key_ts}{cls.APP_SECRET}".encode()).hexdigest()
267
+ token = hashlib.md5(f"{key_ts}{cls.APP_SECRET}".encode("utf-8")).hexdigest()
251
268
 
252
269
  return {
253
270
  'token': token,
jmcomic/jm_option.py CHANGED
@@ -314,6 +314,7 @@ class JmOption:
314
314
  def new_jm_client(self, domain=None, impl=None, cache=None, **kwargs) -> JmcomicClient:
315
315
  # 所有需要用到的 self.client 配置项如下
316
316
  postman_conf: dict = self.client.postman.src_dict # postman dsl 配置
317
+ meta_data: dict = postman_conf['meta_data'] # 请求元信息
317
318
  impl: str = impl or self.client.impl # client_key
318
319
  retry_times: int = self.client.retry_times # 重试次数
319
320
  cache: str = cache or self.client.cache # 启用缓存
@@ -335,15 +336,11 @@ class JmOption:
335
336
 
336
337
  # support kwargs overwrite meta_data
337
338
  if len(kwargs) != 0:
338
- postman_conf['meta_data'].update(kwargs)
339
+ meta_data.update(kwargs)
339
340
 
340
341
  # headers
341
- meta_data = postman_conf['meta_data']
342
342
  if meta_data['headers'] is None:
343
- headers = self.decide_postman_headers(impl, domain[0])
344
- # if headers is None:
345
- # postman_conf['type'] = 'requests'
346
- meta_data['headers'] = headers
343
+ meta_data['headers'] = self.decide_postman_headers(impl, domain[0])
347
344
 
348
345
  # postman
349
346
  postman = Postmans.create(data=postman_conf)
@@ -375,6 +372,9 @@ class JmOption:
375
372
 
376
373
  if is_client_type(JmHtmlClient):
377
374
  # 网页端
375
+ domain_list = JmModuleConfig.DOMAIN_HTML_LIST
376
+ if domain_list is not None:
377
+ return domain_list
378
378
  return [JmModuleConfig.get_html_domain()]
379
379
 
380
380
  ExceptionTool.raises(f'没有配置域名,且是无法识别的client类型: {client_key}')
jmcomic/jm_plugin.py CHANGED
@@ -249,26 +249,32 @@ class ZipPlugin(JmOptionPlugin):
249
249
  mkdir_if_not_exists(zip_dir)
250
250
 
251
251
  # 原文件夹 -> zip文件
252
- dir_zip_dict = {}
252
+ dir_zip_dict: Dict[str, Optional[str]] = {}
253
253
  photo_dict = downloader.all_downloaded[album]
254
254
 
255
255
  if level == 'album':
256
256
  zip_path = self.get_zip_path(album, None, filename_rule, suffix, zip_dir)
257
257
  dir_path = self.zip_album(album, photo_dict, zip_path)
258
- dir_zip_dict[dir_path] = zip_path
258
+ if dir_path is not None:
259
+ # 要删除这个album文件夹
260
+ dir_zip_dict[dir_path] = zip_path
261
+ # 也要删除album下的photo文件夹
262
+ for d in files_of_dir(dir_path):
263
+ dir_zip_dict[d] = None
259
264
 
260
265
  elif level == 'photo':
261
266
  for photo, image_list in photo_dict.items():
262
267
  zip_path = self.get_zip_path(None, photo, filename_rule, suffix, zip_dir)
263
268
  dir_path = self.zip_photo(photo, image_list, zip_path)
264
- dir_zip_dict[dir_path] = zip_path
269
+ if dir_path is not None:
270
+ dir_zip_dict[dir_path] = zip_path
265
271
 
266
272
  else:
267
273
  ExceptionTool.raises(f'Not Implemented Zip Level: {level}')
268
274
 
269
275
  self.after_zip(dir_zip_dict)
270
276
 
271
- def zip_photo(self, photo, image_list: list, zip_path: str):
277
+ def zip_photo(self, photo, image_list: list, zip_path: str) -> Optional[str]:
272
278
  """
273
279
  压缩photo文件夹
274
280
  :returns: photo文件夹路径
@@ -277,46 +283,54 @@ class ZipPlugin(JmOptionPlugin):
277
283
  if len(image_list) == 0 \
278
284
  else os.path.dirname(image_list[0][0])
279
285
 
280
- all_filepath = set(map(lambda t: t[0], image_list))
286
+ all_filepath = set(map(lambda t: self.unified_path(t[0]), image_list))
281
287
 
282
- if len(all_filepath) == 0:
283
- self.debug('无下载文件,无需压缩', 'skip')
284
- return
285
-
286
- from common import backup_dir_to_zip
287
- backup_dir_to_zip(photo_dir, zip_path, acceptor=lambda f: f in all_filepath)
288
- self.debug(f'压缩章节[{photo.photo_id}]成功 → {zip_path}', 'finish')
288
+ return self.do_zip(photo_dir,
289
+ zip_path,
290
+ all_filepath,
291
+ f'压缩章节[{photo.photo_id}]成功 → {zip_path}',
292
+ )
289
293
 
290
- return photo_dir
294
+ @staticmethod
295
+ def unified_path(f):
296
+ return fix_filepath(f, os.path.isdir(f))
291
297
 
292
- def zip_album(self, album, photo_dict: dict, zip_path):
298
+ def zip_album(self, album, photo_dict: dict, zip_path) -> Optional[str]:
293
299
  """
294
300
  压缩album文件夹
295
301
  :returns: album文件夹路径
296
302
  """
297
- album_dir = self.option.decide_album_dir(album)
298
303
  all_filepath: Set[str] = set()
299
304
 
300
- for image_list in photo_dict.values():
301
- image_list: List[Tuple[str, JmImageDetail]]
302
- for path, _ in image_list:
303
- all_filepath.add(path)
305
+ def addpath(f):
306
+ all_filepath.update(set(f))
307
+
308
+ album_dir = self.option.decide_album_dir(album)
309
+ # addpath(self.option.decide_image_save_dir(photo) for photo in photo_dict.keys())
310
+ addpath(path for ls in photo_dict.values() for path, _ in ls)
311
+
312
+ return self.do_zip(album_dir,
313
+ zip_path,
314
+ all_filepath,
315
+ msg=f'压缩本子[{album.album_id}]成功 → {zip_path}',
316
+ )
304
317
 
318
+ def do_zip(self, source_dir, zip_path, all_filepath, msg):
305
319
  if len(all_filepath) == 0:
306
320
  self.debug('无下载文件,无需压缩', 'skip')
307
- return
321
+ return None
308
322
 
309
323
  from common import backup_dir_to_zip
310
324
  backup_dir_to_zip(
311
- album_dir,
325
+ source_dir,
312
326
  zip_path,
313
- acceptor=lambda f: f in all_filepath
314
- )
327
+ acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
328
+ ).close()
315
329
 
316
- self.debug(f'压缩本子[{album.album_id}]成功 → {zip_path}', 'finish')
317
- return album_dir
330
+ self.debug(msg, 'finish')
331
+ return self.unified_path(source_dir)
318
332
 
319
- def after_zip(self, dir_zip_dict: Dict[str, str]):
333
+ def after_zip(self, dir_zip_dict: Dict[str, Optional[str]]):
320
334
  # 是否要删除所有原文件
321
335
  if self.delete_original_file is True:
322
336
  self.delete_all_files_and_empty_dir(
@@ -352,10 +366,10 @@ class ZipPlugin(JmOptionPlugin):
352
366
  os.remove(f)
353
367
  self.debug(f'删除原文件: {f}', 'remove')
354
368
 
355
- for d in dir_list:
369
+ for d in sorted(dir_list, reverse=True):
356
370
  # check exist
357
- if file_exists(d) and len(os.listdir(d)) == 0:
358
- os.removedirs(d)
371
+ if file_exists(d):
372
+ os.rmdir(d)
359
373
  self.debug(f'删除文件夹: {d}', 'remove')
360
374
 
361
375
 
jmcomic/jm_toolkit.py CHANGED
@@ -489,7 +489,7 @@ class JmApiAdaptTool:
489
489
 
490
490
  fields['sort'] = sort
491
491
  import random
492
- fields['data_original_domain'] = random.choice(JmModuleConfig.DOMAIN_API_IMAGE_LIST)
492
+ fields['data_original_domain'] = random.choice(JmModuleConfig.DOMAIN_IMAGE_LIST)
493
493
 
494
494
 
495
495
  class JmImageTool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jmcomic
3
- Version: 2.3.15
3
+ Version: 2.3.16
4
4
  Summary: Python API For JMComic (禁漫天堂)
5
5
  Home-page: https://github.com/hect0x7/JMComic-Crawler-Python
6
6
  Author: hect0x7
@@ -0,0 +1,17 @@
1
+ jmcomic/__init__.py,sha256=qqA6jypcSuTQ_DN37vmWjpu-jC8pkxB_s-AiFhj2Y6E,879
2
+ jmcomic/api.py,sha256=wzHtdI3AoB1NOKbx7hlcRD_KSUu_CexHKXS0pOLTAsI,2497
3
+ jmcomic/cl.py,sha256=ArDxQvt4G2YungPUqYHG5zWkUxQh71nY-T_IS2jzIV8,3489
4
+ jmcomic/jm_client_impl.py,sha256=fDx5VZnlmYpdie5grHfwf8E-zh-QYrbdHzUJK5nqdw4,25161
5
+ jmcomic/jm_client_interface.py,sha256=r-y81BqiQSj74dwjnpa22uHbaYPVAENG6QOegx9g-F0,13087
6
+ jmcomic/jm_config.py,sha256=x8Xi4aTNn8YX32d_f7Wy775Kp9YTlqYJS64Rl3wpOVY,14092
7
+ jmcomic/jm_downloader.py,sha256=QcvBzTWAwGuZ9b10R5qYnXE_rjEIJvobsvNF5G5ZqXU,7207
8
+ jmcomic/jm_entity.py,sha256=6N5EBAWIl-rbVAak8HuGeyNB6KPM_kQ6ekPKfZht4c0,15082
9
+ jmcomic/jm_option.py,sha256=YxLO4uqnTVqj5A9Ouv_lbQ7rSBA2zgbWuSW0yKuMxdA,18685
10
+ jmcomic/jm_plugin.py,sha256=nLCyrWTjaSXCRcVHZBwJtgzYeeNEc92vOqw0_8AwJpA,14906
11
+ jmcomic/jm_toolkit.py,sha256=YrOlDp_fYQ5Ggu40Py-jArM2D1GfpQ7VJycfnR6aaLs,21846
12
+ jmcomic-2.3.16.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
13
+ jmcomic-2.3.16.dist-info/METADATA,sha256=s1R-negNRV1gArP_eLwwp45AsD-LTzbY36ddCEo3iXY,4944
14
+ jmcomic-2.3.16.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
15
+ jmcomic-2.3.16.dist-info/entry_points.txt,sha256=tRbQltaGSBjejI0c9jYt-4SXQMd5nSDHcMvHmuTy4ow,44
16
+ jmcomic-2.3.16.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
17
+ jmcomic-2.3.16.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- jmcomic/__init__.py,sha256=us33H3aqW0Hlu7igzVxvRBtQ2S_8fwX92WfPTPnVUQ4,879
2
- jmcomic/api.py,sha256=wzHtdI3AoB1NOKbx7hlcRD_KSUu_CexHKXS0pOLTAsI,2497
3
- jmcomic/cl.py,sha256=ArDxQvt4G2YungPUqYHG5zWkUxQh71nY-T_IS2jzIV8,3489
4
- jmcomic/jm_client_impl.py,sha256=ojNeh4BKRfrxxkWS1_VQr8ZpaknWRADGXPGWyQM2O1s,25068
5
- jmcomic/jm_client_interface.py,sha256=r-y81BqiQSj74dwjnpa22uHbaYPVAENG6QOegx9g-F0,13087
6
- jmcomic/jm_config.py,sha256=qL12dheI3iraHpw-SejweqTk7q5zpp-y0btOKXvA9I8,13422
7
- jmcomic/jm_downloader.py,sha256=QcvBzTWAwGuZ9b10R5qYnXE_rjEIJvobsvNF5G5ZqXU,7207
8
- jmcomic/jm_entity.py,sha256=6N5EBAWIl-rbVAak8HuGeyNB6KPM_kQ6ekPKfZht4c0,15082
9
- jmcomic/jm_option.py,sha256=uNq6cjUkPXiAViEbdBW9XmvrFkNuE8X3bhpUJ-dVx70,18659
10
- jmcomic/jm_plugin.py,sha256=VEfGu3xyj415dHR4VUVf-43O24S42Ki33dtdSzWGuvY,14223
11
- jmcomic/jm_toolkit.py,sha256=K4ip55Di7ZZDv_Bnj-NvaOSKoRHaCmrMrXliD2vSJhw,21850
12
- jmcomic-2.3.15.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
13
- jmcomic-2.3.15.dist-info/METADATA,sha256=R3FlUuJYhRF87TxmDMwkqAWgV5N_K363zBX9N_KQEE8,4944
14
- jmcomic-2.3.15.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
15
- jmcomic-2.3.15.dist-info/entry_points.txt,sha256=tRbQltaGSBjejI0c9jYt-4SXQMd5nSDHcMvHmuTy4ow,44
16
- jmcomic-2.3.15.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
17
- jmcomic-2.3.15.dist-info/RECORD,,