diff --git a/.gitignore b/.gitignore index 5990fab5c..56502f4ba 100644 --- a/.gitignore +++ b/.gitignore @@ -161,4 +161,5 @@ cython_debug/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -.idea/ \ No newline at end of file +.idea/ +.agent \ No newline at end of file diff --git a/README.md b/README.md index ba488da9e..2529466dd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@

Python API for JMComic

+ +

+ 简体中文 • + English • + 日本語 • + 한국어 +

+

提供 Python API 访问禁漫天堂(网页端 & 移动端),集成 GitHub Actions 下载器🚀

@@ -56,7 +64,7 @@ * 通过pip官方源安装(推荐,并且更新也是这个命令) ```shell - pip install jmcomic -i https://pypi.org/project -U + pip install jmcomic -U ``` * 通过源代码安装 @@ -175,14 +183,21 @@ jmcomic 123 - `硬件占用监控插件` - `只下载新章插件` - `压缩文件插件` + - `客户端代理插件` - `下载特定后缀图片插件` - `发送QQ邮件插件` - - `自动使用浏览器cookies插件` + - `日志主题过滤插件` + - `自动获取浏览器cookies插件` - `导出收藏夹为csv文件插件` - `合并所有图片为pdf文件插件` - `合并所有图片为长图png插件` - - `重复文件检测删除插件` - `网页观看本地章节插件` + - `订阅更新插件` + - `小章节跳过插件` + - `重复文件检测删除插件` + - `路径字符串替换插件` + - `高级重试插件` + - `封面下载插件` ## 使用小说明 diff --git a/assets/docs/mkdocs.yml b/assets/docs/mkdocs.yml index 42869acb5..27c716af5 100644 --- a/assets/docs/mkdocs.yml +++ b/assets/docs/mkdocs.yml @@ -32,6 +32,33 @@ theme: - search.share - navigation.tabs - navigation.top +nav: + - 首页: index.md + - 版本更新计划: roadmap.md + - 配置文件指南: option_file_syntax.md + - Api 文档: + - api/client.md + - api/command-line.md + - api/config.md + - api/download.md + - api/entity.md + - api/option.md + - api/plugin.md + - api/toolkit.md + - 使用教程: + - tutorial/0_common_usage.md + - tutorial/1_github_actions.md + - tutorial/2_command_line.md + - tutorial/4_module_custom.md + - tutorial/5_filter.md + - tutorial/6_plugin.md + - tutorial/7_advance.md + - tutorial/8_pick_domain.md + - tutorial/9_custom_download_dir_name.md + - tutorial/10_export_favorites.md + - tutorial/11_log_custom.md + - tutorial/12_domain_strategy.md + plugins: - search - mkdocstrings: diff --git a/assets/docs/sources/api/plugin.md b/assets/docs/sources/api/plugin.md index 732963a99..ef833dc9b 100644 --- a/assets/docs/sources/api/plugin.md +++ b/assets/docs/sources/api/plugin.md @@ -3,4 +3,4 @@ ::: jmcomic.jm_plugin options: filters: - - Plugin$ \ No newline at end of file + - (Plugin$|JmOptionPlugin|^Plugin) \ No newline at end of file diff --git a/assets/docs/sources/index.md b/assets/docs/sources/index.md index 1f9bf2f8c..16783b1d1 100644 --- a/assets/docs/sources/index.md +++ b/assets/docs/sources/index.md @@ -7,7 +7,7 @@ > > 你可以通过简单的几行Python代码,访问禁漫的接口,以及下载禁漫的本子。 > -> [查看项目更新计划](TODO.md) +> [查看项目更新计划](roadmap.md) ## 一图看懂 JMComic 工具生态 diff --git a/assets/docs/sources/option_file_syntax.md b/assets/docs/sources/option_file_syntax.md index 75497b708..42d4b8542 100644 --- a/assets/docs/sources/option_file_syntax.md +++ b/assets/docs/sources/option_file_syntax.md @@ -42,6 +42,14 @@ client: # retry_times: 请求失败重试次数,默认为5 retry_times: 5 + # cache: 是否开启客户端级别的缓存,用于缓存已经请求过的元数据(如本子详情、搜索结果等),减少重复网络请求。 + # 支持以下几种配置值(详见 CacheRegistry 类): + # - null 或 false (默认值): 关闭缓存,每次请求都重新发起。 + # - true 或 level_option: 开启 option 级别缓存,同一个 option 派生的所有 client 共享同一份缓存。 + # - level_client: 开启 client 级别缓存,每个 client 维持各自独立的缓存字典,互不干扰。 + cache: null + + # postman: 请求配置 postman: meta_data: @@ -137,6 +145,7 @@ dir_rule: plugins: after_init: - plugin: usage_log # 实时打印硬件占用率的插件 + # log: false # 选填。所有的插件都可以配置 `log: false` 以关闭该插件执行时产生的日志输出,默认是 true kwargs: interval: 0.5 # 间隔时间 enable_warning: true # 占用过大时发出预警 diff --git a/assets/docs/sources/TODO.md b/assets/docs/sources/roadmap.md similarity index 97% rename from assets/docs/sources/TODO.md rename to assets/docs/sources/roadmap.md index 0b1252897..df8d8ce70 100644 --- a/assets/docs/sources/TODO.md +++ b/assets/docs/sources/roadmap.md @@ -1,4 +1,4 @@ -# 版本更新计划 +# 项目更新计划 | 版本范围 | 更新计划 | |:--------:|:-----------------------------------------:| diff --git a/assets/docs/sources/tutorial/0_common_usage.md b/assets/docs/sources/tutorial/0_common_usage.md index 2b5be939d..23514dd9d 100644 --- a/assets/docs/sources/tutorial/0_common_usage.md +++ b/assets/docs/sources/tutorial/0_common_usage.md @@ -228,6 +228,7 @@ page: JmCategoryPage = cl.month_ranking(1) page: JmCategoryPage = cl.week_ranking(1) # 循环获取分页,使用 cl.categories_filter_gen +# 基础用法:简单的 for 循环 for page in cl.categories_filter_gen(page=1, # 起始页码 # 下面是分类参数 time=JmMagicConstants.TIME_WEEK, @@ -237,6 +238,22 @@ for page in cl.categories_filter_gen(page=1, # 起始页码 for aid, atitle in page: print(aid, atitle) +# 高级用法:使用 generator 的 send() 方法在遍历中途动态修改查询条件 +# 注意:必须用 while 循环手动接收 send() 的返回值,避免在 for 循环内调用 send() 跳过分页 +generator = cl.categories_filter_gen(page=1, time=JmMagicConstants.TIME_WEEK) +try: + page = next(generator) # 预先启动生成器 + while True: + # 打印第一页 + for aid, atitle in page: + print(aid, atitle) + + # 假设我们只想看前一页,下一页想换一个排序方式 + # 调用 send 传入包含新参数的 dict 即可覆盖原来的查询条件 + page = generator.send({"order_by": JmMagicConstants.ORDER_BY_LATEST}) +except StopIteration: + pass + ``` ## 高级搜索(分类/副分类) @@ -281,6 +298,19 @@ for page in html_cl.search_gen(search_query='mana', # 打印page内容 for aid, atitle in page.iter_id_title(): print(aid, atitle) + +# 高级用法:使用 generator 的 send() 方法进行手动翻页或修改查询条件 +generator = html_cl.search_gen('mana') +try: + page = next(generator) + while True: + for aid, atitle in page.iter_id_title(): + print(aid, atitle) + + # 可直接动态传参改变搜索条件,例如下一页换成搜索 'nana' + page = generator.send({"search_query": 'nana'}) +except StopIteration: + pass ``` diff --git a/assets/docs/sources/tutorial/12_domain_strategy.md b/assets/docs/sources/tutorial/12_domain_strategy.md new file mode 100644 index 000000000..48f944176 --- /dev/null +++ b/assets/docs/sources/tutorial/12_domain_strategy.md @@ -0,0 +1,114 @@ +# 域名与重试策略 + +访问禁漫时,常遇到网络不畅或默认域名失效的情况。jmcomic 提供了静态配置、动态获取和重试插件机制来应对。 + +下面演示如何配置和获取稳定或最新的可用域名。 + +## 1. 静态配置域名 + +如果你的网络环境下,某些域名(如 `18comic.vip`, `18comic.org`)可以稳定访问,最直接的方式是在配置文件中写死这些域名。 + +```yaml +# option.yml 示例 +client: + impl: html + domain: + html: + - 18comic.vip + - 18comic.org +``` + +```python +from jmcomic import * + +# 通过配置文件构建并获取配置好的 Option 和 Client +# Option会加载上面的域名列表,在请求时如果第一个域名失败,会自动重试列表中的下一个域名。 +op = create_option('option.yml') +cl = op.new_jm_client() +``` + +## 2. 动态获取域名 + +如果静态配置的域名失效,可以通过调用以下内置的 API 动态获取最新的禁漫域名。 + +> **注意**: +> 默认情况下,以下 API 在请求外网时会自动使用系统代理。但在 Linux 服务器等无全局代理的环境中,如果需要手动指定代理,你可以自行创建一个配置了 proxy 的 postman 对象并作为参数传入: +> `JmModuleConfig.get_html_domain_all(postman=JmModuleConfig.new_postman(proxies={'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'}))` + + +### 2.1 抓取全部可用域名(推荐) + +通过请求禁漫的官方发布页,获取所有公告的最新的网页端域名列表。 + +```python +from jmcomic import * + +# 获取全量域名列表 +domain_list = JmModuleConfig.get_html_domain_all() +print(f"全量域名列表:{domain_list}") + +# 将获取到的域名替换掉全局默认域名列表 +JmModuleConfig.DOMAIN_HTML_LIST = domain_list + +op = create_option('option.yml') +# 新建的 Client 会默认使用刚刚更新的 DOMAIN_HTML_LIST +cl = op.new_jm_client() +``` + +### 2.2 通过 GitHub 兜底获取域名 + +如果连禁漫的发布页本身都被墙了无法访问,可以请求禁漫官方放在 GitHub 的仓库来解析最新域名。 + +```python +from jmcomic import * + +# 该请求发往 github.com,在大多数常规网络中均能保持连通 +domains = JmModuleConfig.get_html_domain_all_via_github() + +op = JmOption.default() +# 可以结合重试机制,允许失败时轮换多次 +op.client.retry_times = 3 + +# 应用域名池新建包含该域名的 Client (记得指定 impl='html') +# 将新建的 client 赋值回 op,使其在后续的下载中生效 +op.client = op.new_jm_client(domain_list=domains, impl='html') + +download_album('438696', op) +``` + +### 2.3 获取单个跳转域名 + +除了获取全部域名,也可以通过访问永久跳转页获取单个重定向用的新域名。 + +```python +from jmcomic import * + +# 获取当前可用的单一网页端域名 +domain = JmModuleConfig.get_html_domain() + +op = JmOption.default() +op.client = op.new_jm_client(domain_list=[domain], impl='html') +``` + + +## 3. 使用高级重试插件(AdvancedRetryPlugin) + +默认的机制是在单次请求报错时,按顺序尝试数组内的下一个域名。 +如果经常遇到连接断开或超时,可以使用 `advanced_retry` 插件。该插件提供: +- 记录历史失败次数 +- 限制单个域名的最大失败次数(超过则拉黑废弃) +- 对列表循环多轮尝试等容错机制 + +**在 option.yml 中配置启用:** + +```yaml +plugins: + after_init: + - plugin: advanced_retry # 声明并开启高级重试插件 + kwargs: + retry_config: + retry_rounds: 3 # 整个域名数组支持轮询尝试的圈数 + retry_domain_max_times: 5 # 单个域名允许的最大失败次数 +``` + +配置后,用该 option 构建的 Client 在下载和请求时,就会自动切入高级容错策略。 diff --git a/assets/docs/sources/tutorial/4_module_custom.md b/assets/docs/sources/tutorial/4_module_custom.md index bc015eedb..2f16013a2 100644 --- a/assets/docs/sources/tutorial/4_module_custom.md +++ b/assets/docs/sources/tutorial/4_module_custom.md @@ -2,16 +2,6 @@ -下方所有函数都省略了如下的导包和准备代码 - -```python -from jmcomic import * -option = JmOption.default() -client: JmcomicClient = option.build_jm_client() -``` - - - ## 自定义下载前后的回调函数 ```python @@ -151,8 +141,8 @@ def custom_jm_log(): """ # jmcomic模块在运行过程中会使用 jm_log() 这个函数进行打印信息 - # jm_log() 这个函数 最后会调用 JmModuleConfig.log_executor 函数 - # 你可以写一个自己的函数,替换 JmModuleConfig.log_executor,实现自定义log + # jm_log() 这个函数 最后会调用 JmModuleConfig.EXECUTOR_LOG 函数 + # 你可以写一个自己的函数,替换 JmModuleConfig.EXECUTOR_LOG,实现自定义log # 1. 自定义log函数 def my_log(topic: str, msg: str): @@ -164,11 +154,12 @@ def custom_jm_log(): pass # 2. 让my_log生效 - JmModuleConfig.log_executor = my_log + JmModuleConfig.EXECUTOR_LOG = my_log ``` + ## 自定义异常监听器/回调 ```python diff --git a/assets/docs/sources/tutorial/5_filter.md b/assets/docs/sources/tutorial/5_filter.md index 90f87dff6..b425f8dd2 100644 --- a/assets/docs/sources/tutorial/5_filter.md +++ b/assets/docs/sources/tutorial/5_filter.md @@ -13,12 +13,19 @@ filter(过滤器)是v2.1.12新引入的机制, ... 2. 让你的class生效,使用如下代码: - JmModuleConfig.CLASS_DOWNLOADER = MyDownloader + # 如果是旧版本写法:JmModuleConfig.CLASS_DOWNLOADER = MyDownloader + # 推荐新版本写法: + MyDownloader.use() 3. 照常使用下载api: download_album(xxx, option) ``` +> [!WARNING] +> **使用 Filter 机制的两大陷阱** +> 1. `do_filter` 的返回值**必须支持 `len()`**(比如返回 list、tuple 或原本的 Entity 本身),因为底层代码会使用 `len(iter_objs)` 约束并发线程数。如果你过滤后没有任何内容,**请返回空列表 `[]`** 而不是 `None`。 +> 2. 一旦 `JmDownloader` 使用了 filter 机制屏蔽了任意一个本子/章节/图片的下载,该下载器的 **`downloader.all_success` 属性将永远为 `False`**! + * 下面的示例只演示步骤1 diff --git a/assets/docs/sources/tutorial/6_plugin.md b/assets/docs/sources/tutorial/6_plugin.md index 733b196a6..bd8ea92cb 100644 --- a/assets/docs/sources/tutorial/6_plugin.md +++ b/assets/docs/sources/tutorial/6_plugin.md @@ -119,3 +119,42 @@ from jmcomic import create_option option = create_option('xxx') ``` +## 高级:异步插件生命周期控制 + +如果你编写的插件是异步的(比如启动了新线程处理任务),此时主程序可能会先于插件执行完毕而退出。为解决此问题,`JmOptionPlugin` 提供了注册等待挂起的功能: + +```python +import threading +import time +from jmcomic import JmOptionPlugin, JmModuleConfig + +class MyAsyncPlugin(JmOptionPlugin): + plugin_key = 'my_async_plugin' + + def invoke(self, **kwargs) -> None: + # 1. 告诉 option 有一个异步插件正在运行,请主线程在退出前关掉我或等我 + self.enter_wait_list() + self.is_running = True + + # 2. 启动一个新的线程... + self.thread = threading.Thread(target=self.do_async_work) + self.thread.start() + + def do_async_work(self): + while self.is_running: + print('异步工作运行中...') + time.sleep(1) + + def wait_until_finish(self): + # 3. 覆写 wait_until_finish 方法,实现优雅停机 / 强制阻塞等待的逻辑 + # 主程序在结束时必定会调用它(如果此前挂起了该插件) + self.is_running = False # 发送停机信号 + if hasattr(self, 'thread') and self.thread.is_alive(): + self.thread.join() # 阻塞直到线程安全退出 + +JmModuleConfig.register_plugin(MyAsyncPlugin) +``` + +这样,程序在所有任务执行完退出的最后一刻,会通过 `option.wait_all_plugins_finish()` 遍历所有调用过 `enter_wait_list()` 挂起的插件,并调用其 `wait_until_finish()` 方法。只要你在该方法中实现了停机信号或阻塞等待的发送,主线程就会等待你的异步逻辑全部安全并优雅地退出。 + + diff --git a/assets/docs/sources/tutorial/9_custom_download_dir_name.md b/assets/docs/sources/tutorial/9_custom_download_dir_name.md index 9d22bd5c4..459ed3e1e 100644 --- a/assets/docs/sources/tutorial/9_custom_download_dir_name.md +++ b/assets/docs/sources/tutorial/9_custom_download_dir_name.md @@ -53,10 +53,13 @@ D:/a/b/c/ddd/00003.webp 除了title,你还可以写什么?其实Ptitle表示的是jmcomic里的章节实体类 JmPhotoDetail 的属性。 -最终能写什么,取决于JmPhotoDetail有哪些属性,建议使用IDE来获知这些属性,不过这需要你懂一些python基础。 +最终能写什么,取决于 JmPhotoDetail 有哪些属性。建议您查阅源码或者使用 `get_properties_dict()` 方法在控制台打印并探索该实体类的所有可用字段。 除了Pxxx,你还可以写Axxx,表示这个章节所在的本子的属性xxx,详见本子实体类 JmAlbumDetail。 +> [!TIP] +> **探索更多复杂的路径组合语法(如连字、加括号组合等)** +> 除了单纯的属性拼接,`dir_rule.rule` 还支持带括号组合与连接符的高阶语法,比如使用 `(JM{Aid}-{Pindex})-{Pname}` 这种 f-string 和普通符号交织的写法。 ## 1.1 简繁体统一(normalize_zh) diff --git a/assets/readme/README-en.md b/assets/readme/README-en.md new file mode 100644 index 000000000..89cb523d4 --- /dev/null +++ b/assets/readme/README-en.md @@ -0,0 +1,227 @@ + +
+

Python API for JMComic

+ +

+ 简体中文 • + English • + 日本語 • + 한국어 +

+ +

+ Provide Python API to access JMComic (Web & Mobile), integrates GitHub Actions downloader🚀 +

+ +[![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/hect0x7) +[![Stars](https://img.shields.io/github/stars/hect0x7/JMComic-Crawler-Python?color=orange&label=stars&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/stargazers) +[![Forks](https://img.shields.io/github/forks/hect0x7/JMComic-Crawler-Python?color=green&label=forks&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/forks) +[![GitHub latest releases](https://img.shields.io/github/v/release/hect0x7/JMComic-Crawler-Python?color=blue&label=version)](https://github.com/hect0x7/JMComic-Crawler-Python/releases/latest) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/jmcomic?style=flat&color=hotpink)](https://pepy.tech/projects/jmcomic) +[![Licence](https://img.shields.io/github/license/hect0x7/JMComic-Crawler-Python?color=red)](https://github.com/hect0x7/JMComic-Crawler-Python) + +
+ + + + +> This project encapsulates a Python API for crawling JM. +> +> With a few simple lines of Python code, you can download albums from JM to your local machine, with properly processed images. +> +> **Friendly Prompt: Cherish JM. In order to reduce the pressure on JM servers, please do not download too many albums at once 🙏🙏🙏.** + +[【Guide】Tutorial: Downloading JM Albums using GitHub Actions](../docs/sources/tutorial/1_github_actions.md) + +[【Guide】Tutorial: Exporting and downloading your JM favorites data](../docs/sources/tutorial/10_export_favorites.md) + + +![introduction.jpg](../docs/sources/images/introduction.jpg) + + +## Introduction + +The core function of this project is to download albums. + +Based on this, an easy-to-use, highly extensible framework is designed to meet various download requirements. + +Currently, the core functions are relatively stable, and the project is in the maintenance phase. + +In addition to downloading, other JM interfaces are also implemented on demand. Existing features: + +- Login +- Search albums (supports all search parameters) +- Image downloading and decoding +- Categories/Rankings +- Album/Chapter details +- Personal favorites +- Interface encryption and decryption (for the APP API) + +## Installation Guide + +> ⚠ If you have not installed Python, you must install Python before executing the following steps. Version >= 3.7 is required ([Download from Python Official Site](https://www.python.org/downloads/)). + +* Install via official pip source (recommended, the update command is identical) + + ```shell + pip install jmcomic -U + ``` +* Install from source code + + ```shell + pip install git+https://github.com/hect0x7/JMComic-Crawler-Python + ``` + +## Quick Start + +### 1. Downloading an album + +All you need is the following code to download all chapter images of the album `JM123`: + +```python +import jmcomic # Import this module, you need to install it first. +jmcomic.download_album('123') # Pass the ID of the album to download the entire album locally. +``` + +The `download_album` method above also accepts an `option` parameter to control the configuration, which includes JM domain names, network proxies, image format conversions, plugins, and more. + +You might need these options. It is recommended to create an option instance from a configuration file and use it to download albums, as shown in the next section: + +### 2. Using option for advanced downloading + +1. First, create a configuration file, let's say `option.yml` + + This file uses a specific format, please refer to the documentation → [Configuration File Guide](../docs/sources/option_file_syntax.md) + + Here is a demonstration. Assuming you want to convert the downloaded images into `png` format, you should write the following into `option.yml`: + +```yml +download: + image: + suffix: .png # This option converts the downloaded image to png format +``` + +2. Secondly, run the following Python code + +```python +import jmcomic + +# Create configuration object +option = jmcomic.create_option_by_file('Path to your configuration file, e.g. D:/option.yml') +# Download the album using the option configured +jmcomic.download_album(123, option) +# Equivalent to: option.download_album(123) +``` + +### 3. Using the Command Line +> If your only goal is to download albums, using the command line is simpler and more straightforward. +> +> For example, on Windows, press `Win + R`, enter `jmcomic xxx`, and you can download the album. + +Examples: + +Command to download album 123: + +```sh +jmcomic 123 +``` + +Command to download chapter 456 of album 123: +```sh +jmcomic 123 p456 +``` + +The command-line mode also supports custom options. You can use environment variables or command line arguments: + +a. Specify the option file path via `--option` argument + +```sh +jmcomic 123 --option="D:/a.yml" +``` + +b. Set the environment variable `JM_OPTION_PATH` to the option file path (recommended) + +> Please Google how to configure environment variables. By using powershell: `setx JM_OPTION_PATH "D:/a.yml"` (Requires a restart to take effect). + +```sh +jmcomic 123 +``` + + + +## Advanced Usage + +Please check the documentation homepage → [jmcomic.readthedocs.io (Chinese language)](https://jmcomic.readthedocs.io/zh-cn/latest) + +*(Tip: jmcomic provides many options. For most download requirements, you can find a corresponding configuration or plugin setup.)* + +## Key Features + +- **Bypass Cloudflare anti-bot mechanisms** +- **Implement the latest decryption logic for the JM APP API (1.6.3)** +- Multiple usages: + + - GitHub Actions: Enter the album ID directly on the webpage to download ([Tutorial: Download JM Albums using GitHub Actions](../docs/sources/tutorial/1_github_actions.md)) + - Command Line: No need to write Python code, easy to use ([Tutorial: Download JM Albums by Command Line](../docs/sources/tutorial/2_command_line.md)) + - Python Code: The most powerful usage, requiring basic Python programming knowledge +- Supports both **Web** and **Mobile** implementations, switchable via configuration (**Mobile is IP restriction-free and very compatible, Web restricts some IP regions but offers higher efficiency**) +- Built-in **auto-retry and domain switching** mechanisms +- **Multi-threaded downloading** (can be fine-tuned to one-thread-per-image, greatly boosting speed) +- **Highly configurable** + + - Can work smoothly out of the box without configurations + - Supported formats to generate `Option` instances + - Configurable items include: `Domains` `Clients` `Disk Caching` `Concurrent chapters/images downloads` `Format Conversions` `Path rules` `Request Meta (headers, cookies, proxies)` `Simplified/Traditional Chinese Conversion`, etc. +- **Highly Extensible** + + - Supports custom callbacks before/after downloading albums/chapters/images + - Customizable objects: `Downloader` `Option` `Client` `Entities`, etc. + - Supports custom logging and exception listener mechanics + - **Embedded with powerful Plugins** to easily extend features or inject others': + - `Login Plugin` + - `Hardware usage monitor plugin` + - `Filter-new-chapter plugin` + - `Zip-files plugin` + - `Client proxy plugin` + - `Specific image suffix format downloader` + - `Send via QQ Mail plugin` + - `Log topic filter plugin` + - `Auto fetch browser cookies plugin` + - `Export favorites to CSV plugin` + - `Merge images into PDF plugin` + - `Merge images into Long png plugin` + - `Local chapter web-viewer plugin` + - `Subscribe album update plugin` + - `Skip small chapters plugin` + - `Duplicate detection and deletion plugin` + - `Path string replacement plugin` + - `Advanced retry plugin` + - `Download cover plugin` + +## Prerequisites + +* Python >= 3.7. Version 3.9+ is highly recommended because `jmcomic`'s dependencies may not perfectly support prior versions. +* Since this is a personal project, the documentation/examples may occasionally be out of sync. Please feel free to open an Issue for any clarifications. + +## Directory Structure + +* `.github`: GitHub Actions configuration files +* `assets`: Resources aside from pure code + * `docs`: Documentation + * `option`: Test/example configurations +* `src`: Main code base + * `jmcomic`: Core `jmcomic` package +* `tests`: Unit tests relying on `unittest` +* `usage`: Examples of usage implementations + +## Acknowledgments + +### Image Segmentation logic + JM Mobile APIs Support + + + + + + Repo Card + + diff --git a/assets/readme/README-jp.md b/assets/readme/README-jp.md new file mode 100644 index 000000000..5aab7e21a --- /dev/null +++ b/assets/readme/README-jp.md @@ -0,0 +1,226 @@ + +
+

Python API for JMComic

+ +

+ 简体中文 • + English • + 日本語 • + 한국어 +

+ +

+ JMComicへアクセスするためのPython API(Web版&モバイル版)を提供し、GitHub Actionsダウンローダーも統合しています🚀 +

+ +[![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/hect0x7) +[![Stars](https://img.shields.io/github/stars/hect0x7/JMComic-Crawler-Python?color=orange&label=stars&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/stargazers) +[![Forks](https://img.shields.io/github/forks/hect0x7/JMComic-Crawler-Python?color=green&label=forks&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/forks) +[![GitHub latest releases](https://img.shields.io/github/v/release/hect0x7/JMComic-Crawler-Python?color=blue&label=version)](https://github.com/hect0x7/JMComic-Crawler-Python/releases/latest) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/jmcomic?style=flat&color=hotpink)](https://pepy.tech/projects/jmcomic) +[![Licence](https://img.shields.io/github/license/hect0x7/JMComic-Crawler-Python?color=red)](https://github.com/hect0x7/JMComic-Crawler-Python) + +
+ + + + +> 本プロジェクトは、JMのクローラー用のPython APIをカプセル化したものです。 +> +> 数行のPythonコードだけで、JM上のアルバムをローカルへダウンロードすることができます。ダウンロードされた画像は完全に処理済みです。 +> +> **ご案内:JMのサーバー負荷を軽減するため、一度に大量のダウンロードは控えてください 🙏🙏🙏** + +[【ガイド】チュートリアル:GitHub Actionsを使ってダウンロードする](../docs/sources/tutorial/1_github_actions.md) + +[【ガイド】チュートリアル:お気に入りのデータをエクスポートしてダウンロードする](../docs/sources/tutorial/10_export_favorites.md) + + +![introduction.jpg](../docs/sources/images/introduction.jpg) + + +## プロジェクトの紹介 + +本プロジェクトのコア機能は「アルバムのダウンロード」です。 + +これを基に、使いやすく、拡張性が高く、また特殊なダウンロード要求にも対応できるフレームワークを設計しました。 + +現在、主要機能の実装は比較的安定しており、プロジェクトはメンテナンス段階にあります。 + +ダウンロード機能以外にも、必要に応じて他のJMインターフェースも実装しています。既存の機能は以下の通りです: + +- ログイン +- アルバム検索(すべての検索条件をサポート) +- 画像のダウンロードおよびデコード +- カテゴリ / ランキング +- アルバム / 各チャプター(エピソード)の詳細 +- 個人のお気に入り +- インターフェースの暗号化・復号化(APP API) + +## インストール手順 + +> ⚠ まだPythonをインストールしていない場合は、先にPythonのインストールをお願いします。要件: Python >= 3.7 ([公式のPythonページからダウンロード](https://www.python.org/downloads/))。 + +* 公式 pip ソースからインストール(推奨。アップデートもこのコマンドを使用します) + + ```shell + pip install jmcomic -U + ``` +* ソースコードからインストール + + ```shell + pip install git+https://github.com/hect0x7/JMComic-Crawler-Python + ``` + +## クイックスタート + +### 1. アルバムのダウンロード方法 + +以下の簡単なコードを使用するだけで、アルバム `JM123` のすべてのチャプター画像をダウンロードできます。 + +```python +import jmcomic # モジュールのインポート(事前にインストール必須) +jmcomic.download_album('123') # ダウンロードしたいアルバムのIDを渡し、アルバム全体をローカルにダウンロード +``` + +上記の `download_album` メソッドには `option` パラメータが用意されており、JMのドメイン名、ネットワークプロキシ、画像のフォーマット変換、プラグインなどのダウンロード設定を管理できます。 + +これらの設定項目が必要な場合は、設定ファイルから `option` オブジェクトを作成し、それを使用してアルバムをダウンロードすることをお勧めします。次の章をご参照ください。 + +### 2. Option 設定を利用してアルバムをダウンロード + +1. まず、設定ファイルを作成します。ファイル名を `option.yml` と仮定します。 + + このファイルには固有の記述形式があります。こちらのドキュメントを参照してください → [設定ファイルガイド](../docs/sources/option_file_syntax.md) + + 以下は簡単なデモです。ダウンロードした画像を png 形式に変換したい場合、`option.yml` に以下のように書き込みます。 + +```yml +download: + image: + suffix: .png # ダウンロードした画像をpng形式に変換する設定 +``` + +2. 続いて、以下の Python コードを実行します。 + +```python +import jmcomic + +# 設定オブジェクトの作成 +option = jmcomic.create_option_by_file('あなたの設定ファイルのパス、例: D:/option.yml') +# option オブジェクトを使用してアルバムをダウンロード +jmcomic.download_album(123, option) +# 等価の記述: option.download_album(123) +``` + +### 3. コマンドラインの使用 +> 単にアルバムをダウンロードするだけなら、コマンドラインを使用する方が前述の方法よりもシンプルかつ直接的です。 +> +> 例えば、Windowsでは `win+r` キーを押して `jmcomic xxx` と入力するだけでダウンロードできます。 + +例: + +アルバム123をダウンロードするコマンド + +```sh +jmcomic 123 +``` +アルバム123のチャプター456をダウンロードするコマンド +```sh +jmcomic 123 p456 +``` + +コマンドラインモードも独自の Option 設定をサポートしています。環境変数またはコマンドライン引数を利用できます。 + +a. コマンドライン引数 `--option` 経由で設定ファイルのパスを指定 + +```sh +jmcomic 123 --option="D:/a.yml" +``` + +b. 環境変数 `JM_OPTION_PATH` にオプションファイルのパスを設定(推奨) + +> 環境変数の設定方法は Google 等で検索してください。または powershell コマンドを使用: `setx JM_OPTION_PATH "D:/a.yml"` (再起動後に反映されます) + +```sh +jmcomic 123 +``` + + + +## 高度な利用方法 + +ドキュメントのトップページをご覧ください → [jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/zh-cn/latest) + +(ヒント: jmcomicは多数のダウンロード設定項目を提供しています。大部分のダウンロード要件については、関連する項目やプラグインを探すことで実現できる可能性が高いです。) + +## プロジェクトの特色 + +- **Cloudflareのボット対策のバイパス機能** +- **JM APP インターフェースの最新暗号化アルゴリズムを実装 (1.6.3)** +- 様々な利用方法のサポート: + + - GitHub Actions: Web上でアルバムIDを直接入力してダウンロード([チュートリアル:GitHub Actions経由でのダウンロード](../docs/sources/tutorial/1_github_actions.md)) + - コマンドライン: Pythonのコード不要、簡単操作([チュートリアル:コマンドラインからのダウンロード](../docs/sources/tutorial/2_command_line.md)) + - Pythonコード: 最も本質的かつ強力な利用法(一定のPythonプログラミング知識が必要です) +- **Web版**と**モバイル版**の2つのクライアントをサポートし、設定から簡単に切り替え可能(**モバイル版はIP制限がなく圧倒的な互換性を持ち、Web版はエリア制限があるものの高効率**) +- **自動再試行およびドメイン切り替えメカニズム**のサポート +- **マルチスレッドダウンロード**(各画像ごとにスレッドの細分化が可能。驚異的な効率) +- **強力な設定オプション** + + - カスタマイズ無しでもシームレスに動作。 + - 設定ファイルからのOption生成・さまざまなフォーマットに対応。 + - 設定可能な要素一覧:`リクエストドメイン` `クライアントの実装` `ディスクキャッシュの利用状況` `同時にダウンロードするチャプター/画像の数` `画像フォーマット変換` `ダウンロードパスの規則構成` `メタ情報(headers, cookies, proxies)` `簡体字/繁体字(中国語)の変換` など。 +- **強力な拡張性** + + - アルバム/チャプター/画像ダウンロード前後のコールバック関数のカスタムをサポート + - 各種クラスのカスタマイズ対応: `Downloader(スケジューリング担当)` `Option(設定担当)` `Client(リクエスト担当)` `エンティティクラス` など + - カスタムログ出力・例外リスナーの実装 + - **プラグイン(Plugin)システムにより、機能を容易に拡張したり、他者の製作物を利用可能**。組み込みプラグインの一例: + - `ログインプラグイン` + - `ハードウェアリソース監視プラグイン` + - `最新チャプターのみダウンロードするプラグイン` + - `ファイル圧縮(Zip)プラグイン` + - `クライアントプロキシプラグイン` + - `特定拡張子の画像ダウンロードプラグイン` + - `QQメール送信プラグイン` + - `ログトピックフィルタプラグイン` + - `ブラウザのクッキーを自動で抽出するプラグイン` + - `お気に入りをCSV形式でエクスポートするプラグイン` + - `すべての画像を1つのPDFファイルに結合するプラグイン` + - `すべての画像を縦長の1つのPNGファイルに結合するプラグイン` + - `Webブラウザからローカルのチャプターを閲覧するプラグイン` + - `アルバム更新購読プラグイン` + - `画像数の少ないチャプターをスキップするプラグイン` + - `重複ファイルの検出・削除プラグイン` + - `パス文字列置換プラグイン` + - `高度な再試行プラグイン` + - `表紙ダウンロードプラグイン` + +## ご利用上の注意点 + +* Python >= 3.7 ですが、jmcomicの依存ライブラリが古いバージョンをサポートしない可能性があるため、3.9以上をお勧めします。 +* 個人のプロジェクトであるため、ドキュメントやサンプルコードの更新が遅れることがあります。ご不明な点はIssueにてご質問ください。 + +## ディレクトリ構造のご紹介 + +* `.github`: GitHub Actions 用の設定ファイル +* `assets`: コードやスクリプト以外のリソースファイル・画像類 + * `docs`: ドキュメントテキスト + * `option`: オプションファイルのサンプル・テンプレート +* `src`: ソースコード本体 + * `jmcomic`: `jmcomic` パッケージ +* `tests`: テスト環境(`unittest`を利用した構成) +* `usage`: 使い方・使用例を実装したスクリプト類 + +## 特別な感謝 + +### 画像分割と連結アルゴリズム + JMモバイル版APIの実装と参照 + + + + + + Repo Card + + diff --git a/assets/readme/README-kr.md b/assets/readme/README-kr.md new file mode 100644 index 000000000..ffea01101 --- /dev/null +++ b/assets/readme/README-kr.md @@ -0,0 +1,226 @@ + +
+

Python API for JMComic

+ +

+ 简体中文 • + English • + 日本語 • + 한국어 +

+ +

+ JMComic 접속을 위한 Python API(웹 및 모바일 지원), GitHub Actions 다운로더 통합 제공 🚀 +

+ +[![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/hect0x7) +[![Stars](https://img.shields.io/github/stars/hect0x7/JMComic-Crawler-Python?color=orange&label=stars&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/stargazers) +[![Forks](https://img.shields.io/github/forks/hect0x7/JMComic-Crawler-Python?color=green&label=forks&style=flat)](https://github.com/hect0x7/JMComic-Crawler-Python/forks) +[![GitHub latest releases](https://img.shields.io/github/v/release/hect0x7/JMComic-Crawler-Python?color=blue&label=version)](https://github.com/hect0x7/JMComic-Crawler-Python/releases/latest) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/jmcomic?style=flat&color=hotpink)](https://pepy.tech/projects/jmcomic) +[![Licence](https://img.shields.io/github/license/hect0x7/JMComic-Crawler-Python?color=red)](https://github.com/hect0x7/JMComic-Crawler-Python) + +
+ + + + +> 이 프로젝트는 JM을 크롤링하기 위한 Python API를 캡슐화한 것입니다. +> +> 몇 줄의 간단한 Python 코드만으로 JM의 앨범을 로컬로 원활하게 다운로드할 수 있으며, 이미지 또한 모두 처리된 상태입니다. +> +> **안내: JM 서버의 부하를 줄이기 위해 한 번에 너무 많은 앨범을 다운로드하지 말아주세요 🙏🙏🙏** + +[【가이드】튜토리얼: GitHub Actions를 사용하여 다운로드하기](../docs/sources/tutorial/1_github_actions.md) + +[【가이드】튜토리얼: 즐겨찾기 데이터를 내보내고 다운로드하기](../docs/sources/tutorial/10_export_favorites.md) + + +![introduction.jpg](../docs/sources/images/introduction.jpg) + + +## 프로젝트 소개 + +본 프로젝트의 핵심 기능은 앨범 다운로드입니다. + +이를 기반으로 사용하기 쉽고 확장성이 뛰어나며 일부 특수한 다운로드 요구를 충족할 수 있는 프레임워크가 설계되었습니다. + +현재 핵심 기능은 꽤 안정적으로 동작하며, 프로젝트는 유지보수 단계에 있습니다. + +다운로드 기능 외에도, 필요한 경우에 한해 추가적인 JM 인터페이스가 구현되어 있습니다. 기존 기능들은 아래와 같습니다: + +- 로그인 +- 앨범 검색 (모든 검색 매개변수 지원) +- 이미지 다운로드 및 복호화 +- 카테고리 / 랭킹 +- 앨범 / 챕터(에피소드) 세부 정보 +- 개인 즐겨찾기 +- 인터페이스 암호화 및 복호화 (APP API) + +## 설치 가이드 + +> ⚠ Python이 시스템에 설치되어 있지 않다면, 다음 단계를 진행하기 전에 반드시 Python을 먼저 설치해주시기 바랍니다. 필요 버전 >= 3.7 ([Python 공식 사이트에서 다운로드하기](https://www.python.org/downloads/)). + +* 공식 pip 저장소를 통한 설치 (추천. 업데이트 명령어도 동일합니다) + + ```shell + pip install jmcomic -U + ``` +* 소스코드를 이용한 설치 + + ```shell + pip install git+https://github.com/hect0x7/JMComic-Crawler-Python + ``` + +## 빠른 시작 + +### 1. 앨범 다운로드하기 + +아래의 간단한 코드를 사용하면 `JM123` 앨범의 모든 챕터 이미지를 다운로드할 수 있습니다: + +```python +import jmcomic # 이 모듈을 임포트합니다. 사전 설치 필요. +jmcomic.download_album('123') # 다운로드하려는 앨범의 ID를 함수에 넘겨 로컬에 저장합니다. +``` + +위에 보이는 `download_album` 메서드는 구성 항목을 제어하는 부가적인 `option` 매개변수를 지원합니다. (예: JM 도메인, 네트워크 프록시, 이미지 포맷 변환, 플러그인 등) + +사용자 환경에 맞게 이러한 구성 옵션이 필요할 수도 있습니다. 구성 파일로 옵션을 만들고 이를 사용하여 다운로드하는 것을 권장합니다. 아래의 챕터를 참고하세요: + +### 2. Option 설정을 사용하여 앨범 다운로드 + +1. 먼저 구성 파일을 하나 만듭니다. 이름은 자율이며, 예시로 `option.yml`을 만들어보겠습니다. + + 파일에는 특정한 구문 형식이 존재합니다. 문서를 참조해주세요 → [환경 설정 파일 안내](../docs/sources/option_file_syntax.md) + + 한 가지 데모를 보여드리자면, 다운로드한 이미지를 png 포맷으로 변환하고 싶으시다면 `option.yml`안에 아래와 비슷한 내용을 기입하면 됩니다: + +```yml +download: + image: + suffix: .png # 이 구성은 다운로드된 이미지를 png 로 변환하는데 쓰입니다. +``` + +2. 두 번째로, 아래의 Python 코드를 실행합니다. + +```python +import jmcomic + +# 환경 설정 객체를 생성합니다 +option = jmcomic.create_option_by_file('내 설정 파일 경로, 예: D:/option.yml') +# 생성된 option 객체를 통해 앨범을 다운로드합니다 +jmcomic.download_album(123, option) +# 동등한 사용법: option.download_album(123) +``` + +### 3. 커맨드라인 (명령줄) 사용법 +> 앨범만을 다운로드 하려면 위에서 말한 방법보다 이렇게 사용하는 것이 훨씬 편하고 직관적입니다. +> +> 예를 들어 윈도우에서는 단순하게 `Win+r` 단축키를 이용해 `jmcomic xxx` 를 타이핑하고 앨범을 즉시 내려받을 수 있습니다. + +예시: + +123번 앨범을 다운로드 하는 명령어 + +```sh +jmcomic 123 +``` +123번 앨범의 456번 챕터 이미지를 다운로드 하는 명령어 +```sh +jmcomic 123 p456 +``` + +커맨드라인 모드에서는 임의의 Option을 통한 커스텀 설정을 지원합니다. 환경변수나 명령어 인자를 설정할 수 있습니다: + +a. 명령줄 매개변수 `--option`을 사용해 파일 경로를 지정 + +```sh +jmcomic 123 --option="D:/a.yml" +``` + +b. 환경 변수 `JM_OPTION_PATH` 를 옵션 파일명으로 설정 (권장) + +> 환경 변수는 구글링을 통하거나 powershell 터미널에서 다음을 쳐서 만들 수 있습니다: `setx JM_OPTION_PATH "D:/a.yml"` 설정 후에는 다시 작동해야 적용이 됩니다. + +```sh +jmcomic 123 +``` + + + +## 활용법 + +자세한 활용 문서를 원하시면 문서 사이트로 접속하세요 → [jmcomic.readthedocs.io](https://jmcomic.readthedocs.io/zh-cn/latest) + +(힌트: jmcomic은 다양한 다운로드 설정 항목을 제공합니다. 대부분의 다운로드 요구 사항과 관련된 구성 항목 및 플러그인을 쉽게 찾을 수 있을 것입니다.) + +## 프로젝트의 특징 + +- **Cloudflare 크롤러 방지 수칙 우회** +- **금만(1.6.3) APP 인터페이스 최근의 암호화/복호화 알고리즘 완벽 지원** +- 다양한 사용 방법: + + - GitHub Actions: 웹페이지 내 바로 앨범 ID를 통하여 받을 수 있습니다. ([튜토리얼:GitHub Actions를 이용해 다운로드](../docs/sources/tutorial/1_github_actions.md)) + - 커맨드라인: 파이썬 코드를 짤 필요 없이 단순합니다. ([튜토리얼:명령줄을 이용해 다운로드](../docs/sources/tutorial/2_command_line.md)) + - Python 코드 구현: 가장 직관적이고 강력하며 최소한의 파이썬 기반 지식이 필요합니다. +- **웹 인터페이스** 및 **모바일 인터페이스** 지원. 간단한 구성을 통한 전환 지원. (**모바일 구동환경에서의 IP제한을 돌파하고 뛰어난 호환이 됩니다, 웹은 특정 지역에서 제약받지만 성능은 최고입니다.**) +- **자동 재접속(Retry) 및 도메인 전환 구조** 기본지원 +- **멀티스레드 다운로드** (1이미지 당 1스레드를 통한 극단적인 빠른 스피드) +- **강력한 구성 옵션** + + - 환경 구성 없이도 매우 편하게 즐길 수 있습니다. + - 각종 파일 포맷 종류 지원 + - 구성 가능 요소: `요청된 도메인 네임` `클라이언트 구현체` `디스크 캐시 사용 여부` `동시에 다운로드 할 파일의 개수` `포맷 바꾸기` `규칙적으로 이미지 저장하기` `요청용 메타데이터정보들(headers, cookies, proxies)` `중국어 간체/번체 변환` 등등 +- **자율성 확보 (Extensible)** + + - 챕터/이미지의 다운로드 전, 다운로드 후의 콜백 기능 및 커스텀 함수 동작. + - 여러 사용자 정의 클래스를 구성하도록 개방: `Downloader (스케줄 관리)` `Option (구성 관리)` `Client (요청 관리)` `Entity 생성` 및 등등. + - 사용자 맞춤형 로거, 에러 감지기 시스템 + - **강력한 'Plugin 시스템', 타인의 플러그인 이용가능, 현재 기본적으로 딸려 나오는 지원 플러그인**: + - `로그인 플러그인` + - `하드웨어 리소스 추적 플러그인` + - `새로 올라온 챕터만을 받는 플러그인` + - `압축(Archive) 지원 플러그인` + - `클라이언트 프록시 플러그인` + - `특정한 이미지 확장자를 지정하여 받는 플러그인` + - `QQ메일 알리미 플러그인` + - `로그 주제 필터 플러그인` + - `웹 브라우저의 쿠키(Cookies)를 능동적으로 받는 플러그인` + - `북마크 목록을 CSV 표로 추출하는 플러그인` + - `모든 이미지를 읽기용 PDF 파일 한 개로 결합하는 플러그인` + - `모든 이미지를 좁고 긴 하나의 원본 PNG 사진으로 결합하는 플러그인` + - `로컬 디스크에 받은 만화를 열람할 웹서버 호스팅 플러그인` + - `앨범 업데이트 구독 플러그인` + - `이미지 수가 적은 챕터 건너뛰기 플러그인` + - `중복 이미지를 탐지하고 제거하는 플러그인` + - `경로 문자열 바꾸기 플러그인` + - `고급 재접속(Retry) 플러그인` + - `표지 다운로드 플러그인` + +## 사용 팁 + +* Python 3.7 이상을 요구하지만, 라이브러리와 jmcomic 패키지의 충돌을 막기 위해 3.9 이상의 쓰임을 추천합니다. +* 여유 시간에 만들어 지는 프로젝트이기에 정보나 활용 코드의 늦은 갱신이 다분합니다. 이슈(Issue)페이지로 연락주시기 바랍니다! + +## 프로젝트 폴더 안내 + +* `.github`: GitHub Actions 구성 파일 +* `assets`: 코드가 아닌 관련 리소스 + * `docs`: 상세 가이드 및 관련 프로젝트 설명 문서 + * `option`: 설정 샘플 예제 +* `src`: 실용 소스코드 폴더 + * `jmcomic`: `jmcomic` 핵심 모듈 +* `tests`: 유닛 테스트 패키지 구조, 자동화 테스트 +* `usage`: 실사용 시 참조하면 좋은 활용 구조 + +## 이하 프로젝트들에 감사드립니다. + +### 이미지 복구/분할 알고리즘 & JM 모바일 API 호환 + + + + + + Repo Card + +