jmcomic 2.0.4__py3-none-any.whl → 2.0.6__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,6 +2,6 @@
2
2
  # 被依赖方 <--- 使用方
3
3
  # config <--- entity <--- toolkit <--- client <--- option
4
4
 
5
- __version__ = '2.0.4'
5
+ __version__ = '2.0.6'
6
6
 
7
7
  from .api import *
jmcomic/jm_client_impl.py CHANGED
@@ -95,9 +95,18 @@ class AbstractJmClient(
95
95
 
96
96
  setattr(self, func_name, wrap_func)
97
97
 
98
- wrap_func_cache('get_photo_detail', 'album_cache_dict')
99
- wrap_func_cache('get_album_detail', 'photo_cache_dict')
100
- wrap_func_cache('search_album', 'search_album_cache_dict')
98
+ for func in {
99
+ 'get_photo_detail',
100
+ 'get_album_detail',
101
+ 'search_album',
102
+ }:
103
+ wrap_func_cache(func, func + '.cache.dict')
104
+
105
+ def get_jmcomic_url(self, postman=None):
106
+ return JmModuleConfig.get_jmcomic_url(postman or self.get_root_postman())
107
+
108
+ def get_jmcomic_domain_all(self, postman=None):
109
+ return JmModuleConfig.get_jmcomic_domain_all(postman or self.get_root_postman())
101
110
 
102
111
 
103
112
  # 基于网页实现的JmClient
@@ -113,7 +122,7 @@ class JmHtmlClient(AbstractJmClient):
113
122
  # 用 JmcomicText 解析 html,返回实体类
114
123
  return JmcomicText.analyse_jm_album_html(resp.text)
115
124
 
116
- def get_photo_detail(self, photo_id: str, album=True) -> JmPhotoDetail:
125
+ def get_photo_detail(self, photo_id, fetch_album=True) -> JmPhotoDetail:
117
126
  # 参数校验
118
127
  photo_id = JmcomicText.parse_to_photo_id(photo_id)
119
128
 
@@ -124,7 +133,7 @@ class JmHtmlClient(AbstractJmClient):
124
133
  photo_detail = JmcomicText.analyse_jm_photo_html(resp.text)
125
134
 
126
135
  # 一并获取该章节的所处本子
127
- if album is True:
136
+ if fetch_album is True:
128
137
  photo_detail.from_album = self.get_album_detail(photo_detail.album_id)
129
138
 
130
139
  return photo_detail
@@ -127,7 +127,7 @@ class JmDetailClient:
127
127
  def get_album_detail(self, album_id) -> JmAlbumDetail:
128
128
  raise NotImplementedError
129
129
 
130
- def get_photo_detail(self, photo_id: str, album=True) -> JmPhotoDetail:
130
+ def get_photo_detail(self, photo_id, fetch_album=True) -> JmPhotoDetail:
131
131
  raise NotImplementedError
132
132
 
133
133
  def ensure_photo_can_use(self, photo_detail: JmPhotoDetail):
@@ -210,4 +210,8 @@ class JmcomicClient(
210
210
  JmUserClient,
211
211
  Postman,
212
212
  ):
213
- pass
213
+ def get_jmcomic_url(self, postman=None):
214
+ return JmModuleConfig.get_jmcomic_url(postman or self)
215
+
216
+ def get_jmcomic_domain_all(self, postman=None):
217
+ return JmModuleConfig.get_jmcomic_domain_all(postman or self)
jmcomic/jm_config.py CHANGED
@@ -3,12 +3,24 @@ def default_jm_debug(topic: str, msg: str):
3
3
  print(f'{format_ts()}:【{topic}】{msg}')
4
4
 
5
5
 
6
+ def default_postman_constructor(session, **kwargs):
7
+ from common import Postmans
8
+
9
+ kwargs.setdefault('impersonate', 'chrome110')
10
+ kwargs.setdefault('headers', JmModuleConfig.headers())
11
+
12
+ if session is True:
13
+ return Postmans.new_session(**kwargs)
14
+
15
+ return Postmans.new_postman(**kwargs)
16
+
17
+
6
18
  class JmModuleConfig:
7
19
  # 网站相关
8
20
  PROT = "https://"
9
21
  DOMAIN = None
10
- JM_REDIRECT_URL = f'{PROT}jm365.xyz/3YeBdF' # 永久網域,怕走失的小伙伴收藏起来
11
- JM_PUB_URL = f'{PROT}jmcomic1.bet'
22
+ JM_REDIRECT_URL = f'{PROT}jm365.work/3YeBdF' # 永久網域,怕走失的小伙伴收藏起来
23
+ JM_PUB_URL = f'{PROT}jmcomic2.bet'
12
24
  JM_CDN_IMAGE_URL_TEMPLATE = PROT + 'cdn-msp.{domain}/media/photos/{photo_id}/{index:05}{suffix}' # index 从1开始
13
25
  JM_IMAGE_SUFFIX = ['.jpg', '.webp', '.png', '.gif']
14
26
 
@@ -40,6 +52,7 @@ class JmModuleConfig:
40
52
  # debug
41
53
  enable_jm_debug = True
42
54
  debug_executor = default_jm_debug
55
+ postman_constructor = default_postman_constructor
43
56
 
44
57
  @classmethod
45
58
  def domain(cls, postman=None):
@@ -84,15 +97,17 @@ class JmModuleConfig:
84
97
  def disable_jm_debug(cls):
85
98
  cls.enable_jm_debug = False
86
99
 
100
+ @classmethod
101
+ def new_postman(cls, session=False, **kwargs):
102
+ return cls.postman_constructor(session, **kwargs)
103
+
87
104
  @classmethod
88
105
  def get_jmcomic_url(cls, postman=None):
89
106
  """
90
107
  访问禁漫的永久网域,从而得到一个可用的禁漫网址
91
108
  @return: https://jm-comic2.cc
92
109
  """
93
- if postman is None:
94
- from common import Postmans
95
- postman = Postmans.get_impl_clazz('cffi_Session').create()
110
+ postman = postman or cls.new_postman(session=True)
96
111
 
97
112
  resp = postman.get(cls.JM_REDIRECT_URL)
98
113
  url = resp.url
@@ -105,9 +120,7 @@ class JmModuleConfig:
105
120
  访问禁漫发布页,得到所有禁漫的域名
106
121
  @return:['18comic.vip', ..., 'jm365.xyz/ZNPJam'], 最后一个是【APP軟件下載】
107
122
  """
108
- if postman is None:
109
- from common import Postmans
110
- postman = Postmans.get_impl_clazz('cffi').create()
123
+ postman = postman or cls.new_postman(session=True)
111
124
 
112
125
  resp = postman.get(cls.JM_PUB_URL)
113
126
  if resp.status_code != 200:
jmcomic/jm_entity.py CHANGED
@@ -204,6 +204,9 @@ class JmPhotoDetail(WorkEntity):
204
204
  def __len__(self):
205
205
  return len(self.page_arr)
206
206
 
207
+ def __iter__(self) -> Generator[JmImageDetail, Any, None]:
208
+ return super().__iter__()
209
+
207
210
 
208
211
  class JmAlbumDetail(WorkEntity):
209
212
 
@@ -297,6 +300,9 @@ class JmAlbumDetail(WorkEntity):
297
300
 
298
301
  return ret
299
302
 
303
+ def __iter__(self) -> Generator[JmPhotoDetail, Any, None]:
304
+ return super().__iter__()
305
+
300
306
 
301
307
  class JmSearchPage(IterableEntity):
302
308
 
jmcomic/jm_option.py CHANGED
@@ -1,68 +1,6 @@
1
1
  from .jm_client_impl import *
2
2
 
3
3
 
4
- class JmOptionAdvice:
5
-
6
- def decide_image_save_dir(self,
7
- option: 'JmOption',
8
- photo_detail: JmPhotoDetail,
9
- ) -> StrNone:
10
- """
11
- 决定一个本子图片的下载文件夹
12
- @param option: JmOption对象
13
- @param photo_detail: 本子章节实体类
14
- @return: 下载文件夹,为空表示不处理
15
- """
16
- pass
17
-
18
- def decide_image_filepath(self,
19
- option: 'JmOption',
20
- photo_detail: JmPhotoDetail,
21
- index: int,
22
- ) -> StrNone:
23
- """
24
- 决定一个本子图片的绝对路径
25
- @param option: JmOption对象
26
- @param photo_detail: 本子章节实体类
27
- @param index: 本子章节里的第几章图片
28
- @return: 下载绝对路径,为空表示不处理
29
- """
30
- pass
31
-
32
- def decide_image_suffix(self,
33
- option: 'JmOption',
34
- img_detail: JmImageDetail,
35
- ) -> StrNone:
36
- """
37
- 决定一个图片的保存后缀名
38
- @param option: JmOption对象
39
- @param img_detail: 禁漫图片实体类
40
- @return: 保存后缀名,为空表示不处理
41
- """
42
- pass
43
-
44
-
45
- class JmAdviceRegistry:
46
- advice_registration: Dict[Any, List[JmOptionAdvice]] = {}
47
-
48
- @classmethod
49
- def register_advice(cls, base, *advice):
50
- advice_ls = cls.advice_registration.get(base, None)
51
-
52
- if advice_ls is None:
53
- advice_ls = list(advice)
54
- cls.advice_registration[base] = advice_ls
55
- else:
56
- for e in advice:
57
- advice_ls.append(e)
58
-
59
- return advice
60
-
61
- @classmethod
62
- def get_advice(cls, base) -> List[JmOptionAdvice]:
63
- return cls.advice_registration.setdefault(base, [])
64
-
65
-
66
4
  class DirRule:
67
5
  rule_sample = [
68
6
  # 根目录 / Album-id / Photo-序号 /
@@ -205,12 +143,6 @@ class JmOption:
205
143
  """
206
144
 
207
145
  def decide_image_save_dir(self, photo_detail) -> str:
208
- # 先检查advice的回调,如果回调支持,则优先使用回调
209
- for advice in JmAdviceRegistry.get_advice(self):
210
- save_dir = advice.decide_image_save_dir(self, photo_detail)
211
- if save_dir is not None:
212
- return save_dir
213
-
214
146
  # 使用 self.dir_rule 决定 save_dir
215
147
  save_dir = self.dir_rule.deside_image_save_dir(
216
148
  photo_detail.from_album,
@@ -221,12 +153,6 @@ class JmOption:
221
153
  return save_dir
222
154
 
223
155
  def decide_image_suffix(self, img_detail: JmImageDetail):
224
- # 先检查advice的回调,如果回调支持,则优先使用回调
225
- for advice in JmAdviceRegistry.get_advice(self):
226
- suffix = advice.decide_image_suffix(self, img_detail)
227
- if suffix is not None:
228
- return suffix
229
-
230
156
  # 动图则使用原后缀
231
157
  suffix = img_detail.img_file_suffix
232
158
  if suffix.endswith("gif"):
@@ -236,25 +162,12 @@ class JmOption:
236
162
  return self.download_image_suffix or suffix
237
163
 
238
164
  def decide_image_filepath(self, photo_detail: JmPhotoDetail, index: int) -> str:
239
- # 先检查advice的回调,如果回调支持,则优先使用回调
240
- for advice in JmAdviceRegistry.get_advice(self):
241
- filepath = advice.decide_image_filepath(self, photo_detail, index)
242
- if filepath is not None:
243
- return filepath
244
-
245
165
  # 通过拼接生成绝对路径
246
166
  save_dir = self.decide_image_save_dir(photo_detail)
247
167
  image: JmImageDetail = photo_detail[index]
248
168
  suffix = self.decide_image_suffix(image)
249
169
  return save_dir + image.img_file_name + suffix
250
170
 
251
- """
252
- 下面是对Advice的支持
253
- """
254
-
255
- def register_advice(self, *advice):
256
- JmAdviceRegistry.register_advice(self, *advice)
257
-
258
171
  """
259
172
  下面是创建对象相关方法
260
173
  """
jmcomic/jm_toolkit.py CHANGED
@@ -1,5 +1,3 @@
1
- from PIL import Image
2
-
3
1
  from .jm_entity import *
4
2
 
5
3
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jmcomic
3
- Version: 2.0.4
3
+ Version: 2.0.6
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,13 @@
1
+ jmcomic/__init__.py,sha256=NGI9lVZSXarXZ-NkTiyKuV_UryivzWCMmIBXYec1vBw,159
2
+ jmcomic/api.py,sha256=iXmXyLKWMUBtehLurKoTP-lr_Q7b-lA7Eg7BTYphLNk,4867
3
+ jmcomic/jm_client_impl.py,sha256=JMoohpYMzL34Odtr8eVKyHB8uaxet31YGZho26Z0-pw,10808
4
+ jmcomic/jm_client_interface.py,sha256=AD-v7ZJ7C5uWYBlfdRdT7vMq8dELlVuTa8ekBSK7xPU,5734
5
+ jmcomic/jm_config.py,sha256=epuPrMKFAHdmYiB5osjWBP2rQIyAqtxZvjM8FlAsbX4,4948
6
+ jmcomic/jm_entity.py,sha256=xK0NJaA3C5noTQQXmnoFA-Ln3gqmbMlR7p4aRgBHbuw,9152
7
+ jmcomic/jm_option.py,sha256=PLBThV_3Sjzt-1daCYIcbRVvS-7iVC5qCy_BmLB8mxc,9298
8
+ jmcomic/jm_toolkit.py,sha256=hUBdP3BERsRMuCBg1fKjYO4PVE5VBMOv3OJ1x07qr2U,11284
9
+ jmcomic-2.0.6.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
10
+ jmcomic-2.0.6.dist-info/METADATA,sha256=Z5Y8dqt71_btU09Lqi2MaS_LlKqzYdCs9BbLzK0bPTI,3633
11
+ jmcomic-2.0.6.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
12
+ jmcomic-2.0.6.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
13
+ jmcomic-2.0.6.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- jmcomic/__init__.py,sha256=FLmaQwoIKQ4Exh-7qCy5mD87CqW_VW8tXGIlN7q10NQ,159
2
- jmcomic/api.py,sha256=iXmXyLKWMUBtehLurKoTP-lr_Q7b-lA7Eg7BTYphLNk,4867
3
- jmcomic/jm_client_impl.py,sha256=ycfh3VXCs17BoeDS-4lfsfGpmTOc36H5FVIqkpEuYqE,10545
4
- jmcomic/jm_client_interface.py,sha256=88R8cXvZ7l2OJPvFEelybc2MIza45dEGPgd0g8-dljE,5511
5
- jmcomic/jm_config.py,sha256=IP8fsogzMBGVT7aepZ19kZG2gtNRuxItV2I0Q9euvkY,4608
6
- jmcomic/jm_entity.py,sha256=71PwA11P89o9vvZ3CG1vsR0uYXVIH4lZKz1w5tudydM,8956
7
- jmcomic/jm_option.py,sha256=zNQZ_fjoG38J1TFGlOravlc1bQZ4MlcZqH_3A50qXOI,12222
8
- jmcomic/jm_toolkit.py,sha256=SQAlnt5vawqENJq8IL9cUrU2wxfy-me1UnKUePxDL4Y,11307
9
- jmcomic-2.0.4.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
10
- jmcomic-2.0.4.dist-info/METADATA,sha256=rwInKusUzh0lcDvGs4oryDCeM5rZUlQDO8BLyEYRcac,3633
11
- jmcomic-2.0.4.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
12
- jmcomic-2.0.4.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
13
- jmcomic-2.0.4.dist-info/RECORD,,