jmcomic 2.5.12__tar.gz → 2.5.15__tar.gz

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.
Files changed (24) hide show
  1. {jmcomic-2.5.12/src/jmcomic.egg-info → jmcomic-2.5.15}/PKG-INFO +54 -55
  2. jmcomic-2.5.15/README.md +157 -0
  3. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/__init__.py +1 -1
  4. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_client_impl.py +42 -3
  5. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_client_interface.py +28 -5
  6. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_config.py +32 -4
  7. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_plugin.py +23 -50
  8. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_toolkit.py +1 -1
  9. {jmcomic-2.5.12 → jmcomic-2.5.15/src/jmcomic.egg-info}/PKG-INFO +54 -55
  10. jmcomic-2.5.12/README.md +0 -158
  11. {jmcomic-2.5.12 → jmcomic-2.5.15}/LICENSE +0 -0
  12. {jmcomic-2.5.12 → jmcomic-2.5.15}/setup.cfg +0 -0
  13. {jmcomic-2.5.12 → jmcomic-2.5.15}/setup.py +0 -0
  14. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/api.py +0 -0
  15. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/cl.py +0 -0
  16. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_downloader.py +0 -0
  17. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_entity.py +0 -0
  18. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_exception.py +0 -0
  19. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic/jm_option.py +0 -0
  20. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic.egg-info/SOURCES.txt +0 -0
  21. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic.egg-info/dependency_links.txt +0 -0
  22. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic.egg-info/entry_points.txt +0 -0
  23. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic.egg-info/requires.txt +0 -0
  24. {jmcomic-2.5.12 → jmcomic-2.5.15}/src/jmcomic.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jmcomic
3
- Version: 2.5.12
3
+ Version: 2.5.15
4
4
  Summary: Python API For JMComic (禁漫天堂)
5
5
  Home-page: https://github.com/hect0x7/JMComic-Crawler-Python
6
6
  Author: hect0x7
@@ -40,24 +40,26 @@ Requires-Dist: pycryptodome
40
40
 
41
41
  ## 项目介绍
42
42
 
43
- 本项目的核心功能是下载本子,基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
43
+ 本项目的核心功能是下载本子。
44
44
 
45
- 目前核心功能实现较为稳定,项目也处于维护阶段。
45
+ 基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
46
46
 
47
- 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现,具体如下。
47
+ 目前核心功能实现较为稳定,项目也处于维护阶段。
48
48
 
49
- ### 已实现的禁漫API:
49
+ 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现。目前已有功能:
50
50
 
51
51
  - 登录
52
- - 搜本
53
- - 分类 (排行榜)
54
- - 本子章节详情
52
+ - 搜索本子(支持所有搜索项)
55
53
  - 图片下载解码
56
- - 收藏夹
57
- - 移动端接口加解密
54
+ - 分类/排行榜
55
+ - 本子/章节详情
56
+ - 个人收藏夹
57
+ - 接口加解密(APP的接口)
58
58
 
59
59
  ## 安装教程
60
60
 
61
+ > ⚠如果你没有安装过Python,需要先安装Python再执行下面的步骤,且版本需要>=3.7([点我去python官网下载](https://www.python.org/downloads/))
62
+
61
63
  * 通过pip官方源安装(推荐,并且更新也是这个命令)
62
64
 
63
65
  ```shell
@@ -72,7 +74,9 @@ Requires-Dist: pycryptodome
72
74
  ## 快速上手
73
75
 
74
76
  ### 1. 下载本子方法
77
+
75
78
  只需要使用如下代码,就可以下载本子`JM422866`的所有章节的图片:
79
+
76
80
  ```python
77
81
  import jmcomic # 导入此模块,需要先安装.
78
82
  jmcomic.download_album('422866') # 传入要下载的album的id,即可下载整个album到本地.
@@ -85,10 +89,10 @@ jmcomic.download_album('422866') # 传入要下载的album的id,即可下载
85
89
  ### 2. 使用option配置来下载本子
86
90
 
87
91
  1. 首先,创建一个配置文件,假设文件名为 `option.yml`
88
-
89
- 该文件有特定的写法,你需要参考这个文档 → [option配置](./assets/docs/sources/option_file_syntax.md)
90
-
91
- 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
92
+
93
+ 该文件有特定的写法,你需要参考这个文档 → [配置文件指南](./assets/docs/sources/option_file_syntax.md)
94
+
95
+ 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
92
96
 
93
97
  ```yml
94
98
  download:
@@ -97,6 +101,7 @@ download:
97
101
  ```
98
102
 
99
103
  2. 第二步,运行下面的python代码
104
+
100
105
  ```python
101
106
  import jmcomic
102
107
 
@@ -104,24 +109,14 @@ import jmcomic
104
109
  option = jmcomic.create_option_by_file('你的配置文件路径,例如 D:/option.yml')
105
110
  # 使用option对象来下载本子
106
111
  jmcomic.download_album(422866, option)
112
+ # 等价写法: option.download_album(422866)
107
113
  ```
108
114
 
109
-
110
-
111
115
  ## 进阶使用
112
116
 
113
- 文档网站:[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/en/latest)
114
-
115
- 首先,就下载功能,jmcomic提供了很多配置项,大部分的下载需求你都可以通过上文介绍的配置文件来配置。
117
+ 请查阅文档首页→[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/zh-cn/latest)
116
118
 
117
- 如果你不满足于下载,还有其他的使用需求,推荐你先看看以下文档:
118
-
119
- * [jmcomic常用类和方法演示](assets/docs/sources/tutorial/0_demo.md)
120
- * [option配置文件语法(包含插件配置)](./assets/docs/sources/option_file_syntax.md)
121
- * [GitHub Actions使用教程](./assets/docs/sources/tutorial/1_github_actions.md)
122
- * [命令行使用教程](assets/docs/sources/tutorial/2_command_line.md)
123
- * [插件机制](assets/docs/sources/tutorial/6_plugin.md)
124
- * [下载过滤器机制](assets/docs/sources/tutorial/5_filter.md)
119
+ (提示:jmcomic提供了很多下载配置项,大部分的下载需求你都可以尝试寻找相关配置项或插件来实现。)
125
120
 
126
121
  ## 项目特点
127
122
 
@@ -129,35 +124,35 @@ jmcomic.download_album(422866, option)
129
124
  - **实现禁漫APP接口最新的加解密算法 (1.6.3)**
130
125
  - 用法多样:
131
126
 
132
- - GitHub
133
- Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
134
- - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
135
- - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
127
+ - GitHub
128
+ Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
129
+ - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
130
+ - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
136
131
  - 支持**网页端**和**移动端**两种客户端实现,可通过配置切换(**移动端不限ip兼容性好,网页端限制ip地区但效率高**)
137
132
  - 支持**自动重试和域名切换**机制
138
133
  - **多线程下载**(可细化到一图一线程,效率极高)
139
134
  - **可配置性强**
140
135
 
141
- - 不配置也能使用,十分方便
142
- - 配置可以从配置文件生成,支持多种文件格式
143
- - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
144
-
136
+ - 不配置也能使用,十分方便
137
+ - 配置可以从配置文件生成,支持多种文件格式
138
+ - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
139
+
145
140
  - **可扩展性强**
146
141
 
147
- - 支持自定义本子/章节/图片下载前后的回调函数
148
- - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
149
- - 支持自定义日志、异常监听器
150
- - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
151
- - `登录插件`
152
- - `硬件占用监控插件`
153
- - `只下载新章插件`
154
- - `压缩文件插件`
155
- - `下载特定后缀图片插件`
156
- - `发送QQ邮件插件`
157
- - `日志主题过滤插件`
158
- - `自动使用浏览器cookies插件`
159
- - `jpg图片合成为一个pdf插件`
160
- - `导出收藏夹为csv文件插件`
142
+ - 支持自定义本子/章节/图片下载前后的回调函数
143
+ - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
144
+ - 支持自定义日志、异常监听器
145
+ - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
146
+ - `登录插件`
147
+ - `硬件占用监控插件`
148
+ - `只下载新章插件`
149
+ - `压缩文件插件`
150
+ - `下载特定后缀图片插件`
151
+ - `发送QQ邮件插件`
152
+ - `日志主题过滤插件`
153
+ - `自动使用浏览器cookies插件`
154
+ - `jpg图片合成为一个pdf插件`
155
+ - `导出收藏夹为csv文件插件`
161
156
 
162
157
  ## 使用小说明
163
158
 
@@ -169,13 +164,11 @@ jmcomic.download_album(422866, option)
169
164
  * .github:GitHub Actions配置文件
170
165
  * assets:存放一些非代码的资源文件
171
166
 
172
- * docs:项目文档
173
- * option:存放配置文件
174
-
167
+ * docs:项目文档
168
+ * option:存放配置文件
175
169
  * src:存放源代码
176
170
 
177
- * jmcomic:`jmcomic`模块
178
-
171
+ * jmcomic:`jmcomic`模块
179
172
  * tests:测试目录,存放测试代码,使用unittest
180
173
  * usage:用法目录,存放示例/使用代码
181
174
 
@@ -183,4 +176,10 @@ jmcomic.download_album(422866, option)
183
176
 
184
177
  ### 图片分割算法代码+禁漫移动端API
185
178
 
186
- [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt)](https://github.com/tonquer/JMComic-qt)
179
+ <a href="https://github.com/tonquer/JMComic-qt">
180
+ <picture>
181
+ <source media="(prefers-color-scheme: dark)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt&theme=radical" />
182
+ <source media="(prefers-color-scheme: light)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
183
+ <img alt="Repo Card" src="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
184
+ </picture>
185
+ </a>
@@ -0,0 +1,157 @@
1
+ # Python API For JMComic (禁漫天堂)
2
+
3
+ 本项目封装了一套可用于爬取JM的Python API.
4
+
5
+ 你可以通过简单的几行Python代码,实现下载JM上的本子到本地,并且是处理好的图片。
6
+
7
+ [【指路】教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md)
8
+
9
+ [【指路】教程:导出并下载你的禁漫收藏夹数据](./assets/docs/sources/tutorial/10_export_favorites.md)
10
+
11
+ **友情提示:珍爱JM,为了减轻JM的服务器压力,请不要一次性爬取太多本子,西门🙏🙏🙏**.
12
+
13
+ ## 项目介绍
14
+
15
+ 本项目的核心功能是下载本子。
16
+
17
+ 基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
18
+
19
+ 目前核心功能实现较为稳定,项目也处于维护阶段。
20
+
21
+ 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现。目前已有功能:
22
+
23
+ - 登录
24
+ - 搜索本子(支持所有搜索项)
25
+ - 图片下载解码
26
+ - 分类/排行榜
27
+ - 本子/章节详情
28
+ - 个人收藏夹
29
+ - 接口加解密(APP的接口)
30
+
31
+ ## 安装教程
32
+
33
+ > ⚠如果你没有安装过Python,需要先安装Python再执行下面的步骤,且版本需要>=3.7([点我去python官网下载](https://www.python.org/downloads/))
34
+
35
+ * 通过pip官方源安装(推荐,并且更新也是这个命令)
36
+
37
+ ```shell
38
+ pip install jmcomic -i https://pypi.org/project -U
39
+ ```
40
+ * 通过源代码安装
41
+
42
+ ```shell
43
+ pip install git+https://github.com/hect0x7/JMComic-Crawler-Python
44
+ ```
45
+
46
+ ## 快速上手
47
+
48
+ ### 1. 下载本子方法
49
+
50
+ 只需要使用如下代码,就可以下载本子`JM422866`的所有章节的图片:
51
+
52
+ ```python
53
+ import jmcomic # 导入此模块,需要先安装.
54
+ jmcomic.download_album('422866') # 传入要下载的album的id,即可下载整个album到本地.
55
+ ```
56
+
57
+ 上面的 `download_album`方法还有一个参数`option`,可用于控制下载配置,配置包括禁漫域名、网络代理、图片格式转换、插件等等。
58
+
59
+ 你可能需要这些配置项。推荐使用配置文件创建option,用option下载本子,见下章:
60
+
61
+ ### 2. 使用option配置来下载本子
62
+
63
+ 1. 首先,创建一个配置文件,假设文件名为 `option.yml`
64
+
65
+ 该文件有特定的写法,你需要参考这个文档 → [配置文件指南](./assets/docs/sources/option_file_syntax.md)
66
+
67
+ 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
68
+
69
+ ```yml
70
+ download:
71
+ image:
72
+ suffix: .png # 该配置用于把下载的图片转为png格式
73
+ ```
74
+
75
+ 2. 第二步,运行下面的python代码
76
+
77
+ ```python
78
+ import jmcomic
79
+
80
+ # 创建配置对象
81
+ option = jmcomic.create_option_by_file('你的配置文件路径,例如 D:/option.yml')
82
+ # 使用option对象来下载本子
83
+ jmcomic.download_album(422866, option)
84
+ # 等价写法: option.download_album(422866)
85
+ ```
86
+
87
+ ## 进阶使用
88
+
89
+ 请查阅文档首页→[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/zh-cn/latest)
90
+
91
+ (提示:jmcomic提供了很多下载配置项,大部分的下载需求你都可以尝试寻找相关配置项或插件来实现。)
92
+
93
+ ## 项目特点
94
+
95
+ - **绕过Cloudflare的反爬虫**
96
+ - **实现禁漫APP接口最新的加解密算法 (1.6.3)**
97
+ - 用法多样:
98
+
99
+ - GitHub
100
+ Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
101
+ - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
102
+ - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
103
+ - 支持**网页端**和**移动端**两种客户端实现,可通过配置切换(**移动端不限ip兼容性好,网页端限制ip地区但效率高**)
104
+ - 支持**自动重试和域名切换**机制
105
+ - **多线程下载**(可细化到一图一线程,效率极高)
106
+ - **可配置性强**
107
+
108
+ - 不配置也能使用,十分方便
109
+ - 配置可以从配置文件生成,支持多种文件格式
110
+ - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
111
+
112
+ - **可扩展性强**
113
+
114
+ - 支持自定义本子/章节/图片下载前后的回调函数
115
+ - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
116
+ - 支持自定义日志、异常监听器
117
+ - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
118
+ - `登录插件`
119
+ - `硬件占用监控插件`
120
+ - `只下载新章插件`
121
+ - `压缩文件插件`
122
+ - `下载特定后缀图片插件`
123
+ - `发送QQ邮件插件`
124
+ - `日志主题过滤插件`
125
+ - `自动使用浏览器cookies插件`
126
+ - `jpg图片合成为一个pdf插件`
127
+ - `导出收藏夹为csv文件插件`
128
+
129
+ ## 使用小说明
130
+
131
+ * Python >= 3.7
132
+ * 个人项目,文档和示例会有不及时之处,可以Issue提问
133
+
134
+ ## 项目文件夹介绍
135
+
136
+ * .github:GitHub Actions配置文件
137
+ * assets:存放一些非代码的资源文件
138
+
139
+ * docs:项目文档
140
+ * option:存放配置文件
141
+ * src:存放源代码
142
+
143
+ * jmcomic:`jmcomic`模块
144
+ * tests:测试目录,存放测试代码,使用unittest
145
+ * usage:用法目录,存放示例/使用代码
146
+
147
+ ## 感谢以下项目
148
+
149
+ ### 图片分割算法代码+禁漫移动端API
150
+
151
+ <a href="https://github.com/tonquer/JMComic-qt">
152
+ <picture>
153
+ <source media="(prefers-color-scheme: dark)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt&theme=radical" />
154
+ <source media="(prefers-color-scheme: light)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
155
+ <img alt="Repo Card" src="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
156
+ </picture>
157
+ </a>
@@ -2,7 +2,7 @@
2
2
  # 被依赖方 <--- 使用方
3
3
  # config <--- entity <--- toolkit <--- client <--- option <--- downloader
4
4
 
5
- __version__ = '2.5.12'
5
+ __version__ = '2.5.15'
6
6
 
7
7
  from .api import *
8
8
  from .jm_plugin import *
@@ -237,6 +237,9 @@ class JmHtmlClient(AbstractJmClient):
237
237
 
238
238
  func_to_cache = ['search', 'fetch_detail_entity']
239
239
 
240
+ API_SEARCH = '/search/photos'
241
+ API_CATEGORY = '/albums'
242
+
240
243
  def add_favorite_album(self,
241
244
  album_id,
242
245
  folder_id='0',
@@ -304,7 +307,12 @@ class JmHtmlClient(AbstractJmClient):
304
307
  main_tag: int,
305
308
  order_by: str,
306
309
  time: str,
310
+ category: str,
311
+ sub_category: Optional[str],
307
312
  ) -> JmSearchPage:
313
+ """
314
+ 网页搜索API
315
+ """
308
316
  params = {
309
317
  'main_tag': main_tag,
310
318
  'search_query': search_query,
@@ -313,8 +321,10 @@ class JmHtmlClient(AbstractJmClient):
313
321
  't': time,
314
322
  }
315
323
 
324
+ url = self.build_search_url(self.API_SEARCH, category, sub_category)
325
+
316
326
  resp = self.get_jm_html(
317
- self.append_params_to_url('/search/photos', params),
327
+ self.append_params_to_url(url, params),
318
328
  allow_redirects=True,
319
329
  )
320
330
 
@@ -326,11 +336,31 @@ class JmHtmlClient(AbstractJmClient):
326
336
  else:
327
337
  return JmPageTool.parse_html_to_search_page(resp.text)
328
338
 
339
+ @classmethod
340
+ def build_search_url(cls, base: str, category: str, sub_category: Optional[str]):
341
+ """
342
+ 构建网页搜索/分类的URL
343
+
344
+ 示例:
345
+ :param base: "/search/photos"
346
+ :param category CATEGORY_DOUJIN
347
+ :param sub_category SUB_DOUJIN_CG
348
+ :return "/search/photos/doujin/sub/CG"
349
+ """
350
+ if category == JmMagicConstants.CATEGORY_ALL:
351
+ return base
352
+
353
+ if sub_category is None:
354
+ return f'{base}/{category}'
355
+ else:
356
+ return f'{base}/{category}/sub/{sub_category}'
357
+
329
358
  def categories_filter(self,
330
359
  page: int,
331
360
  time: str,
332
361
  category: str,
333
362
  order_by: str,
363
+ sub_category: Optional[str] = None,
334
364
  ) -> JmCategoryPage:
335
365
  params = {
336
366
  'page': page,
@@ -338,7 +368,7 @@ class JmHtmlClient(AbstractJmClient):
338
368
  't': time,
339
369
  }
340
370
 
341
- url = f'/albums/' + (category if category != JmMagicConstants.CATEGORY_ALL else '')
371
+ url = self.build_search_url(self.API_CATEGORY, category, sub_category)
342
372
 
343
373
  resp = self.get_jm_html(
344
374
  self.append_params_to_url(url, params),
@@ -372,7 +402,7 @@ class JmHtmlClient(AbstractJmClient):
372
402
  allow_redirects=False,
373
403
  )
374
404
 
375
- if resp.status_code != 301:
405
+ if resp.status_code != 200:
376
406
  ExceptionTool.raises_resp(f'登录失败,状态码为{resp.status_code}', resp)
377
407
 
378
408
  orig_cookies = self.get_meta_data('cookies') or {}
@@ -573,7 +603,12 @@ class JmApiClient(AbstractJmClient):
573
603
  main_tag: int,
574
604
  order_by: str,
575
605
  time: str,
606
+ category: str,
607
+ sub_category: Optional[str],
576
608
  ) -> JmSearchPage:
609
+ """
610
+ 移动端暂不支持 category和sub_category
611
+ """
577
612
  params = {
578
613
  'main_tag': main_tag,
579
614
  'search_query': search_query,
@@ -603,7 +638,11 @@ class JmApiClient(AbstractJmClient):
603
638
  time: str,
604
639
  category: str,
605
640
  order_by: str,
641
+ sub_category: Optional[str] = None,
606
642
  ):
643
+ """
644
+ 移动端不支持 sub_category
645
+ """
607
646
  # o: mv, mv_m, mv_w, mv_t
608
647
  o = f'{order_by}_{time}' if time != JmMagicConstants.TIME_ALL else order_by
609
648
 
@@ -308,9 +308,14 @@ class JmSearchAlbumClient:
308
308
  main_tag: int,
309
309
  order_by: str,
310
310
  time: str,
311
+ category: str,
312
+ sub_category: Optional[str],
311
313
  ) -> JmSearchPage:
312
314
  """
313
315
  搜索【成人A漫】
316
+ 网页端与移动端的搜索有差别:
317
+
318
+ - 移动端不支持 category, sub_category参数,网页端支持全部参数
314
319
  """
315
320
  raise NotImplementedError
316
321
 
@@ -319,55 +324,65 @@ class JmSearchAlbumClient:
319
324
  page: int = 1,
320
325
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
321
326
  time: str = JmMagicConstants.TIME_ALL,
327
+ category: str = JmMagicConstants.CATEGORY_ALL,
328
+ sub_category: Optional[str] = None,
322
329
  ):
323
330
  """
324
331
  对应禁漫的站内搜索
325
332
  """
326
- return self.search(search_query, page, 0, order_by, time)
333
+ return self.search(search_query, page, 0, order_by, time, category, sub_category)
327
334
 
328
335
  def search_work(self,
329
336
  search_query: str,
330
337
  page: int = 1,
331
338
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
332
339
  time: str = JmMagicConstants.TIME_ALL,
340
+ category: str = JmMagicConstants.CATEGORY_ALL,
341
+ sub_category: Optional[str] = None,
333
342
  ):
334
343
  """
335
344
  搜索album的作品 work
336
345
  """
337
- return self.search(search_query, page, 1, order_by, time)
346
+ return self.search(search_query, page, 1, order_by, time, category, sub_category)
338
347
 
339
348
  def search_author(self,
340
349
  search_query: str,
341
350
  page: int = 1,
342
351
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
343
352
  time: str = JmMagicConstants.TIME_ALL,
353
+ category: str = JmMagicConstants.CATEGORY_ALL,
354
+ sub_category: Optional[str] = None,
344
355
  ):
345
356
  """
346
357
  搜索album的作者 author
347
358
  """
348
- return self.search(search_query, page, 2, order_by, time)
359
+ return self.search(search_query, page, 2, order_by, time, category, sub_category)
349
360
 
350
361
  def search_tag(self,
351
362
  search_query: str,
352
363
  page: int = 1,
353
364
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
354
365
  time: str = JmMagicConstants.TIME_ALL,
366
+ category: str = JmMagicConstants.CATEGORY_ALL,
367
+ sub_category: Optional[str] = None,
355
368
  ):
356
369
  """
357
370
  搜索album的标签 tag
358
371
  """
359
- return self.search(search_query, page, 3, order_by, time)
372
+ return self.search(search_query, page, 3, order_by, time, category, sub_category)
360
373
 
361
374
  def search_actor(self,
362
375
  search_query: str,
363
376
  page: int = 1,
364
377
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
365
378
  time: str = JmMagicConstants.TIME_ALL,
379
+ category: str = JmMagicConstants.CATEGORY_ALL,
380
+ sub_category: Optional[str] = None,
366
381
  ):
367
382
  """
368
383
  搜索album的登场角色 actor
369
384
  """
370
- return self.search(search_query, page, 4, order_by, time)
385
+ return self.search(search_query, page, 4, order_by, time, category, sub_category)
371
386
 
372
387
 
373
388
  class JmCategoryClient:
@@ -384,6 +399,7 @@ class JmCategoryClient:
384
399
  time: str,
385
400
  category: str,
386
401
  order_by: str,
402
+ sub_category: Optional[str] = None,
387
403
  ) -> JmCategoryPage:
388
404
  """
389
405
  分类
@@ -391,6 +407,7 @@ class JmCategoryClient:
391
407
  :param page: 页码
392
408
  :param time: 时间范围,默认是全部时间
393
409
  :param category: 类别,默认是最新,即显示最新的禁漫本子
410
+ :param sub_category: 副分类,仅网页端有这功能
394
411
  :param order_by: 排序方式,默认是观看数
395
412
  """
396
413
  raise NotImplementedError
@@ -522,6 +539,8 @@ class JmcomicClient(
522
539
  page: int = 1,
523
540
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
524
541
  time: str = JmMagicConstants.TIME_ALL,
542
+ category: str = JmMagicConstants.CATEGORY_ALL,
543
+ sub_category: Optional[str] = None,
525
544
  ) -> Generator[JmSearchPage, Dict, None]:
526
545
  """
527
546
  搜索结果的生成器,支持下面这种调用方式:
@@ -552,6 +571,8 @@ class JmcomicClient(
552
571
  'main_tag': main_tag,
553
572
  'order_by': order_by,
554
573
  'time': time,
574
+ 'category': category,
575
+ 'sub_category': sub_category,
555
576
  }
556
577
 
557
578
  yield from self.do_page_iter(params, page, self.search)
@@ -561,6 +582,7 @@ class JmcomicClient(
561
582
  time: str = JmMagicConstants.TIME_ALL,
562
583
  category: str = JmMagicConstants.CATEGORY_ALL,
563
584
  order_by: str = JmMagicConstants.ORDER_BY_LATEST,
585
+ sub_category: Optional[str] = None,
564
586
  ) -> Generator[JmCategoryPage, Dict, None]:
565
587
  """
566
588
  见 search_gen
@@ -569,6 +591,7 @@ class JmcomicClient(
569
591
  'time': time,
570
592
  'category': category,
571
593
  'order_by': order_by,
594
+ 'sub_category': sub_category,
572
595
  }
573
596
 
574
597
  yield from self.do_page_iter(params, page, self.categories_filter)
@@ -35,7 +35,29 @@ class JmMagicConstants:
35
35
  CATEGORY_DOUJIN_COSPLAY = 'doujin_cosplay' # cosplay
36
36
  CATEGORY_3D = '3D' # 3D
37
37
  CATEGORY_ENGLISH_SITE = 'english_site' # 英文站
38
- CATEGORY_JM_TEAM = '禁漫漢化組'
38
+
39
+ # 副分类
40
+ SUB_CHINESE = 'chinese' # 汉化,通用副分类
41
+ SUB_JAPANESE = 'japanese' # 日语,通用副分类
42
+
43
+ # 其他类(CATEGORY_ANOTHER)的副分类
44
+ SUB_ANOTHER_OTHER = 'other' # 其他漫画
45
+ SUB_ANOTHER_3D = '3d' # 3D
46
+ SUB_ANOTHER_COSPLAY = 'cosplay' # cosplay
47
+
48
+ # 同人(SUB_CHINESE)的副分类
49
+ SUB_DOUJIN_CG = 'CG' # CG
50
+ SUB_DOUJIN_CHINESE = SUB_CHINESE
51
+ SUB_DOUJIN_JAPANESE = SUB_JAPANESE
52
+
53
+ # 短篇(CATEGORY_SHORT)的副分类
54
+ SUB_SHORT_CHINESE = SUB_CHINESE
55
+ SUB_SHORT_JAPANESE = SUB_JAPANESE
56
+
57
+ # 单本(CATEGORY_SINGLE)的副分类
58
+ SUB_SINGLE_CHINESE = SUB_CHINESE
59
+ SUB_SINGLE_JAPANESE = SUB_JAPANESE
60
+ SUB_SINGLE_YOUTH = 'youth'
39
61
 
40
62
  # 分页大小
41
63
  PAGE_SIZE_SEARCH = 80
@@ -53,7 +75,7 @@ class JmMagicConstants:
53
75
  APP_TOKEN_SECRET = '18comicAPP'
54
76
  APP_TOKEN_SECRET_2 = '18comicAPPContent'
55
77
  APP_DATA_SECRET = '185Hcomic3PAPP7R'
56
- APP_VERSION = '1.6.7'
78
+ APP_VERSION = '1.7.0'
57
79
  APP_HEADERS_TEMPLATE = {
58
80
  'Accept-Encoding': 'gzip',
59
81
  'user-agent': 'Mozilla/5.0 (Linux; Android 9; V1938CT Build/PQ3A.190705.11211812; wv) AppleWebKit/537.36 (KHTML, '
@@ -65,14 +87,20 @@ class JmMagicConstants:
65
87
  'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,'
66
88
  'application/signed-exchange;v=b3;q=0.7',
67
89
  'accept-language': 'zh-CN,zh;q=0.9',
68
- 'sec-ch-ua': '"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"',
90
+ 'cache-control': 'no-cache',
91
+ 'dnt': '1',
92
+ 'pragma': 'no-cache',
93
+ 'priority': 'u=0, i',
94
+ 'referer': 'https://18comic.vip/',
95
+ 'sec-ch-ua': '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
69
96
  'sec-ch-ua-mobile': '?0',
70
97
  'sec-ch-ua-platform': '"Windows"',
71
98
  'sec-fetch-dest': 'document',
72
99
  'sec-fetch-mode': 'navigate',
73
100
  'sec-fetch-site': 'none',
74
101
  'sec-fetch-user': '?1',
75
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '
102
+ 'upgrade-insecure-requests': '1',
103
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 '
76
104
  'Safari/537.36',
77
105
  }
78
106
 
@@ -1,6 +1,7 @@
1
1
  """
2
2
  该文件存放的是option插件
3
3
  """
4
+ import os.path
4
5
 
5
6
  from .jm_option import *
6
7
 
@@ -296,91 +297,63 @@ class ZipPlugin(JmOptionPlugin):
296
297
  zip_dir = JmcomicText.parse_to_abspath(zip_dir)
297
298
  mkdir_if_not_exists(zip_dir)
298
299
 
299
- # 原文件夹 -> zip文件
300
- dir_zip_dict: Dict[str, Optional[str]] = {}
300
+ path_to_delete = []
301
301
  photo_dict = downloader.download_success_dict[album]
302
302
 
303
303
  if level == 'album':
304
304
  zip_path = self.get_zip_path(album, None, filename_rule, suffix, zip_dir)
305
- self.zip_album(album, photo_dict, zip_path, dir_zip_dict)
305
+ self.zip_album(album, photo_dict, zip_path, path_to_delete)
306
306
 
307
307
  elif level == 'photo':
308
308
  for photo, image_list in photo_dict.items():
309
309
  zip_path = self.get_zip_path(None, photo, filename_rule, suffix, zip_dir)
310
- self.zip_photo(photo, image_list, zip_path, dir_zip_dict)
310
+ self.zip_photo(photo, image_list, zip_path, path_to_delete)
311
311
 
312
312
  else:
313
313
  ExceptionTool.raises(f'Not Implemented Zip Level: {level}')
314
314
 
315
- self.after_zip(dir_zip_dict)
315
+ self.after_zip(path_to_delete)
316
316
 
317
- def zip_photo(self, photo, image_list: list, zip_path: str, dir_zip_dict) -> Optional[str]:
317
+ def zip_photo(self, photo, image_list: list, zip_path: str, path_to_delete):
318
318
  """
319
319
  压缩photo文件夹
320
- :returns: photo文件夹路径
321
320
  """
322
321
  photo_dir = self.option.decide_image_save_dir(photo) \
323
322
  if len(image_list) == 0 \
324
323
  else os.path.dirname(image_list[0][0])
325
324
 
326
- all_filepath = set(map(lambda t: self.unified_path(t[0]), image_list))
327
-
328
- if len(all_filepath) == 0:
329
- self.log('无下载文件,无需压缩', 'skip')
330
- return None
331
-
332
325
  from common import backup_dir_to_zip
333
- backup_dir_to_zip(
334
- photo_dir,
335
- zip_path,
336
- acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
337
- ).close()
326
+ backup_dir_to_zip(photo_dir, zip_path)
338
327
 
339
328
  self.log(f'压缩章节[{photo.photo_id}]成功 → {zip_path}', 'finish')
340
- dir_zip_dict[self.unified_path(photo_dir)] = zip_path
329
+ path_to_delete.append(self.unified_path(photo_dir))
341
330
 
342
331
  @staticmethod
343
332
  def unified_path(f):
344
333
  return fix_filepath(f, os.path.isdir(f))
345
334
 
346
- def zip_album(self, album, photo_dict: dict, zip_path, dir_zip_dict) -> Optional[str]:
335
+ def zip_album(self, album, photo_dict: dict, zip_path, path_to_delete):
347
336
  """
348
337
  压缩album文件夹
349
- :returns: album文件夹路径
350
338
  """
351
339
 
352
- # 所有下载了的图片文件的路径
353
- all_filepath: Set[str] = set(path for ls in photo_dict.values() for path, _ in ls)
354
-
355
- if len(all_filepath) == 0:
356
- self.log('无下载文件,无需压缩', 'skip')
357
- return
358
-
359
- # 该本子的所有章节的图片所在文件夹
360
- photo_dir_list = [self.option.decide_image_save_dir(photo) for photo in photo_dict.keys()]
361
-
362
- # 压缩文件对象
363
- from common import backup_dir_to_zip
340
+ album_dir = self.option.dir_rule.decide_album_root_dir(album)
364
341
  import zipfile
365
- zfile = zipfile.ZipFile(zip_path, 'w')
366
-
367
- for photo_dir in photo_dir_list:
368
- photo_dir = self.unified_path(photo_dir)
369
- backup_dir_to_zip(
370
- photo_dir,
371
- zip_path,
372
- zfile=zfile,
373
- prefix=os.path.basename(photo_dir.rstrip('/')),
374
- acceptor=lambda f: os.path.isdir(f) or self.unified_path(f) in all_filepath
375
- )
376
- dir_zip_dict[photo_dir] = zip_path
377
-
378
- zfile.close()
342
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as f:
343
+ for photo in photo_dict.keys():
344
+ # 定位到章节所在文件夹
345
+ photo_dir = self.unified_path(self.option.decide_image_save_dir(photo))
346
+ # 章节文件夹标记为删除
347
+ path_to_delete.append(photo_dir)
348
+ for file in files_of_dir(photo_dir):
349
+ abspath = os.path.join(photo_dir, file)
350
+ relpath = os.path.relpath(abspath, album_dir)
351
+ f.write(abspath, relpath)
379
352
  self.log(f'压缩本子[{album.album_id}]成功 → {zip_path}', 'finish')
380
353
 
381
- def after_zip(self, dir_zip_dict: Dict[str, Optional[str]]):
354
+ def after_zip(self, path_to_delete: List[str]):
382
355
  # 删除所有原文件
383
- dirs = sorted(dir_zip_dict.keys(), reverse=True)
356
+ dirs = sorted(path_to_delete, reverse=True)
384
357
  image_paths = [
385
358
  path
386
359
  for photo_dict in self.downloader.download_success_dict.values()
@@ -650,7 +623,7 @@ class FavoriteFolderExportPlugin(JmOptionPlugin):
650
623
  """
651
624
  import zipfile
652
625
 
653
- with zipfile.ZipFile(zip_path, 'w') as zipf:
626
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
654
627
  # 获取文件夹中的文件列表并将其添加到 ZIP 文件中
655
628
  for file in files:
656
629
  zipf.write(file, arcname=of_file_name(file))
@@ -135,7 +135,7 @@ class JmcomicText:
135
135
  last_pattern = pattern[len(pattern) - 1]
136
136
  # 缩小文本
137
137
  for i in range(0, len(pattern) - 1):
138
- match = pattern[i].search(text)
138
+ match: Match = pattern[i].search(text)
139
139
  if match is None:
140
140
  return None
141
141
  text = match[0]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jmcomic
3
- Version: 2.5.12
3
+ Version: 2.5.15
4
4
  Summary: Python API For JMComic (禁漫天堂)
5
5
  Home-page: https://github.com/hect0x7/JMComic-Crawler-Python
6
6
  Author: hect0x7
@@ -40,24 +40,26 @@ Requires-Dist: pycryptodome
40
40
 
41
41
  ## 项目介绍
42
42
 
43
- 本项目的核心功能是下载本子,基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
43
+ 本项目的核心功能是下载本子。
44
44
 
45
- 目前核心功能实现较为稳定,项目也处于维护阶段。
45
+ 基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
46
46
 
47
- 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现,具体如下。
47
+ 目前核心功能实现较为稳定,项目也处于维护阶段。
48
48
 
49
- ### 已实现的禁漫API:
49
+ 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现。目前已有功能:
50
50
 
51
51
  - 登录
52
- - 搜本
53
- - 分类 (排行榜)
54
- - 本子章节详情
52
+ - 搜索本子(支持所有搜索项)
55
53
  - 图片下载解码
56
- - 收藏夹
57
- - 移动端接口加解密
54
+ - 分类/排行榜
55
+ - 本子/章节详情
56
+ - 个人收藏夹
57
+ - 接口加解密(APP的接口)
58
58
 
59
59
  ## 安装教程
60
60
 
61
+ > ⚠如果你没有安装过Python,需要先安装Python再执行下面的步骤,且版本需要>=3.7([点我去python官网下载](https://www.python.org/downloads/))
62
+
61
63
  * 通过pip官方源安装(推荐,并且更新也是这个命令)
62
64
 
63
65
  ```shell
@@ -72,7 +74,9 @@ Requires-Dist: pycryptodome
72
74
  ## 快速上手
73
75
 
74
76
  ### 1. 下载本子方法
77
+
75
78
  只需要使用如下代码,就可以下载本子`JM422866`的所有章节的图片:
79
+
76
80
  ```python
77
81
  import jmcomic # 导入此模块,需要先安装.
78
82
  jmcomic.download_album('422866') # 传入要下载的album的id,即可下载整个album到本地.
@@ -85,10 +89,10 @@ jmcomic.download_album('422866') # 传入要下载的album的id,即可下载
85
89
  ### 2. 使用option配置来下载本子
86
90
 
87
91
  1. 首先,创建一个配置文件,假设文件名为 `option.yml`
88
-
89
- 该文件有特定的写法,你需要参考这个文档 → [option配置](./assets/docs/sources/option_file_syntax.md)
90
-
91
- 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
92
+
93
+ 该文件有特定的写法,你需要参考这个文档 → [配置文件指南](./assets/docs/sources/option_file_syntax.md)
94
+
95
+ 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
92
96
 
93
97
  ```yml
94
98
  download:
@@ -97,6 +101,7 @@ download:
97
101
  ```
98
102
 
99
103
  2. 第二步,运行下面的python代码
104
+
100
105
  ```python
101
106
  import jmcomic
102
107
 
@@ -104,24 +109,14 @@ import jmcomic
104
109
  option = jmcomic.create_option_by_file('你的配置文件路径,例如 D:/option.yml')
105
110
  # 使用option对象来下载本子
106
111
  jmcomic.download_album(422866, option)
112
+ # 等价写法: option.download_album(422866)
107
113
  ```
108
114
 
109
-
110
-
111
115
  ## 进阶使用
112
116
 
113
- 文档网站:[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/en/latest)
114
-
115
- 首先,就下载功能,jmcomic提供了很多配置项,大部分的下载需求你都可以通过上文介绍的配置文件来配置。
117
+ 请查阅文档首页→[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/zh-cn/latest)
116
118
 
117
- 如果你不满足于下载,还有其他的使用需求,推荐你先看看以下文档:
118
-
119
- * [jmcomic常用类和方法演示](assets/docs/sources/tutorial/0_demo.md)
120
- * [option配置文件语法(包含插件配置)](./assets/docs/sources/option_file_syntax.md)
121
- * [GitHub Actions使用教程](./assets/docs/sources/tutorial/1_github_actions.md)
122
- * [命令行使用教程](assets/docs/sources/tutorial/2_command_line.md)
123
- * [插件机制](assets/docs/sources/tutorial/6_plugin.md)
124
- * [下载过滤器机制](assets/docs/sources/tutorial/5_filter.md)
119
+ (提示:jmcomic提供了很多下载配置项,大部分的下载需求你都可以尝试寻找相关配置项或插件来实现。)
125
120
 
126
121
  ## 项目特点
127
122
 
@@ -129,35 +124,35 @@ jmcomic.download_album(422866, option)
129
124
  - **实现禁漫APP接口最新的加解密算法 (1.6.3)**
130
125
  - 用法多样:
131
126
 
132
- - GitHub
133
- Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
134
- - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
135
- - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
127
+ - GitHub
128
+ Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
129
+ - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
130
+ - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
136
131
  - 支持**网页端**和**移动端**两种客户端实现,可通过配置切换(**移动端不限ip兼容性好,网页端限制ip地区但效率高**)
137
132
  - 支持**自动重试和域名切换**机制
138
133
  - **多线程下载**(可细化到一图一线程,效率极高)
139
134
  - **可配置性强**
140
135
 
141
- - 不配置也能使用,十分方便
142
- - 配置可以从配置文件生成,支持多种文件格式
143
- - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
144
-
136
+ - 不配置也能使用,十分方便
137
+ - 配置可以从配置文件生成,支持多种文件格式
138
+ - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
139
+
145
140
  - **可扩展性强**
146
141
 
147
- - 支持自定义本子/章节/图片下载前后的回调函数
148
- - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
149
- - 支持自定义日志、异常监听器
150
- - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
151
- - `登录插件`
152
- - `硬件占用监控插件`
153
- - `只下载新章插件`
154
- - `压缩文件插件`
155
- - `下载特定后缀图片插件`
156
- - `发送QQ邮件插件`
157
- - `日志主题过滤插件`
158
- - `自动使用浏览器cookies插件`
159
- - `jpg图片合成为一个pdf插件`
160
- - `导出收藏夹为csv文件插件`
142
+ - 支持自定义本子/章节/图片下载前后的回调函数
143
+ - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
144
+ - 支持自定义日志、异常监听器
145
+ - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
146
+ - `登录插件`
147
+ - `硬件占用监控插件`
148
+ - `只下载新章插件`
149
+ - `压缩文件插件`
150
+ - `下载特定后缀图片插件`
151
+ - `发送QQ邮件插件`
152
+ - `日志主题过滤插件`
153
+ - `自动使用浏览器cookies插件`
154
+ - `jpg图片合成为一个pdf插件`
155
+ - `导出收藏夹为csv文件插件`
161
156
 
162
157
  ## 使用小说明
163
158
 
@@ -169,13 +164,11 @@ jmcomic.download_album(422866, option)
169
164
  * .github:GitHub Actions配置文件
170
165
  * assets:存放一些非代码的资源文件
171
166
 
172
- * docs:项目文档
173
- * option:存放配置文件
174
-
167
+ * docs:项目文档
168
+ * option:存放配置文件
175
169
  * src:存放源代码
176
170
 
177
- * jmcomic:`jmcomic`模块
178
-
171
+ * jmcomic:`jmcomic`模块
179
172
  * tests:测试目录,存放测试代码,使用unittest
180
173
  * usage:用法目录,存放示例/使用代码
181
174
 
@@ -183,4 +176,10 @@ jmcomic.download_album(422866, option)
183
176
 
184
177
  ### 图片分割算法代码+禁漫移动端API
185
178
 
186
- [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt)](https://github.com/tonquer/JMComic-qt)
179
+ <a href="https://github.com/tonquer/JMComic-qt">
180
+ <picture>
181
+ <source media="(prefers-color-scheme: dark)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt&theme=radical" />
182
+ <source media="(prefers-color-scheme: light)" srcset="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
183
+ <img alt="Repo Card" src="https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt" />
184
+ </picture>
185
+ </a>
jmcomic-2.5.12/README.md DELETED
@@ -1,158 +0,0 @@
1
- # Python API For JMComic (禁漫天堂)
2
-
3
- 本项目封装了一套可用于爬取JM的Python API.
4
-
5
- 你可以通过简单的几行Python代码,实现下载JM上的本子到本地,并且是处理好的图片。
6
-
7
- [【指路】教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md)
8
-
9
- [【指路】教程:导出并下载你的禁漫收藏夹数据](./assets/docs/sources/tutorial/10_export_favorites.md)
10
-
11
- **友情提示:珍爱JM,为了减轻JM的服务器压力,请不要一次性爬取太多本子,西门🙏🙏🙏**.
12
-
13
- ## 项目介绍
14
-
15
- 本项目的核心功能是下载本子,基于此,设计了一套方便使用、便于扩展,能满足一些特殊下载需求的框架。
16
-
17
- 目前核心功能实现较为稳定,项目也处于维护阶段。
18
-
19
- 除了下载功能以外,也实现了其他的一些禁漫接口,按需实现,具体如下。
20
-
21
- ### 已实现的禁漫API:
22
-
23
- - 登录
24
- - 搜本
25
- - 分类 (排行榜)
26
- - 本子章节详情
27
- - 图片下载解码
28
- - 收藏夹
29
- - 移动端接口加解密
30
-
31
- ## 安装教程
32
-
33
- * 通过pip官方源安装(推荐,并且更新也是这个命令)
34
-
35
- ```shell
36
- pip install jmcomic -i https://pypi.org/project -U
37
- ```
38
- * 通过源代码安装
39
-
40
- ```shell
41
- pip install git+https://github.com/hect0x7/JMComic-Crawler-Python
42
- ```
43
-
44
- ## 快速上手
45
-
46
- ### 1. 下载本子方法
47
- 只需要使用如下代码,就可以下载本子`JM422866`的所有章节的图片:
48
- ```python
49
- import jmcomic # 导入此模块,需要先安装.
50
- jmcomic.download_album('422866') # 传入要下载的album的id,即可下载整个album到本地.
51
- ```
52
-
53
- 上面的 `download_album`方法还有一个参数`option`,可用于控制下载配置,配置包括禁漫域名、网络代理、图片格式转换、插件等等。
54
-
55
- 你可能需要这些配置项。推荐使用配置文件创建option,用option下载本子,见下章:
56
-
57
- ### 2. 使用option配置来下载本子
58
-
59
- 1. 首先,创建一个配置文件,假设文件名为 `option.yml`
60
-
61
- 该文件有特定的写法,你需要参考这个文档 → [option配置](./assets/docs/sources/option_file_syntax.md)
62
-
63
- 下面做一个演示,假设你需要把下载的图片转为png格式,你应该把以下内容写进`option.yml`
64
-
65
- ```yml
66
- download:
67
- image:
68
- suffix: .png # 该配置用于把下载的图片转为png格式
69
- ```
70
-
71
- 2. 第二步,运行下面的python代码
72
- ```python
73
- import jmcomic
74
-
75
- # 创建配置对象
76
- option = jmcomic.create_option_by_file('你的配置文件路径,例如 D:/option.yml')
77
- # 使用option对象来下载本子
78
- jmcomic.download_album(422866, option)
79
- ```
80
-
81
-
82
-
83
- ## 进阶使用
84
-
85
- 文档网站:[jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/en/latest)
86
-
87
- 首先,就下载功能,jmcomic提供了很多配置项,大部分的下载需求你都可以通过上文介绍的配置文件来配置。
88
-
89
- 如果你不满足于下载,还有其他的使用需求,推荐你先看看以下文档:
90
-
91
- * [jmcomic常用类和方法演示](assets/docs/sources/tutorial/0_demo.md)
92
- * [option配置文件语法(包含插件配置)](./assets/docs/sources/option_file_syntax.md)
93
- * [GitHub Actions使用教程](./assets/docs/sources/tutorial/1_github_actions.md)
94
- * [命令行使用教程](assets/docs/sources/tutorial/2_command_line.md)
95
- * [插件机制](assets/docs/sources/tutorial/6_plugin.md)
96
- * [下载过滤器机制](assets/docs/sources/tutorial/5_filter.md)
97
-
98
- ## 项目特点
99
-
100
- - **绕过Cloudflare的反爬虫**
101
- - **实现禁漫APP接口最新的加解密算法 (1.6.3)**
102
- - 用法多样:
103
-
104
- - GitHub
105
- Actions:网页上直接输入本子id就能下载([教程:使用GitHub Actions下载禁漫本子](./assets/docs/sources/tutorial/1_github_actions.md))
106
- - 命令行:无需写Python代码,简单易用([教程:使用命令行下载禁漫本子](./assets/docs/sources/tutorial/2_command_line.md))
107
- - Python代码:最本质、最强大的使用方式,需要你有一定的python编程基础
108
- - 支持**网页端**和**移动端**两种客户端实现,可通过配置切换(**移动端不限ip兼容性好,网页端限制ip地区但效率高**)
109
- - 支持**自动重试和域名切换**机制
110
- - **多线程下载**(可细化到一图一线程,效率极高)
111
- - **可配置性强**
112
-
113
- - 不配置也能使用,十分方便
114
- - 配置可以从配置文件生成,支持多种文件格式
115
- - 配置点有:`请求域名` `客户端实现` `是否使用磁盘缓存` `同时下载的章节/图片数量` `图片格式转换` `下载路径规则` `请求元信息(headers,cookies,proxies)`
116
-
117
- - **可扩展性强**
118
-
119
- - 支持自定义本子/章节/图片下载前后的回调函数
120
- - 支持自定义类:`Downloader(负责调度)` `Option(负责配置)` `Client(负责请求)` `实体类`等
121
- - 支持自定义日志、异常监听器
122
- - **支持Plugin插件,可以方便地扩展功能,以及使用别人的插件,目前内置插件有**:
123
- - `登录插件`
124
- - `硬件占用监控插件`
125
- - `只下载新章插件`
126
- - `压缩文件插件`
127
- - `下载特定后缀图片插件`
128
- - `发送QQ邮件插件`
129
- - `日志主题过滤插件`
130
- - `自动使用浏览器cookies插件`
131
- - `jpg图片合成为一个pdf插件`
132
- - `导出收藏夹为csv文件插件`
133
-
134
- ## 使用小说明
135
-
136
- * Python >= 3.7
137
- * 个人项目,文档和示例会有不及时之处,可以Issue提问
138
-
139
- ## 项目文件夹介绍
140
-
141
- * .github:GitHub Actions配置文件
142
- * assets:存放一些非代码的资源文件
143
-
144
- * docs:项目文档
145
- * option:存放配置文件
146
-
147
- * src:存放源代码
148
-
149
- * jmcomic:`jmcomic`模块
150
-
151
- * tests:测试目录,存放测试代码,使用unittest
152
- * usage:用法目录,存放示例/使用代码
153
-
154
- ## 感谢以下项目
155
-
156
- ### 图片分割算法代码+禁漫移动端API
157
-
158
- [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=tonquer&repo=JMComic-qt)](https://github.com/tonquer/JMComic-qt)
File without changes
File without changes
File without changes
File without changes
File without changes