jmcomic 2.1.21__py3-none-any.whl → 2.2.0__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 +2 -1
- jmcomic/jm_client_impl.py +1 -3
- jmcomic/jm_config.py +9 -1
- jmcomic/jm_downloader.py +2 -0
- jmcomic/jm_option.py +50 -0
- jmcomic/jm_plugin.py +53 -0
- {jmcomic-2.1.21.dist-info → jmcomic-2.2.0.dist-info}/METADATA +17 -7
- jmcomic-2.2.0.dist-info/RECORD +15 -0
- jmcomic-2.1.21.dist-info/RECORD +0 -14
- {jmcomic-2.1.21.dist-info → jmcomic-2.2.0.dist-info}/LICENSE +0 -0
- {jmcomic-2.1.21.dist-info → jmcomic-2.2.0.dist-info}/WHEEL +0 -0
- {jmcomic-2.1.21.dist-info → jmcomic-2.2.0.dist-info}/top_level.txt +0 -0
jmcomic/__init__.py
CHANGED
jmcomic/jm_client_impl.py
CHANGED
|
@@ -87,7 +87,7 @@ class AbstractJmClient(
|
|
|
87
87
|
|
|
88
88
|
# noinspection PyMethodMayBeStatic, PyUnusedLocal
|
|
89
89
|
def before_retry(self, e, kwargs, retry_count, url):
|
|
90
|
-
jm_debug('req.
|
|
90
|
+
jm_debug('req.error', str(e))
|
|
91
91
|
|
|
92
92
|
def enable_cache(self, debug=False):
|
|
93
93
|
def wrap_func_cache(func_name, cache_dict_name):
|
|
@@ -235,7 +235,6 @@ class JmHtmlClient(AbstractJmClient):
|
|
|
235
235
|
resp = self.get(url, **kwargs)
|
|
236
236
|
|
|
237
237
|
if require_200 is True and resp.status_code != 200:
|
|
238
|
-
# write_text('./resp.html', resp.text)
|
|
239
238
|
self.check_special_http_code(resp)
|
|
240
239
|
self.raise_request_error(resp)
|
|
241
240
|
|
|
@@ -342,7 +341,6 @@ class JmHtmlClient(AbstractJmClient):
|
|
|
342
341
|
if content not in html:
|
|
343
342
|
continue
|
|
344
343
|
|
|
345
|
-
write_text('./resp.html', html)
|
|
346
344
|
cls.raise_request_error(
|
|
347
345
|
resp,
|
|
348
346
|
f'{reason}'
|
jmcomic/jm_config.py
CHANGED
|
@@ -78,6 +78,9 @@ class JmModuleConfig:
|
|
|
78
78
|
# debug开关标记
|
|
79
79
|
enable_jm_debug = True
|
|
80
80
|
|
|
81
|
+
# 插件注册表
|
|
82
|
+
plugin_registry = {}
|
|
83
|
+
|
|
81
84
|
@classmethod
|
|
82
85
|
def downloader_class(cls):
|
|
83
86
|
if cls.CLASS_DOWNLOADER is not None:
|
|
@@ -256,7 +259,8 @@ class JmModuleConfig:
|
|
|
256
259
|
},
|
|
257
260
|
'impl': 'html',
|
|
258
261
|
'retry_times': 5
|
|
259
|
-
}
|
|
262
|
+
},
|
|
263
|
+
'plugin': {},
|
|
260
264
|
}
|
|
261
265
|
|
|
262
266
|
@classmethod
|
|
@@ -289,6 +293,10 @@ class JmModuleConfig:
|
|
|
289
293
|
|
|
290
294
|
return option_dict
|
|
291
295
|
|
|
296
|
+
@classmethod
|
|
297
|
+
def register_plugin(cls, plugin_class):
|
|
298
|
+
cls.plugin_registry[plugin_class.plugin_key] = plugin_class
|
|
299
|
+
|
|
292
300
|
|
|
293
301
|
jm_debug = JmModuleConfig.jm_debug
|
|
294
302
|
disable_jm_debug = JmModuleConfig.disable_jm_debug
|
jmcomic/jm_downloader.py
CHANGED
|
@@ -21,7 +21,9 @@ class DownloadCallback:
|
|
|
21
21
|
f'本子获取成功: [{album.id}], '
|
|
22
22
|
f'作者: [{album.author}], '
|
|
23
23
|
f'章节数: [{len(album)}], '
|
|
24
|
+
f'总页数: [{album.page_count}], '
|
|
24
25
|
f'标题: [{album.title}], '
|
|
26
|
+
f'关键词: [{album.keywords}], '
|
|
25
27
|
)
|
|
26
28
|
|
|
27
29
|
def after_album(self, album: JmAlbumDetail):
|
jmcomic/jm_option.py
CHANGED
|
@@ -109,6 +109,7 @@ class JmOption:
|
|
|
109
109
|
dir_rule: Dict,
|
|
110
110
|
download: Dict,
|
|
111
111
|
client: Dict,
|
|
112
|
+
plugin: Dict,
|
|
112
113
|
filepath=None,
|
|
113
114
|
):
|
|
114
115
|
# 版本号
|
|
@@ -119,9 +120,13 @@ class JmOption:
|
|
|
119
120
|
self.client = DictModel(client)
|
|
120
121
|
# 下载配置
|
|
121
122
|
self.download = DictModel(download)
|
|
123
|
+
# 插件配置
|
|
124
|
+
self.plugin = DictModel(plugin)
|
|
122
125
|
# 其他配置
|
|
123
126
|
self.filepath = filepath
|
|
124
127
|
|
|
128
|
+
self.call_all_plugin('after_init')
|
|
129
|
+
|
|
125
130
|
@property
|
|
126
131
|
def download_cache(self):
|
|
127
132
|
return self.download.cache
|
|
@@ -286,3 +291,48 @@ class JmOption:
|
|
|
286
291
|
else:
|
|
287
292
|
default_dict[key] = value
|
|
288
293
|
return default_dict
|
|
294
|
+
|
|
295
|
+
# 下面的方法提供面向对象的调用风格
|
|
296
|
+
|
|
297
|
+
def download_album(self, album_id):
|
|
298
|
+
from .api import download_album
|
|
299
|
+
download_album(album_id, self)
|
|
300
|
+
|
|
301
|
+
def download_album(self, photo_id):
|
|
302
|
+
from .api import download_album
|
|
303
|
+
download_album(photo_id, self)
|
|
304
|
+
|
|
305
|
+
# 下面的方法为调用插件提供支持
|
|
306
|
+
def call_all_plugin(self, key: str):
|
|
307
|
+
plugin_dict: dict = self.plugin.get(key, {})
|
|
308
|
+
if plugin_dict is None or len(plugin_dict) == 0:
|
|
309
|
+
return
|
|
310
|
+
|
|
311
|
+
# 保证 jm_plugin.py 被加载
|
|
312
|
+
from .jm_plugin import JmOptionPlugin
|
|
313
|
+
|
|
314
|
+
plugin_registry = JmModuleConfig.plugin_registry
|
|
315
|
+
for name, kwargs in plugin_dict.items():
|
|
316
|
+
plugin_class: Optional[Type[JmOptionPlugin]] = plugin_registry.get(name, None)
|
|
317
|
+
|
|
318
|
+
if plugin_class is None:
|
|
319
|
+
raise JmModuleConfig.exception(f'[{key}] 未注册的plugin: {name}')
|
|
320
|
+
|
|
321
|
+
self.invoke_plugin(plugin_class, kwargs)
|
|
322
|
+
|
|
323
|
+
def invoke_plugin(self, plugin_class, kwargs: dict):
|
|
324
|
+
# 保证 jm_plugin.py 被加载
|
|
325
|
+
from .jm_plugin import JmOptionPlugin
|
|
326
|
+
|
|
327
|
+
plugin_class: Type[JmOptionPlugin]
|
|
328
|
+
try:
|
|
329
|
+
plugin = plugin_class.build(self)
|
|
330
|
+
plugin.invoke(**kwargs)
|
|
331
|
+
except JmcomicException as e:
|
|
332
|
+
msg = str(e)
|
|
333
|
+
jm_debug('plugin.exception', msg)
|
|
334
|
+
raise JmModuleConfig.exception(msg)
|
|
335
|
+
except BaseException as e:
|
|
336
|
+
msg = str(e)
|
|
337
|
+
jm_debug('plugin.error', msg)
|
|
338
|
+
raise e
|
jmcomic/jm_plugin.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
该文件存放的是option插件类
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .jm_option import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JmOptionPlugin:
|
|
9
|
+
plugin_key: str
|
|
10
|
+
|
|
11
|
+
def __init__(self, option: JmOption):
|
|
12
|
+
self.option = option
|
|
13
|
+
|
|
14
|
+
def invoke(self, **kwargs) -> None:
|
|
15
|
+
"""
|
|
16
|
+
执行插件的功能
|
|
17
|
+
@param kwargs: 给插件的参数
|
|
18
|
+
"""
|
|
19
|
+
raise NotImplementedError
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def build(cls, option: JmOption) -> 'JmOptionPlugin':
|
|
23
|
+
"""
|
|
24
|
+
创建插件实例
|
|
25
|
+
@param option: JmOption对象
|
|
26
|
+
"""
|
|
27
|
+
return cls(option)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
插件功能:登录禁漫,并保存登录后的cookies,让所有client都带上此cookies
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class LoginPlugin(JmOptionPlugin):
|
|
36
|
+
plugin_key = 'login'
|
|
37
|
+
|
|
38
|
+
def invoke(self, username, password) -> None:
|
|
39
|
+
assert isinstance(username, str), '用户名必须是str'
|
|
40
|
+
assert isinstance(password, str), '密码必须是str'
|
|
41
|
+
|
|
42
|
+
client = self.option.new_jm_client()
|
|
43
|
+
client.login(username, password)
|
|
44
|
+
cookies = client['cookies']
|
|
45
|
+
|
|
46
|
+
postman: dict = self.option.client.postman.src_dict
|
|
47
|
+
meta_data = postman.get('meta_data', {})
|
|
48
|
+
meta_data['cookies'] = cookies
|
|
49
|
+
postman['meta_data'] = meta_data
|
|
50
|
+
jm_debug('plugin.login', '登录成功')
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
JmModuleConfig.register_plugin(LoginPlugin)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jmcomic
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python API For JMComic (禁漫天堂)
|
|
5
5
|
Home-page: https://github.com/hect0x7/JMComic-Crawler-Python
|
|
6
6
|
Author: hect0x7
|
|
@@ -34,7 +34,7 @@ Requires-Dist: Pillow
|
|
|
34
34
|
|
|
35
35
|
## 安装教程
|
|
36
36
|
|
|
37
|
-
* 通过pip
|
|
37
|
+
* 通过pip官方源安装(推荐,并且更新也是这个命令)
|
|
38
38
|
|
|
39
39
|
```shell
|
|
40
40
|
pip install jmcomic -i https://pypi.org/project --upgrade
|
|
@@ -56,10 +56,19 @@ jmcomic.download_album('422866') # 传入要下载的album的id,即可下载
|
|
|
56
56
|
# 配置项的作用是告诉程序下载时候的一些选择,
|
|
57
57
|
# 比如,要下载到哪个文件夹,使用怎样的路径组织规则(比如[/作者/本子id/图片] 或者 [/作者/本子名称/图片]).
|
|
58
58
|
# 如果没有配置,则会使用 JmOption.default(),下载的路径是[当前工作文件夹/本子名称/图片].
|
|
59
|
-
#
|
|
59
|
+
# 如果你想要配置,请参考文件 assets/config/常用配置介绍.yml
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
进阶使用可以参考本repo下usage文件夹内的示例代码文件:
|
|
63
|
+
|
|
64
|
+
- API上手介绍: `getting_started.py`
|
|
65
|
+
- 使用API实现简单功能: `usage_simple.py`
|
|
66
|
+
- 使用API的Filter过滤功能: `usage_feature_filter.py`
|
|
67
|
+
- 测试你的ip可以访问哪些禁漫域名: `pick_domain.py`
|
|
68
|
+
- 基于GitHub Actions下载本子: `workflow_download.py`
|
|
69
|
+
- 演示jmcomic模块的自定义功能点: `usage_custom.py`
|
|
70
|
+
- 演示jmcomic模块的Plugin插件体系: `usage_plugin.py`
|
|
71
|
+
|
|
63
72
|
|
|
64
73
|
## 项目特点
|
|
65
74
|
|
|
@@ -68,13 +77,14 @@ jmcomic.download_album('422866') # 传入要下载的album的id,即可下载
|
|
|
68
77
|
- **可配置性强**
|
|
69
78
|
- 不配置也能使用,十分方便
|
|
70
79
|
- 配置可以从**配置文件**生成,支持多种文件格式,无需写Python代码
|
|
71
|
-
- 配置点有:`是否使用磁盘缓存` `图片类型转换` `下载路径` `请求元信息(headers,cookies
|
|
80
|
+
- 配置点有:`是否使用磁盘缓存` `并发下载图片数` `图片类型转换` `下载路径` `请求元信息(headers,cookies,proxies)`等
|
|
72
81
|
- **可扩展性强**
|
|
82
|
+
- **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件**
|
|
73
83
|
- 支持自定义本子/章节/图片下载前后的回调函数
|
|
74
84
|
- 支持自定义debug日志的开关/格式
|
|
75
|
-
- 支持自定义Option/Client/实体类
|
|
85
|
+
- 支持自定义Downloader/Option/Client/实体类
|
|
76
86
|
- ...
|
|
77
|
-
-
|
|
87
|
+
- 支持自动重试和域名切换机制
|
|
78
88
|
- **多线程下载**(可细化到一图一线程,效率极高)
|
|
79
89
|
- 跟进了JM最新的图片分割算法(2023-02-08)
|
|
80
90
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
jmcomic/__init__.py,sha256=wO2S88eNgkgAQzuspVBF1qmc3mqkdzXnIzhtJfdA8SI,200
|
|
2
|
+
jmcomic/api.py,sha256=s1LTgpKQh5hMnl3Im6qD5nvrnusf6NHawzvJKbZxwCo,1864
|
|
3
|
+
jmcomic/jm_client_impl.py,sha256=YN8tX-Z2hGcZVkV4UOuRN039H71vKyl1lYf6pV3OdQg,14136
|
|
4
|
+
jmcomic/jm_client_interface.py,sha256=5BCWxrWkoRRXOSIZX_m4aMPTXKti4l01T6HhIQ4FmNc,8184
|
|
5
|
+
jmcomic/jm_config.py,sha256=lhVTAjexPfBGgFhievcuE9s4U2EkHYjBtrbMnTutp2E,9863
|
|
6
|
+
jmcomic/jm_downloader.py,sha256=JRdO5BSSC5dqN-O8hCZpkH2yaUjCwNYhbva37X_3nso,6016
|
|
7
|
+
jmcomic/jm_entity.py,sha256=VEw4vCpsmzCJqlOuzLz7O9aeHIuGpwCLX10yzoX4ZIc,12908
|
|
8
|
+
jmcomic/jm_option.py,sha256=zgwNLXAtJUQ9ALsrlh3Cq_kpqjQwhQIHkyRu7NUJCKQ,10408
|
|
9
|
+
jmcomic/jm_plugin.py,sha256=PY7ulWiTnYOGf5vRb6dF-XydfSJEIRX0Xa6LkrEsJkg,1306
|
|
10
|
+
jmcomic/jm_toolkit.py,sha256=QKjzZOx4JX801RtpWKGvCMTTdi-WMU7eGSnFvD7iKME,12035
|
|
11
|
+
jmcomic-2.2.0.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
|
|
12
|
+
jmcomic-2.2.0.dist-info/METADATA,sha256=7ZMJtsk7MpJ-apCI0fJJdEVAcf0F8FZKOBdKVXd5Jpc,4428
|
|
13
|
+
jmcomic-2.2.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
14
|
+
jmcomic-2.2.0.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
|
|
15
|
+
jmcomic-2.2.0.dist-info/RECORD,,
|
jmcomic-2.1.21.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
jmcomic/__init__.py,sha256=o0Ckfc5P-D1zwvuYrPZi0nLWHw_ZKTBIAKtZZ9VbrgI,176
|
|
2
|
-
jmcomic/api.py,sha256=s1LTgpKQh5hMnl3Im6qD5nvrnusf6NHawzvJKbZxwCo,1864
|
|
3
|
-
jmcomic/jm_client_impl.py,sha256=vT5HOlK-eohgQJmLbdw_yubdcLqnGZjtEMAseVGqQKQ,14229
|
|
4
|
-
jmcomic/jm_client_interface.py,sha256=5BCWxrWkoRRXOSIZX_m4aMPTXKti4l01T6HhIQ4FmNc,8184
|
|
5
|
-
jmcomic/jm_config.py,sha256=eayA_RDqKeWpkf57Da2jXFBK7-hWs3wa-8Zu5VP_Csg,9662
|
|
6
|
-
jmcomic/jm_downloader.py,sha256=NrDp8q7l1-FChAsEUOnWp9Vcx-C3xn5R2Cq6kG4s2nc,5910
|
|
7
|
-
jmcomic/jm_entity.py,sha256=VEw4vCpsmzCJqlOuzLz7O9aeHIuGpwCLX10yzoX4ZIc,12908
|
|
8
|
-
jmcomic/jm_option.py,sha256=sYzNN_-ptfPIJ4YwBU-x4vQZhbcDdQpvj-PASaHYDOw,8729
|
|
9
|
-
jmcomic/jm_toolkit.py,sha256=QKjzZOx4JX801RtpWKGvCMTTdi-WMU7eGSnFvD7iKME,12035
|
|
10
|
-
jmcomic-2.1.21.dist-info/LICENSE,sha256=kz4coTxZxuGxisK3W00tjK57Zh3RcMGq-EnbXrK7-xA,1064
|
|
11
|
-
jmcomic-2.1.21.dist-info/METADATA,sha256=Z_ww6EdjxC7Ietv-lqBxBRK9cK-zopaTQe-zJo8kJTA,3922
|
|
12
|
-
jmcomic-2.1.21.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
13
|
-
jmcomic-2.1.21.dist-info/top_level.txt,sha256=puvVMFYJqIbd6NOTMEvOyugMTT8woBfSQyxEBan3zY4,8
|
|
14
|
-
jmcomic-2.1.21.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|