mirror of
https://github.com/hect0x7/JMComic-Crawler-Python.git
synced 2025-09-26 22:31:30 +08:00
优化 项目文档&测试代码 (#252)
This commit is contained in:
parent
826be95865
commit
99acab28d1
@ -1,4 +1,5 @@
|
|||||||
repo_url: https://github.com/hect0x7/JMComic-Crawler-Python
|
repo_url: https://github.com/hect0x7/JMComic-Crawler-Python
|
||||||
|
repo_name: hect0x7/JMComic-Crawler-Python
|
||||||
site_name: jmcomic
|
site_name: jmcomic
|
||||||
|
|
||||||
theme:
|
theme:
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
|
|
||||||
|
|
||||||
## 特殊用法教程
|
## 特殊用法教程
|
||||||
- [GitHub Actions使用教程](./tutorial/1_github_actions.md)
|
- [使用GitHub Actions下载本子](./tutorial/1_github_actions.md)
|
||||||
- [命令行使用教程](tutorial/2_command_line.md)
|
- [使用GitHub Actions导出收藏夹](tutorial/10_export_favorites.md)
|
||||||
- [导出收藏夹教程](tutorial/10_export_favorites.md)
|
- [命令行用法教程](tutorial/2_command_line.md)
|
||||||
|
- [测试你的ip能访问哪些禁漫域名](tutorial/8_pick_domain.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# 日志自定义 - 如果你不想看到那么多的日志
|
# 日志自定义
|
||||||
|
|
||||||
本文档缘起于 GitHub Discussions: [discussions/195](https://github.com/hect0x7/JMComic-Crawler-Python/discussions/195)
|
本文档缘起于 GitHub Discussions: [discussions/195](https://github.com/hect0x7/JMComic-Crawler-Python/discussions/195)
|
||||||
|
|
||||||
|
@ -2,45 +2,77 @@
|
|||||||
|
|
||||||
plugin(扩展/插件)是v2.2.0新引入的机制,使用插件可以实现灵活无感知的功能增强。
|
plugin(扩展/插件)是v2.2.0新引入的机制,使用插件可以实现灵活无感知的功能增强。
|
||||||
|
|
||||||
plugin的机制为,可在`特定时间` 回调 `特定插件`。
|
目前jmcomic已经内置了一些插件,源码位于 src/jmcomic/jm_plugin.py。
|
||||||
|
|
||||||
目前jmcomic已经内置了一些强大的插件,源码位于 src/jmcomic/jm_plugin.py。
|
你可以在这里查看这些插件的配置→ [option_file_syntax](../option_file_syntax.md#3-option插件配置项)
|
||||||
|
|
||||||
配置插件的方式请查看 [option_file_syntax](../option_file_syntax.md#3-option插件配置项)
|
## 1. 插件机制介绍
|
||||||
|
|
||||||
|
你可以在option配置文件中配置插件,插件会特定的<u>`事件`</u>发生时自动执行。
|
||||||
|
|
||||||
|
jmcomic里的内置事件如下:
|
||||||
|
|
||||||
|
- `after_init`: option对象创建后
|
||||||
|
|
||||||
|
|
||||||
|
- `before_image`: 下载图片前
|
||||||
|
- `before_album`: 下载本子前
|
||||||
|
- `before_photo`: 下载章节前
|
||||||
|
|
||||||
## 示例1. 使用login插件,自动登录禁漫
|
|
||||||
|
|
||||||
特定时间:after_init(option对象实例化完毕后)
|
- `after_image`: 下载图片后
|
||||||
|
- `after_album`: 下载本子后
|
||||||
|
- `after_photo`: 下载章节后
|
||||||
|
|
||||||
特定插件:login
|
举例:你可以配置一个login插件,在option对象创建后(`after_init`)时,调用`login`插件,执行登录禁漫的功能。
|
||||||
|
|
||||||
插件功能:登录JM,获取并保存cookies,所有的Client都会使用这个cookies。
|
这样你后续使用option下载本子时,都会处于已登录状态。已登录状态可以让你访问所有禁漫本子。
|
||||||
|
|
||||||
首先,你需要在option配置文件当中配置如下内容,来实现在after_init时,调用login插件。
|
## 2. 示例:在after_init时调用login插件
|
||||||
|
|
||||||
|
`login`插件功能:登录JM,获取并保存cookies到option内。后续option创建的Client都会携带cookies,即都是登录状态。
|
||||||
|
|
||||||
|
配置方式:将以下配置写入option文件
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
plugins:
|
plugins: # 插件配置项
|
||||||
after_init: # 时机
|
after_init: # 在after_init事件时自动执行插件
|
||||||
- plugin: login # 插件的key
|
- plugin: login # 插件的key
|
||||||
kwargs:
|
kwargs: # 下面是给插件的参数 (kwargs),由插件类自定义
|
||||||
# 下面是给插件的参数 (kwargs),由插件类自定义
|
username: un # 禁漫帐号
|
||||||
username: un # 禁漫帐号
|
password: pw # 密码
|
||||||
password: pw # 密码
|
|
||||||
```
|
```
|
||||||
|
|
||||||
有了上述option配置,当你调用下面的代码时,login插件就会执行。
|
有了上述option配置,当你调用下面的代码时,login插件就会执行。
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import jmcomic
|
import jmcomic
|
||||||
option = jmcomic.create_option('xxx.yml')
|
|
||||||
# 程序走到这里,login插件已经调用完毕了。
|
option = jmcomic.create_option_by_file('xxx.yml') # 创建option对象
|
||||||
|
# 程序走到这里,login插件已经调用完毕了
|
||||||
|
# 后续下载本子就都是已登录状态里了
|
||||||
|
option.download_album(123)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 3. 怎么手动调用插件
|
||||||
|
|
||||||
|
你可以使用下面的代码触发某个事件
|
||||||
|
|
||||||
## 示例2. 自定义插件
|
```python
|
||||||
|
# 假设你已经创建了option对象
|
||||||
|
from jmcomic import JmOption
|
||||||
|
|
||||||
|
option: JmOption
|
||||||
|
# 手动调用after_init事件下的插件
|
||||||
|
option.call_all_plugin('after_init')
|
||||||
|
# 手动调用一个特定事件的插件(如果你没有配置这个事件的插件,那么无事发生。)
|
||||||
|
option.call_all_plugin('my_event')
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 示例:自定义插件
|
||||||
|
|
||||||
|
* 如果你有好的plugin想法,也欢迎向我提PR,将你的plugin内置到jmcomic模块中
|
||||||
|
|
||||||
下面演示自定义插件,分为3步:
|
下面演示自定义插件,分为3步:
|
||||||
|
|
||||||
@ -48,20 +80,21 @@ option = jmcomic.create_option('xxx.yml')
|
|||||||
2. 让plugin类生效
|
2. 让plugin类生效
|
||||||
3. 使用plugin的key
|
3. 使用plugin的key
|
||||||
|
|
||||||
* 如果你有好的plugin想法,也欢迎向我提PR,将你的plugin内置到jmcomic模块中
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# 1. 自定义plugin类
|
# 1. 自定义plugin类
|
||||||
from jmcomic import JmOptionPlugin, JmModuleConfig, create_option
|
from jmcomic import JmOptionPlugin, JmModuleConfig
|
||||||
|
|
||||||
|
|
||||||
|
# 自定义一个类,继承JmOptionPlugin
|
||||||
class MyPlugin(JmOptionPlugin):
|
class MyPlugin(JmOptionPlugin):
|
||||||
# 指定你的插件的key
|
# 指定你的插件的key
|
||||||
plugin_key = 'myplugin'
|
plugin_key = 'myplugin'
|
||||||
|
|
||||||
# 覆盖invoke方法,设定方法只有一个参数,名为`hello_plugin`
|
# 实现invoke方法
|
||||||
def invoke(self, hello_plugin) -> None:
|
# 方法的参数可以自定义,这里假设方法只有一个参数 word
|
||||||
print(hello_plugin)
|
def invoke(self, word) -> None:
|
||||||
|
print(word)
|
||||||
|
|
||||||
|
|
||||||
# 2. 让plugin类生效
|
# 2. 让plugin类生效
|
||||||
JmModuleConfig.register_plugin(MyPlugin)
|
JmModuleConfig.register_plugin(MyPlugin)
|
||||||
@ -72,20 +105,17 @@ JmModuleConfig.register_plugin(MyPlugin)
|
|||||||
```yaml
|
```yaml
|
||||||
# 3. 在配置文件中使用plugin
|
# 3. 在配置文件中使用plugin
|
||||||
plugins:
|
plugins:
|
||||||
after_init: # 时机
|
after_init: # 事件
|
||||||
- plugin: myplugin # 插件的key
|
- plugin: myplugin # 你自定义的插件key
|
||||||
kwargs:
|
kwargs:
|
||||||
hello_plugin: this is my plugin invoke method's parameter # 你自定义的插件的参数
|
word: hello jmcomic # 你自定义的插件的参数
|
||||||
```
|
```
|
||||||
|
|
||||||
完成上述步骤后,每当你使用下面的代码,你的plugin会被调用,控制台就会打印出 `this is my plugin invoke method's parameter`
|
完成上述步骤后,每当你使用下面的代码,你的plugin会被调用,控制台就会打印出 `hello jmcomic`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from jmcomic import create_option
|
from jmcomic import create_option
|
||||||
|
|
||||||
option = create_option('xxx')
|
option = create_option('xxx')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# jmcomic 综合使用实例
|
# 综合使用实例
|
||||||
|
|
||||||
* 基于v2.2.2+内置插件
|
* 基于v2.2.2+内置插件
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ meta_data = {
|
|||||||
disable_jm_log()
|
disable_jm_log()
|
||||||
|
|
||||||
|
|
||||||
def get_domain_ls():
|
def get_all_domain():
|
||||||
template = 'https://jmcmomic.github.io/go/{}.html'
|
template = 'https://jmcmomic.github.io/go/{}.html'
|
||||||
url_ls = [
|
url_ls = [
|
||||||
template.format(i)
|
template.format(i)
|
||||||
@ -39,9 +39,9 @@ def get_domain_ls():
|
|||||||
return domain_set
|
return domain_set
|
||||||
|
|
||||||
|
|
||||||
domain_set = get_domain_ls()
|
domain_set = get_all_domain()
|
||||||
domain_status_dict = {}
|
|
||||||
print(f'获取到{len(domain_set)}个域名,开始测试')
|
print(f'获取到{len(domain_set)}个域名,开始测试')
|
||||||
|
domain_status_dict = {}
|
||||||
|
|
||||||
|
|
||||||
def test_domain(domain: str):
|
def test_domain(domain: str):
|
||||||
|
@ -251,7 +251,7 @@ class Test_Client(JmTestConfigurable):
|
|||||||
return cl.get_album_detail('123')
|
return cl.get_album_detail('123')
|
||||||
|
|
||||||
def assertEqual(first_cl, second_cl, msg):
|
def assertEqual(first_cl, second_cl, msg):
|
||||||
return self.assertEqual(
|
self.assertEqual(
|
||||||
get(first_cl),
|
get(first_cl),
|
||||||
get(second_cl),
|
get(second_cl),
|
||||||
msg,
|
msg,
|
||||||
@ -265,12 +265,6 @@ class Test_Client(JmTestConfigurable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
cases = [
|
cases = [
|
||||||
(
|
|
||||||
CacheRegistry.level_option,
|
|
||||||
CacheRegistry.level_option,
|
|
||||||
CacheRegistry.level_client,
|
|
||||||
CacheRegistry.level_client,
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
True,
|
True,
|
||||||
'level_option',
|
'level_option',
|
||||||
@ -291,25 +285,17 @@ class Test_Client(JmTestConfigurable):
|
|||||||
# c1 == c2
|
# c1 == c2
|
||||||
# c3 == c4
|
# c3 == c4
|
||||||
# c1 != c3
|
# c1 != c3
|
||||||
|
assertEqual(c1, c2, 'equals in same option level')
|
||||||
|
assertNotEqual(c3, c4, 'not equals in client level')
|
||||||
|
assertNotEqual(c1, c3, 'not equals in different level')
|
||||||
|
|
||||||
# c5 != c1, c2, c3, c4
|
# c5 != c1, c2, c3, c4
|
||||||
invoke_all(
|
obj = get(c5)
|
||||||
args_func_list=[
|
self.assertNotEqual(obj, get(c1))
|
||||||
(None, func) for func in [
|
self.assertNotEqual(obj, get(c3))
|
||||||
lambda: assertEqual(c1, c2, 'equals in same option level'),
|
|
||||||
lambda: assertNotEqual(c3, c4, 'not equals in client level'),
|
|
||||||
lambda: assertNotEqual(c1, c3, 'not equals in different level'),
|
|
||||||
lambda: assertNotEqual(c1, c5, 'not equals for None level'),
|
|
||||||
lambda: assertNotEqual(c3, c5, 'not equals for None level'),
|
|
||||||
]
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
future_ls = thread_pool_executor(
|
for case in cases:
|
||||||
iter_objs=cases,
|
run(*case)
|
||||||
apply_each_obj_func=run,
|
|
||||||
)
|
|
||||||
|
|
||||||
return [f.result() for f in future_ls] # 等待执行完毕
|
|
||||||
|
|
||||||
def test_search_advanced(self):
|
def test_search_advanced(self):
|
||||||
if not self.client.is_given_type(JmHtmlClient):
|
if not self.client.is_given_type(JmHtmlClient):
|
||||||
|
Loading…
Reference in New Issue
Block a user