Skip to content
Merged

Docs #515

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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/
.idea/
.agent
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
<!-- 顶部标题 & 统计徽章 -->
<div align="center">
<h1 style="margin-top: 0" align="center">Python API for JMComic</h1>

<p align="center">
<strong>简体中文</strong> •
<a href="./assets/readme/README-en.md">English</a> •
<a href="./assets/readme/README-jp.md">日本語</a> •
<a href="./assets/readme/README-kr.md">한국어</a>
</p>

<p align="center">
<strong>提供 Python API 访问禁漫天堂(网页端 & 移动端),集成 GitHub Actions 下载器🚀</strong>
</p>
Expand Down Expand Up @@ -56,7 +64,7 @@
* 通过pip官方源安装(推荐,并且更新也是这个命令)

```shell
pip install jmcomic -i https://pypi.org/project -U
pip install jmcomic -U
```
* 通过源代码安装

Expand Down Expand Up @@ -175,14 +183,21 @@ jmcomic 123
- `硬件占用监控插件`
- `只下载新章插件`
- `压缩文件插件`
- `客户端代理插件`
- `下载特定后缀图片插件`
- `发送QQ邮件插件`
- `自动使用浏览器cookies插件`
- `日志主题过滤插件`
- `自动获取浏览器cookies插件`
- `导出收藏夹为csv文件插件`
- `合并所有图片为pdf文件插件`
- `合并所有图片为长图png插件`
- `重复文件检测删除插件`
- `网页观看本地章节插件`
- `订阅更新插件`
- `小章节跳过插件`
- `重复文件检测删除插件`
- `路径字符串替换插件`
- `高级重试插件`
- `封面下载插件`

## 使用小说明

Expand Down
27 changes: 27 additions & 0 deletions assets/docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion assets/docs/sources/api/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
::: jmcomic.jm_plugin
options:
filters:
- Plugin$
- (Plugin$|JmOptionPlugin|^Plugin)
2 changes: 1 addition & 1 deletion assets/docs/sources/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
>
> 你可以通过简单的几行Python代码,访问禁漫的接口,以及下载禁漫的本子。
>
> [查看项目更新计划](TODO.md)
> [查看项目更新计划](roadmap.md)

## 一图看懂 JMComic 工具生态

Expand Down
9 changes: 9 additions & 0 deletions assets/docs/sources/option_file_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -137,6 +145,7 @@ dir_rule:
plugins:
after_init:
- plugin: usage_log # 实时打印硬件占用率的插件
# log: false # 选填。所有的插件都可以配置 `log: false` 以关闭该插件执行时产生的日志输出,默认是 true
kwargs:
interval: 0.5 # 间隔时间
enable_warning: true # 占用过大时发出预警
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 版本更新计划
# 项目更新计划

| 版本范围 | 更新计划 |
|:--------:|:-----------------------------------------:|
Expand Down
30 changes: 30 additions & 0 deletions assets/docs/sources/tutorial/0_common_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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

```

## 高级搜索(分类/副分类)
Expand Down Expand Up @@ -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
```


Expand Down
114 changes: 114 additions & 0 deletions assets/docs/sources/tutorial/12_domain_strategy.md
Original file line number Diff line number Diff line change
@@ -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 在下载和请求时,就会自动切入高级容错策略。
17 changes: 4 additions & 13 deletions assets/docs/sources/tutorial/4_module_custom.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@



下方所有函数都省略了如下的导包和准备代码

```python
from jmcomic import *
option = JmOption.default()
client: JmcomicClient = option.build_jm_client()
```



## 自定义下载前后的回调函数

```python
Expand Down Expand Up @@ -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):
Expand All @@ -164,11 +154,12 @@ def custom_jm_log():
pass

# 2. 让my_log生效
JmModuleConfig.log_executor = my_log
JmModuleConfig.EXECUTOR_LOG = my_log
```




## 自定义异常监听器/回调

```python
Expand Down
9 changes: 8 additions & 1 deletion assets/docs/sources/tutorial/5_filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
Loading