novel-downloader 1.3.2__py3-none-any.whl → 1.4.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.
- novel_downloader/__init__.py +1 -1
- novel_downloader/cli/clean.py +97 -78
- novel_downloader/cli/config.py +177 -0
- novel_downloader/cli/download.py +132 -87
- novel_downloader/cli/export.py +77 -0
- novel_downloader/cli/main.py +21 -28
- novel_downloader/config/__init__.py +1 -25
- novel_downloader/config/adapter.py +32 -31
- novel_downloader/config/loader.py +3 -3
- novel_downloader/config/site_rules.py +1 -2
- novel_downloader/core/__init__.py +3 -6
- novel_downloader/core/downloaders/__init__.py +10 -13
- novel_downloader/core/downloaders/base.py +233 -0
- novel_downloader/core/downloaders/biquge.py +27 -0
- novel_downloader/core/downloaders/common.py +414 -0
- novel_downloader/core/downloaders/esjzone.py +27 -0
- novel_downloader/core/downloaders/linovelib.py +27 -0
- novel_downloader/core/downloaders/qianbi.py +27 -0
- novel_downloader/core/downloaders/qidian.py +352 -0
- novel_downloader/core/downloaders/sfacg.py +27 -0
- novel_downloader/core/downloaders/yamibo.py +27 -0
- novel_downloader/core/exporters/__init__.py +37 -0
- novel_downloader/core/{savers → exporters}/base.py +73 -44
- novel_downloader/core/exporters/biquge.py +25 -0
- novel_downloader/core/exporters/common/__init__.py +12 -0
- novel_downloader/core/{savers → exporters}/common/epub.py +40 -52
- novel_downloader/core/{savers/common/main_saver.py → exporters/common/main_exporter.py} +36 -39
- novel_downloader/core/{savers → exporters}/common/txt.py +20 -24
- novel_downloader/core/exporters/epub_utils/__init__.py +40 -0
- novel_downloader/core/{savers → exporters}/epub_utils/css_builder.py +2 -1
- novel_downloader/core/exporters/epub_utils/image_loader.py +131 -0
- novel_downloader/core/{savers → exporters}/epub_utils/initializer.py +6 -3
- novel_downloader/core/{savers → exporters}/epub_utils/text_to_html.py +49 -2
- novel_downloader/core/{savers → exporters}/epub_utils/volume_intro.py +2 -1
- novel_downloader/core/exporters/esjzone.py +25 -0
- novel_downloader/core/exporters/linovelib/__init__.py +10 -0
- novel_downloader/core/exporters/linovelib/epub.py +449 -0
- novel_downloader/core/exporters/linovelib/main_exporter.py +127 -0
- novel_downloader/core/exporters/linovelib/txt.py +129 -0
- novel_downloader/core/exporters/qianbi.py +25 -0
- novel_downloader/core/{savers → exporters}/qidian.py +8 -8
- novel_downloader/core/exporters/sfacg.py +25 -0
- novel_downloader/core/exporters/yamibo.py +25 -0
- novel_downloader/core/factory/__init__.py +5 -17
- novel_downloader/core/factory/downloader.py +24 -126
- novel_downloader/core/factory/exporter.py +58 -0
- novel_downloader/core/factory/fetcher.py +96 -0
- novel_downloader/core/factory/parser.py +17 -12
- novel_downloader/core/{requesters → fetchers}/__init__.py +22 -15
- novel_downloader/core/{requesters → fetchers}/base/__init__.py +2 -4
- novel_downloader/core/fetchers/base/browser.py +383 -0
- novel_downloader/core/fetchers/base/rate_limiter.py +86 -0
- novel_downloader/core/fetchers/base/session.py +419 -0
- novel_downloader/core/fetchers/biquge/__init__.py +14 -0
- novel_downloader/core/{requesters/biquge/async_session.py → fetchers/biquge/browser.py} +18 -6
- novel_downloader/core/{requesters → fetchers}/biquge/session.py +23 -30
- novel_downloader/core/fetchers/common/__init__.py +14 -0
- novel_downloader/core/fetchers/common/browser.py +79 -0
- novel_downloader/core/{requesters/common/async_session.py → fetchers/common/session.py} +8 -25
- novel_downloader/core/fetchers/esjzone/__init__.py +14 -0
- novel_downloader/core/fetchers/esjzone/browser.py +202 -0
- novel_downloader/core/{requesters/esjzone/async_session.py → fetchers/esjzone/session.py} +62 -42
- novel_downloader/core/fetchers/linovelib/__init__.py +14 -0
- novel_downloader/core/fetchers/linovelib/browser.py +178 -0
- novel_downloader/core/fetchers/linovelib/session.py +178 -0
- novel_downloader/core/fetchers/qianbi/__init__.py +14 -0
- novel_downloader/core/{requesters/qianbi/session.py → fetchers/qianbi/browser.py} +30 -48
- novel_downloader/core/{requesters/qianbi/async_session.py → fetchers/qianbi/session.py} +18 -6
- novel_downloader/core/fetchers/qidian/__init__.py +14 -0
- novel_downloader/core/fetchers/qidian/browser.py +266 -0
- novel_downloader/core/fetchers/qidian/session.py +326 -0
- novel_downloader/core/fetchers/sfacg/__init__.py +14 -0
- novel_downloader/core/fetchers/sfacg/browser.py +189 -0
- novel_downloader/core/{requesters/sfacg/async_session.py → fetchers/sfacg/session.py} +43 -73
- novel_downloader/core/fetchers/yamibo/__init__.py +14 -0
- novel_downloader/core/fetchers/yamibo/browser.py +229 -0
- novel_downloader/core/{requesters/yamibo/async_session.py → fetchers/yamibo/session.py} +62 -44
- novel_downloader/core/interfaces/__init__.py +8 -12
- novel_downloader/core/interfaces/downloader.py +54 -0
- novel_downloader/core/interfaces/{saver.py → exporter.py} +12 -12
- novel_downloader/core/interfaces/fetcher.py +162 -0
- novel_downloader/core/interfaces/parser.py +6 -7
- novel_downloader/core/parsers/__init__.py +5 -6
- novel_downloader/core/parsers/base.py +9 -13
- novel_downloader/core/parsers/biquge/main_parser.py +12 -13
- novel_downloader/core/parsers/common/helper.py +3 -3
- novel_downloader/core/parsers/common/main_parser.py +39 -34
- novel_downloader/core/parsers/esjzone/main_parser.py +24 -17
- novel_downloader/core/parsers/linovelib/__init__.py +10 -0
- novel_downloader/core/parsers/linovelib/main_parser.py +210 -0
- novel_downloader/core/parsers/qianbi/main_parser.py +21 -15
- novel_downloader/core/parsers/qidian/__init__.py +2 -11
- novel_downloader/core/parsers/qidian/book_info_parser.py +113 -0
- novel_downloader/core/parsers/qidian/{browser/chapter_encrypted.py → chapter_encrypted.py} +162 -135
- novel_downloader/core/parsers/qidian/chapter_normal.py +150 -0
- novel_downloader/core/parsers/qidian/{session/chapter_router.py → chapter_router.py} +15 -15
- novel_downloader/core/parsers/qidian/{browser/main_parser.py → main_parser.py} +49 -40
- novel_downloader/core/parsers/qidian/utils/__init__.py +27 -0
- novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +145 -0
- novel_downloader/core/parsers/qidian/{shared → utils}/helpers.py +41 -68
- novel_downloader/core/parsers/qidian/{session → utils}/node_decryptor.py +64 -50
- novel_downloader/core/parsers/sfacg/main_parser.py +12 -12
- novel_downloader/core/parsers/yamibo/main_parser.py +10 -10
- novel_downloader/locales/en.json +18 -2
- novel_downloader/locales/zh.json +18 -2
- novel_downloader/models/__init__.py +64 -0
- novel_downloader/models/browser.py +21 -0
- novel_downloader/models/chapter.py +25 -0
- novel_downloader/models/config.py +100 -0
- novel_downloader/models/login.py +20 -0
- novel_downloader/models/site_rules.py +99 -0
- novel_downloader/models/tasks.py +33 -0
- novel_downloader/models/types.py +15 -0
- novel_downloader/resources/config/settings.toml +31 -25
- novel_downloader/resources/json/linovelib_font_map.json +3573 -0
- novel_downloader/tui/__init__.py +7 -0
- novel_downloader/tui/app.py +32 -0
- novel_downloader/tui/main.py +17 -0
- novel_downloader/tui/screens/__init__.py +14 -0
- novel_downloader/tui/screens/home.py +191 -0
- novel_downloader/tui/screens/login.py +74 -0
- novel_downloader/tui/styles/home_layout.tcss +79 -0
- novel_downloader/tui/widgets/richlog_handler.py +24 -0
- novel_downloader/utils/__init__.py +6 -0
- novel_downloader/utils/chapter_storage.py +25 -38
- novel_downloader/utils/constants.py +15 -5
- novel_downloader/utils/cookies.py +66 -0
- novel_downloader/utils/crypto_utils.py +1 -74
- novel_downloader/utils/file_utils/io.py +1 -1
- novel_downloader/utils/fontocr/ocr_v1.py +2 -1
- novel_downloader/utils/fontocr/ocr_v2.py +2 -2
- novel_downloader/utils/hash_store.py +10 -18
- novel_downloader/utils/hash_utils.py +3 -2
- novel_downloader/utils/logger.py +2 -3
- novel_downloader/utils/network.py +53 -39
- novel_downloader/utils/text_utils/chapter_formatting.py +6 -1
- novel_downloader/utils/text_utils/font_mapping.py +1 -1
- novel_downloader/utils/text_utils/text_cleaning.py +1 -1
- novel_downloader/utils/time_utils/datetime_utils.py +3 -3
- novel_downloader/utils/time_utils/sleep_utils.py +3 -3
- {novel_downloader-1.3.2.dist-info → novel_downloader-1.4.0.dist-info}/METADATA +72 -38
- novel_downloader-1.4.0.dist-info/RECORD +170 -0
- {novel_downloader-1.3.2.dist-info → novel_downloader-1.4.0.dist-info}/WHEEL +1 -1
- {novel_downloader-1.3.2.dist-info → novel_downloader-1.4.0.dist-info}/entry_points.txt +1 -0
- novel_downloader/cli/interactive.py +0 -66
- novel_downloader/cli/settings.py +0 -177
- novel_downloader/config/models.py +0 -187
- novel_downloader/core/downloaders/base/__init__.py +0 -14
- novel_downloader/core/downloaders/base/base_async.py +0 -153
- novel_downloader/core/downloaders/base/base_sync.py +0 -208
- novel_downloader/core/downloaders/biquge/__init__.py +0 -14
- novel_downloader/core/downloaders/biquge/biquge_async.py +0 -27
- novel_downloader/core/downloaders/biquge/biquge_sync.py +0 -27
- novel_downloader/core/downloaders/common/__init__.py +0 -14
- novel_downloader/core/downloaders/common/common_async.py +0 -218
- novel_downloader/core/downloaders/common/common_sync.py +0 -210
- novel_downloader/core/downloaders/esjzone/__init__.py +0 -14
- novel_downloader/core/downloaders/esjzone/esjzone_async.py +0 -27
- novel_downloader/core/downloaders/esjzone/esjzone_sync.py +0 -27
- novel_downloader/core/downloaders/qianbi/__init__.py +0 -14
- novel_downloader/core/downloaders/qianbi/qianbi_async.py +0 -27
- novel_downloader/core/downloaders/qianbi/qianbi_sync.py +0 -27
- novel_downloader/core/downloaders/qidian/__init__.py +0 -10
- novel_downloader/core/downloaders/qidian/qidian_sync.py +0 -227
- novel_downloader/core/downloaders/sfacg/__init__.py +0 -14
- novel_downloader/core/downloaders/sfacg/sfacg_async.py +0 -27
- novel_downloader/core/downloaders/sfacg/sfacg_sync.py +0 -27
- novel_downloader/core/downloaders/yamibo/__init__.py +0 -14
- novel_downloader/core/downloaders/yamibo/yamibo_async.py +0 -27
- novel_downloader/core/downloaders/yamibo/yamibo_sync.py +0 -27
- novel_downloader/core/factory/requester.py +0 -144
- novel_downloader/core/factory/saver.py +0 -56
- novel_downloader/core/interfaces/async_downloader.py +0 -36
- novel_downloader/core/interfaces/async_requester.py +0 -84
- novel_downloader/core/interfaces/sync_downloader.py +0 -36
- novel_downloader/core/interfaces/sync_requester.py +0 -82
- novel_downloader/core/parsers/qidian/browser/__init__.py +0 -12
- novel_downloader/core/parsers/qidian/browser/chapter_normal.py +0 -93
- novel_downloader/core/parsers/qidian/browser/chapter_router.py +0 -71
- novel_downloader/core/parsers/qidian/session/__init__.py +0 -12
- novel_downloader/core/parsers/qidian/session/chapter_encrypted.py +0 -443
- novel_downloader/core/parsers/qidian/session/chapter_normal.py +0 -115
- novel_downloader/core/parsers/qidian/session/main_parser.py +0 -128
- novel_downloader/core/parsers/qidian/shared/__init__.py +0 -37
- novel_downloader/core/parsers/qidian/shared/book_info_parser.py +0 -150
- novel_downloader/core/requesters/base/async_session.py +0 -410
- novel_downloader/core/requesters/base/browser.py +0 -337
- novel_downloader/core/requesters/base/session.py +0 -378
- novel_downloader/core/requesters/biquge/__init__.py +0 -14
- novel_downloader/core/requesters/common/__init__.py +0 -17
- novel_downloader/core/requesters/common/session.py +0 -113
- novel_downloader/core/requesters/esjzone/__init__.py +0 -13
- novel_downloader/core/requesters/esjzone/session.py +0 -235
- novel_downloader/core/requesters/qianbi/__init__.py +0 -13
- novel_downloader/core/requesters/qidian/__init__.py +0 -21
- novel_downloader/core/requesters/qidian/broswer.py +0 -307
- novel_downloader/core/requesters/qidian/session.py +0 -290
- novel_downloader/core/requesters/sfacg/__init__.py +0 -13
- novel_downloader/core/requesters/sfacg/session.py +0 -242
- novel_downloader/core/requesters/yamibo/__init__.py +0 -13
- novel_downloader/core/requesters/yamibo/session.py +0 -237
- novel_downloader/core/savers/__init__.py +0 -34
- novel_downloader/core/savers/biquge.py +0 -25
- novel_downloader/core/savers/common/__init__.py +0 -12
- novel_downloader/core/savers/epub_utils/__init__.py +0 -26
- novel_downloader/core/savers/esjzone.py +0 -25
- novel_downloader/core/savers/qianbi.py +0 -25
- novel_downloader/core/savers/sfacg.py +0 -25
- novel_downloader/core/savers/yamibo.py +0 -25
- novel_downloader/resources/config/rules.toml +0 -196
- novel_downloader-1.3.2.dist-info/RECORD +0 -165
- {novel_downloader-1.3.2.dist-info → novel_downloader-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-1.3.2.dist-info → novel_downloader-1.4.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: novel-downloader
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.0
|
4
4
|
Summary: A command-line tool for downloading Chinese web novels from Qidian and similar platforms.
|
5
5
|
Author-email: Saudade Z <saudadez217@gmail.com>
|
6
6
|
License: MIT License
|
@@ -34,19 +34,18 @@ Classifier: License :: OSI Approved :: MIT License
|
|
34
34
|
Classifier: Natural Language :: Chinese (Simplified)
|
35
35
|
Classifier: Topic :: Utilities
|
36
36
|
Classifier: Programming Language :: Python :: 3
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
37
38
|
Classifier: Programming Language :: Python :: 3.12
|
38
39
|
Classifier: Programming Language :: Python :: 3.13
|
39
|
-
Requires-Python: >=3.
|
40
|
+
Requires-Python: >=3.11
|
40
41
|
Description-Content-Type: text/markdown
|
41
42
|
License-File: LICENSE
|
43
|
+
Requires-Dist: textual
|
42
44
|
Requires-Dist: requests
|
43
45
|
Requires-Dist: aiohttp
|
44
|
-
Requires-Dist:
|
45
|
-
Requires-Dist: DrissionPage
|
46
|
-
Requires-Dist: opencv-python
|
46
|
+
Requires-Dist: playwright
|
47
47
|
Requires-Dist: lxml
|
48
48
|
Requires-Dist: platformdirs
|
49
|
-
Requires-Dist: click
|
50
49
|
Requires-Dist: ebooklib
|
51
50
|
Provides-Extra: dev
|
52
51
|
Requires-Dist: black; extra == "dev"
|
@@ -55,6 +54,8 @@ Requires-Dist: ruff; extra == "dev"
|
|
55
54
|
Requires-Dist: pytest; extra == "dev"
|
56
55
|
Requires-Dist: pytest-cov; extra == "dev"
|
57
56
|
Requires-Dist: pytest-mock; extra == "dev"
|
57
|
+
Requires-Dist: types-requests; extra == "dev"
|
58
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
58
59
|
Requires-Dist: pre-commit; extra == "dev"
|
59
60
|
Requires-Dist: commitizen; extra == "dev"
|
60
61
|
Provides-Extra: font-recovery
|
@@ -63,63 +64,96 @@ Requires-Dist: numpy; extra == "font-recovery"
|
|
63
64
|
Requires-Dist: tinycss2; extra == "font-recovery"
|
64
65
|
Requires-Dist: fonttools; extra == "font-recovery"
|
65
66
|
Requires-Dist: brotli; extra == "font-recovery"
|
67
|
+
Requires-Dist: opencv-python; extra == "font-recovery"
|
66
68
|
Requires-Dist: pillow; extra == "font-recovery"
|
67
69
|
Requires-Dist: huggingface_hub; extra == "font-recovery"
|
68
70
|
Dynamic: license-file
|
69
71
|
|
70
72
|
# novel-downloader
|
71
73
|
|
72
|
-
一个基于 [
|
74
|
+
一个基于 [playwright](https://playwright.dev/) 和 [aiohttp](https://github.com/aio-libs/aiohttp) 的小说下载工具/库。
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
## 项目简介
|
77
|
-
|
78
|
-
**novel-downloader** 是一个通用的小说下载库 / CLI 工具,
|
79
|
-
- 大多数支持的站点仅依赖 [`requests`](https://github.com/psf/requests) 进行 HTTP 抓取
|
80
|
-
- 对于起点中文网 (Qidian), 可在配置中选择:
|
81
|
-
- `mode: session` : 纯 Requests 模式
|
82
|
-
- `mode: browser` : 基于 DrissionPage 驱动 Chrome 的浏览器模式 (可处理更复杂的 JS/加密)。
|
83
|
-
- 若配置 `login_required: true`, 程序会在运行时自动检查登录状态, 支持自动重用历史 Cookie, 仅在首次登录或 Cookie 失效时需要人工介入:
|
84
|
-
- 若使用 `browser` 模式, 请在程序打开的浏览器窗口登录, 登录后回车继续
|
85
|
-
- 若使用 `session` 模式, 请根据程序提示粘贴浏览器中登录成功后的 Cookie ([复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md))
|
76
|
+
> 本项目开发环境为 Python 3.12, 需确保运行环境为 Python 3.11 及以上版本
|
86
77
|
|
87
78
|
## 功能特性
|
88
79
|
|
89
|
-
-
|
90
|
-
-
|
91
|
-
- 断点续爬
|
92
|
-
- 自动整合所有章节并导出为
|
80
|
+
- 支持断点续爬, 自动续传未完成任务
|
81
|
+
- 自动整合所有章节并导出为:
|
93
82
|
- TXT
|
94
|
-
- EPUB
|
83
|
+
- EPUB (可选包含章节插图)
|
95
84
|
- 支持活动广告过滤:
|
96
85
|
- [x] 章节标题
|
97
86
|
- [ ] 章节正文
|
98
|
-
- [ ] 作者说
|
99
87
|
|
100
88
|
---
|
101
89
|
|
102
90
|
## 快速开始
|
103
91
|
|
92
|
+
### 安装
|
93
|
+
|
94
|
+
使用 `pip` 安装:
|
95
|
+
|
104
96
|
```bash
|
105
|
-
# 克隆 + 安装
|
106
97
|
pip install novel-downloader
|
98
|
+
```
|
99
|
+
|
100
|
+
如需使用浏览器模式 (即 `mode: browser`), 请确保已安装 Playwright 依赖:
|
107
101
|
|
108
|
-
|
109
|
-
|
102
|
+
```bash
|
103
|
+
playwright install
|
104
|
+
```
|
110
105
|
|
106
|
+
如需启用字体解密功能 (`decode_font`, 用于处理起点中文网对近一个月更新章节所采用的字体混淆技术), 请使用扩展安装方式:
|
107
|
+
|
108
|
+
```bash
|
109
|
+
pip install novel-downloader[font-recovery]
|
110
|
+
```
|
111
|
+
|
112
|
+
---
|
113
|
+
|
114
|
+
### CLI 模式
|
115
|
+
|
116
|
+
```bash
|
111
117
|
# 初始化默认配置 (生成 settings.toml)
|
112
|
-
novel-cli
|
118
|
+
novel-cli config init
|
113
119
|
|
114
120
|
# 编辑 ./settings.toml 完成 site/book_ids 等
|
115
|
-
# 可查看 docs/
|
121
|
+
# 可查看 docs/3-settings-schema.md
|
116
122
|
|
117
|
-
#
|
123
|
+
# 执行下载任务
|
118
124
|
novel-cli download 123456
|
119
125
|
```
|
120
126
|
|
121
|
-
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
122
|
-
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/
|
127
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
128
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
129
|
+
|
130
|
+
---
|
131
|
+
|
132
|
+
### TUI 模式 (终端用户界面)
|
133
|
+
|
134
|
+
**注意**: TUI 模式仍在开发中, 目前尚未实现登录和修改设置等功能。建议优先使用稳定的 CLI 模式。
|
135
|
+
|
136
|
+
```bash
|
137
|
+
# 初始化默认配置 (生成 settings.toml)
|
138
|
+
novel-cli config init
|
139
|
+
|
140
|
+
# 编辑 ./settings.toml 修改网络配置
|
141
|
+
# 可查看 docs/3-settings-schema.md
|
142
|
+
|
143
|
+
# 启动 TUI 界面
|
144
|
+
novel-tui
|
145
|
+
```
|
146
|
+
|
147
|
+
- 详细可见: [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
148
|
+
- 更多使用方法, 查看 [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
149
|
+
|
150
|
+
---
|
151
|
+
|
152
|
+
### GUI 模式 (图形界面)
|
153
|
+
|
154
|
+
尚未实现
|
155
|
+
|
156
|
+
---
|
123
157
|
|
124
158
|
## 从 GitHub 安装 (开发版)
|
125
159
|
|
@@ -139,11 +173,11 @@ pip install .
|
|
139
173
|
|
140
174
|
- [项目简介](#项目简介)
|
141
175
|
- [安装](https://github.com/BowenZ217/novel-downloader/blob/main/docs/1-installation.md)
|
142
|
-
- [
|
143
|
-
- [
|
144
|
-
- [
|
145
|
-
- [使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-usage-examples.md)
|
146
|
-
- [
|
176
|
+
- [配置](https://github.com/BowenZ217/novel-downloader/blob/main/docs/2-configuration.md)
|
177
|
+
- [settings.toml 配置说明](https://github.com/BowenZ217/novel-downloader/blob/main/docs/3-settings-schema.md)
|
178
|
+
- [支持站点列表](https://github.com/BowenZ217/novel-downloader/blob/main/docs/4-supported-sites.md)
|
179
|
+
- [TUI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/5-tui-usage-examples.md)
|
180
|
+
- [CLI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
147
181
|
- [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md)
|
148
182
|
- [文件保存](https://github.com/BowenZ217/novel-downloader/blob/main/docs/file-saving.md)
|
149
183
|
- [TODO](https://github.com/BowenZ217/novel-downloader/blob/main/docs/todo.md)
|
@@ -0,0 +1,170 @@
|
|
1
|
+
novel_downloader/__init__.py,sha256=TLa2eWlJhpY9lBjsolzhKpaZ7PWwhQj34Tj7RUSLlOY,218
|
2
|
+
novel_downloader/cli/__init__.py,sha256=-2HAut_U1e67MZGdvbpEJ1n5J-bRchzto6L4c-nWeXY,174
|
3
|
+
novel_downloader/cli/clean.py,sha256=hOk8SJQwBCw2oOObTdEI79wpnmZ25uB1s9LQK1-4LNU,4487
|
4
|
+
novel_downloader/cli/config.py,sha256=C6QLfegZLp4legmu8KenqyYKNdrk47bH0z86ujLP0pY,6509
|
5
|
+
novel_downloader/cli/download.py,sha256=HKCxufqnj4vDzCdM7soH_Y_eiVNRGpV17Mz08ADYwqQ,5279
|
6
|
+
novel_downloader/cli/export.py,sha256=x9uvyLuvkuaDZGoH212aHZ7XyPT9b2S78AmTN6rkAu4,2283
|
7
|
+
novel_downloader/cli/main.py,sha256=9J8KMuYwL01X6chIaXpQNeS5d3pHnwB9vA9XjKd8RrM,919
|
8
|
+
novel_downloader/config/__init__.py,sha256=2mnf33MQOUnLGCnL1NtNV_rHBejNxBNIbobIGN0tw4E,666
|
9
|
+
novel_downloader/config/adapter.py,sha256=UYtDlpKFcKmvBBN9ZOI3W7u0a72Fhrpk-DkZmKoKpqk,7281
|
10
|
+
novel_downloader/config/loader.py,sha256=jo_1rr3UKZRAFFYgO-oHpYLRhF431chmfx4fLGh0MKw,5743
|
11
|
+
novel_downloader/config/site_rules.py,sha256=CJksBSvVAC4sR6cEruf4pM1Jv0zTJb1lcHq0Yn6LPFM,2979
|
12
|
+
novel_downloader/core/__init__.py,sha256=zzrXjQfBUhfLmBD_95oHTjtTsR81NSRtHcxpYBxQlZ4,654
|
13
|
+
novel_downloader/core/downloaders/__init__.py,sha256=AK5zeetVXOn_irgHp-NORPYW65UJM4CsF8ysxf2vKD4,1064
|
14
|
+
novel_downloader/core/downloaders/base.py,sha256=H3Y9NnSv4lQA6ilKCd7HqAX24R79wXBMkLG5StK8znc,6420
|
15
|
+
novel_downloader/core/downloaders/biquge.py,sha256=PTm8eeaHVyw_nvtnuRpZ2hT7hLs2LEPV1Drd2O6idNM,651
|
16
|
+
novel_downloader/core/downloaders/common.py,sha256=1YNo-e5tuK5bGvuzX3eVmEJznD7f5JMo7a_abIdmEkM,15504
|
17
|
+
novel_downloader/core/downloaders/esjzone.py,sha256=GBFJ3fIPov483QxkOTaKBU2wd2f8T4GdvzSbRaU9hDI,655
|
18
|
+
novel_downloader/core/downloaders/linovelib.py,sha256=Cd43_70SKbKM8_C8c4qev3pLUgyziW9413qrA8EcStY,663
|
19
|
+
novel_downloader/core/downloaders/qianbi.py,sha256=ARuk1xABOGCjlD_ct5hOKMgWloU187rUJBbICJ2yvkY,651
|
20
|
+
novel_downloader/core/downloaders/qidian.py,sha256=YrX5HdJDopEjc1kvEJRjMc1S4iR049IGvzUNtgE-LPE,12590
|
21
|
+
novel_downloader/core/downloaders/sfacg.py,sha256=ShlkIIR6OW_x2FhNDi79S_3AL2CWId2upQmRkApee_E,647
|
22
|
+
novel_downloader/core/downloaders/yamibo.py,sha256=9L0m5Zq0o1y44tCQ4ZRHHqdO3YresJkRAVvCtsQwouk,651
|
23
|
+
novel_downloader/core/exporters/__init__.py,sha256=ATkkdh6RUIaM19mG1XjFiaMnGRgFFGT3ixsqVkU13Q0,867
|
24
|
+
novel_downloader/core/exporters/base.py,sha256=duIdLnj9kKNZ9r2aJV0Rzl-rnQCP8olk12uzduT9PtE,6146
|
25
|
+
novel_downloader/core/exporters/biquge.py,sha256=SJCChYtDLJKrOpwDCT8IeR0v1LoiUQuTTejfGmRnxX8,462
|
26
|
+
novel_downloader/core/exporters/esjzone.py,sha256=UP9gtTOv6komWjgvwXkttqDYJJPjjbJdiG3yz9RxHSQ,467
|
27
|
+
novel_downloader/core/exporters/qianbi.py,sha256=x841MNIxpS5eY8u91ODC0cpIhpT-ENnFqs_Yx6HwtdM,462
|
28
|
+
novel_downloader/core/exporters/qidian.py,sha256=ecaZcgqXyLvJtT2J5QXw4qS9gY3d72mgUnV-0frJvhQ,724
|
29
|
+
novel_downloader/core/exporters/sfacg.py,sha256=j4_H-ixvDxd_OJfIvD4Lbs24LaiFjaYqhvhZcks-ItI,457
|
30
|
+
novel_downloader/core/exporters/yamibo.py,sha256=QaY13llqpyxIgmMnMVFtR5yFMIpyMHHdCmVDW4Dq-bo,462
|
31
|
+
novel_downloader/core/exporters/common/__init__.py,sha256=qIOZ_TgnnQZ6p45YQsxpTcB69e0Jq9XMG3IY0NBVsTM,274
|
32
|
+
novel_downloader/core/exporters/common/epub.py,sha256=1BhaZCZLehX-v8Z7spatyizhHoMfCF08ZfZGpPfB5Kw,6331
|
33
|
+
novel_downloader/core/exporters/common/main_exporter.py,sha256=-MRZEpAdsfdRt3VxIv4krMaw2UJnrvCnyj5Jde93zuA,3926
|
34
|
+
novel_downloader/core/exporters/common/txt.py,sha256=b5cNvH0hrjaBO89Uddn1IUY1BFhkHJdTd7WjSWk4ndk,4719
|
35
|
+
novel_downloader/core/exporters/epub_utils/__init__.py,sha256=cPtuQDtuJZPgOHRf_T5sgkQE13jZnOyPoK9hHJeMEEo,993
|
36
|
+
novel_downloader/core/exporters/epub_utils/css_builder.py,sha256=qvVgHnyoILgqSUoVsHv-cHzIdtfsqxA8WHt9_89puic,2145
|
37
|
+
novel_downloader/core/exporters/epub_utils/image_loader.py,sha256=hbxoPvXkBIZnoZSIlHwIUx4zWR8QVppWiH1KotMrBXg,3953
|
38
|
+
novel_downloader/core/exporters/epub_utils/initializer.py,sha256=TGueFff1ydRLdJYBEJnqIkoVCV57ZiR3dGu_c5Hrp8g,3364
|
39
|
+
novel_downloader/core/exporters/epub_utils/text_to_html.py,sha256=VSYbm33PrwxFmcT-2f_U2j3kuHzdcSMR7PRqOWvZICU,5617
|
40
|
+
novel_downloader/core/exporters/epub_utils/volume_intro.py,sha256=cwHMVwJeK8TzXnOw4MYWXvbZGt4iWFjdesDm4n_V-Tk,1830
|
41
|
+
novel_downloader/core/exporters/linovelib/__init__.py,sha256=zD7A7OhluipwICssnp27c_oenYozevZH9g0Qj5WOMWY,195
|
42
|
+
novel_downloader/core/exporters/linovelib/epub.py,sha256=wxfNxOX6kxSaove-YlDlNw1cmsBJFwysk6bS6Gsk8Cw,14503
|
43
|
+
novel_downloader/core/exporters/linovelib/main_exporter.py,sha256=cHkAp_jdF6uji5Avu1l8z6mR0nSrWYgX6ETDEezkjoE,3700
|
44
|
+
novel_downloader/core/exporters/linovelib/txt.py,sha256=ALlZUl5nNtg4OmYlurMC0acjmTOBV7G8c13DPrxbG4w,4407
|
45
|
+
novel_downloader/core/factory/__init__.py,sha256=_IY3N35onhWD_nw_TyxKOxa6e7Uak9Cv0bp4pK9yb0M,464
|
46
|
+
novel_downloader/core/factory/downloader.py,sha256=hNCp3IlZQzeTSLBMuO_Y_EzrAn9_-8SLBHcUwMw8ijM,2060
|
47
|
+
novel_downloader/core/factory/exporter.py,sha256=CjDJGnWBDk-S1zYntIDAEo1hLM2q55tlJOjTXKn0hAI,1533
|
48
|
+
novel_downloader/core/factory/fetcher.py,sha256=stfRJnh5ZXLqRsDtQC1BDeTe0yaZI-mgm3Qx03nWUP4,2402
|
49
|
+
novel_downloader/core/factory/parser.py,sha256=0PXepJhlE6aGs9_t81vyho1eCw84-6XRBGb98_phvSQ,2237
|
50
|
+
novel_downloader/core/fetchers/__init__.py,sha256=C1OykEdCzj3fpLRRhVrvwClpzz-pzTzTilH306crgYg,1440
|
51
|
+
novel_downloader/core/fetchers/base/__init__.py,sha256=p9be-q2YjiHcQhv4_KMeZmHgaAYYyUDWoBo6Gvwughc,224
|
52
|
+
novel_downloader/core/fetchers/base/browser.py,sha256=oR3ZMw71_LJrgTZXduVtZuXEkr7PZ9nxlS5ZlYavN_0,11153
|
53
|
+
novel_downloader/core/fetchers/base/rate_limiter.py,sha256=zUYH_PjnKfUzJpcbUPtMkwXxIlF0SH-ZTFlbCUrq060,2724
|
54
|
+
novel_downloader/core/fetchers/base/session.py,sha256=Elfpov2cqojunCrLaaSL9ZgWLNVanUDZvgOoIfk5sSc,13251
|
55
|
+
novel_downloader/core/fetchers/biquge/__init__.py,sha256=9EW4eerGeob4QGoDr11A8Mv7xvcfWVFU57M3VT9vzPI,236
|
56
|
+
novel_downloader/core/fetchers/biquge/browser.py,sha256=vplaCRAz8ECxk-yXm7DxSxW3EyX8GCYJMeImUut53RI,2390
|
57
|
+
novel_downloader/core/fetchers/biquge/session.py,sha256=waxv_dPsBl2SeudaINjt-eUwpW-FcDP2zFN_1-NXhr8,2400
|
58
|
+
novel_downloader/core/fetchers/common/__init__.py,sha256=ur_zQHrmJdPsFvpyC8AWjsZptHLbBHLb3EuKLt6LRVc,236
|
59
|
+
novel_downloader/core/fetchers/common/browser.py,sha256=RgNOizfgi_59Xaee6lTlpfiCMGjz_4luNDlHLQqUpl0,2289
|
60
|
+
novel_downloader/core/fetchers/common/session.py,sha256=Ydtwun9lPN4VEIIEIA7Skm6_GOiF_9VDUPkjGQQTdtM,2299
|
61
|
+
novel_downloader/core/fetchers/esjzone/__init__.py,sha256=Cr30WpKEnCrG_vVqttfI9T0zdkwDsLFOnCxQz4EAQQA,242
|
62
|
+
novel_downloader/core/fetchers/esjzone/browser.py,sha256=SPvbKURw2DkUAlOBLbklmRCFvDoI4tAUDwmBRo2Kuc8,6224
|
63
|
+
novel_downloader/core/fetchers/esjzone/session.py,sha256=hwvS9LMWm5PYHTTZqYkBgWqkVqkrCfQcaFh6NBICt1Q,7218
|
64
|
+
novel_downloader/core/fetchers/linovelib/__init__.py,sha256=sMNXSBvn8gaZxNX5x4Ork8RzXxL7PhuigquWx6zQ6A4,254
|
65
|
+
novel_downloader/core/fetchers/linovelib/browser.py,sha256=pXasjPCG18CXmWkXFh7Uw24HNlTiocSup5tKK42YGck,5515
|
66
|
+
novel_downloader/core/fetchers/linovelib/session.py,sha256=y-R2FzKf0dpffUATI-xTKvq1S2wvQWA50H1avuqUrGM,5525
|
67
|
+
novel_downloader/core/fetchers/qianbi/__init__.py,sha256=h4Rve7fO1GcSJ-DlNC5zw7fjoldJy4chG9RZQf5DuCU,236
|
68
|
+
novel_downloader/core/fetchers/qianbi/browser.py,sha256=1EmrSwpqSYhEO_ID3RJbUaAOhcqvVnMnch6iOafXbTA,3162
|
69
|
+
novel_downloader/core/fetchers/qianbi/session.py,sha256=c3pJcgi9C1x9QYTBihvazHcgT7XTp2HBYfStTn6gSEg,3141
|
70
|
+
novel_downloader/core/fetchers/qidian/__init__.py,sha256=2LshlX82lFpWZMV6yujHsfue9KM0-F1O3HvMCopIv9M,236
|
71
|
+
novel_downloader/core/fetchers/qidian/browser.py,sha256=JuFncpirI4HLyfIkR0xZmHL6AZZy7tQOzkzsC24b9ss,8578
|
72
|
+
novel_downloader/core/fetchers/qidian/session.py,sha256=WrHsov15PoRDYbb1ZRaScJQGRZv6axz9_hVEC1Wt1PM,9746
|
73
|
+
novel_downloader/core/fetchers/sfacg/__init__.py,sha256=bQAIwERsX9XOKrP2LteFKX8Jlhw4oeUNwpZTHXn5RRg,230
|
74
|
+
novel_downloader/core/fetchers/sfacg/browser.py,sha256=15PVS75PxEKR5W7mQbqVxoN0d4V1XVYVF0l1yy_sv_Y,5681
|
75
|
+
novel_downloader/core/fetchers/sfacg/session.py,sha256=9K4emQCRq45vzYn-ZDX549tK2F92x2CBMp4ODohNOjc,5085
|
76
|
+
novel_downloader/core/fetchers/yamibo/__init__.py,sha256=5ds6DNNvpo6F6U5dboEaIsJoKSPorkPte_HWVnXMdXo,236
|
77
|
+
novel_downloader/core/fetchers/yamibo/browser.py,sha256=7YRrWbA8_cOcT_z-VjMWP6FUg30TwV6eLW4zJZ_UxSE,7249
|
78
|
+
novel_downloader/core/fetchers/yamibo/session.py,sha256=434EArdKgEYIBZkb1nMub3PQXdRTS-Ov2_1u9MESjOs,7212
|
79
|
+
novel_downloader/core/interfaces/__init__.py,sha256=hB1SjBzuN7qnZx_h3RV4w_roj3ZwShbIG3CV9jGMB14,602
|
80
|
+
novel_downloader/core/interfaces/downloader.py,sha256=XozFf-7OOtBQDlWNs3IRcBjwTPGFWwseFLGta-sZZmU,1560
|
81
|
+
novel_downloader/core/interfaces/exporter.py,sha256=zwIaJ5FXo_JmKYg2UZV9FTWX7xZ2e0QuL4RTNGRtI04,1610
|
82
|
+
novel_downloader/core/interfaces/fetcher.py,sha256=XlP3d-Q_xvuVextZCdLOxDf8BwBbx799L_WLJx0WTB8,4096
|
83
|
+
novel_downloader/core/interfaces/parser.py,sha256=iZeUgNl-zE-wsf1eW4GVCPjEaLSvQrNJi_mVEOU9ulY,1353
|
84
|
+
novel_downloader/core/parsers/__init__.py,sha256=lrpt5E1YMiI0WY_cco1lEDhBQZJ_ZEV4b5fR6Fs3ZwA,832
|
85
|
+
novel_downloader/core/parsers/base.py,sha256=GifJANFm0auYyzYuqYox9LFgDskW8G2vR0DaMrRcG1w,2962
|
86
|
+
novel_downloader/core/parsers/biquge/__init__.py,sha256=oaLgBLdMW7DcdsEGXW-S91Z6_p5XmBcBIp7TX79hmV4,173
|
87
|
+
novel_downloader/core/parsers/biquge/main_parser.py,sha256=mbrEjJ8iSvWZ7SU4RH8pHxs1jnEwwlag_KkhTYoU0sY,4572
|
88
|
+
novel_downloader/core/parsers/common/__init__.py,sha256=MzNUUxvf7jmeO0LvQ_FRW0QLKuYVXkkTgJ4CxWZKF-Y,341
|
89
|
+
novel_downloader/core/parsers/common/helper.py,sha256=U5SzhVJJ5lGRNhLoOdEQw9LfBuPv17dmyT_MbdgnCl0,12052
|
90
|
+
novel_downloader/core/parsers/common/main_parser.py,sha256=znuXTJC-TXsgBTB3Hyqi87L65bqyM90TYyjU1KEhswc,3229
|
91
|
+
novel_downloader/core/parsers/esjzone/__init__.py,sha256=RSsUdOvaiqv-rTaYVc-qO25jytRCj9X2EYErMltA_b8,177
|
92
|
+
novel_downloader/core/parsers/esjzone/main_parser.py,sha256=jF7WPAwN5S2uUOdXk3fCkM3PSS5DPhI-SzmP00GFItw,8520
|
93
|
+
novel_downloader/core/parsers/linovelib/__init__.py,sha256=t5xzMEb4Q9MZxOvedOnot2HR6nCtU5YnAxGUk2lJoMA,185
|
94
|
+
novel_downloader/core/parsers/linovelib/main_parser.py,sha256=LqC6W-Lk7sdbiqhYvqQAh2z31v23OtMzyp1kAelsugI,7565
|
95
|
+
novel_downloader/core/parsers/qianbi/__init__.py,sha256=CNmoER8U2u4-ix5S0DDq-pHTtkLR0IZf2SLaTTYXee4,173
|
96
|
+
novel_downloader/core/parsers/qianbi/main_parser.py,sha256=kMjGew_dmqjI9oIThyHgxThZZgS3IaESB_tNf1nkCKk,5069
|
97
|
+
novel_downloader/core/parsers/qidian/__init__.py,sha256=fWWFeyythX0gpDCJ-2AslrRl2hq4vW2bx9hHh1W7mAw,173
|
98
|
+
novel_downloader/core/parsers/qidian/book_info_parser.py,sha256=h5oAVJOOSZMV4U2GnSezVHPJOEUKUic_oD2gl94mEPQ,3721
|
99
|
+
novel_downloader/core/parsers/qidian/chapter_encrypted.py,sha256=VhPDERJq1ROJaBlaJuCXJGffisOxkeYFDUKXHo31HfU,18263
|
100
|
+
novel_downloader/core/parsers/qidian/chapter_normal.py,sha256=6mD86OalpxiCDhjzUjcfFYsgmnTRU_rMIgFN8_Ceu50,4453
|
101
|
+
novel_downloader/core/parsers/qidian/chapter_router.py,sha256=foVMlWtE-qUOvJD_4EDiuAVaNkFdeV_ZTCvS5IL7Orc,1957
|
102
|
+
novel_downloader/core/parsers/qidian/main_parser.py,sha256=SPU6sUO8e4Gp_1q2WypuUQYEyHhoXM7OiRsthhFT6SM,4396
|
103
|
+
novel_downloader/core/parsers/qidian/utils/__init__.py,sha256=HfjXrGAwH_ceRSE4m88Dl9qb7vHMGcPFxxTU3qrTld8,548
|
104
|
+
novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py,sha256=8ytJnAfiJIxj0wlke9UwYA6vngUyLxVZt8PbfkNUhss,4687
|
105
|
+
novel_downloader/core/parsers/qidian/utils/helpers.py,sha256=-7vd1BMu5pVFCRySfPWyrItVbZ2wrHPNY8iAQEP7T_8,3264
|
106
|
+
novel_downloader/core/parsers/qidian/utils/node_decryptor.py,sha256=gjqirr5RECScFw0C6DET7ZMaLTcqGcPOmlkwFUJbTHQ,5965
|
107
|
+
novel_downloader/core/parsers/sfacg/__init__.py,sha256=O2nscvtOweMXHMONdvySTsLSy1ulhv53WTp4r6J47tI,169
|
108
|
+
novel_downloader/core/parsers/sfacg/main_parser.py,sha256=yW18MALAZisJdFO-7peI1h-4XVloEDXeCJvXUz5hJ1A,5899
|
109
|
+
novel_downloader/core/parsers/yamibo/__init__.py,sha256=KJ_fCcakoQrsG36OOd0paXXB1cAIwMirKaA8ZLUKUKI,173
|
110
|
+
novel_downloader/core/parsers/yamibo/main_parser.py,sha256=9sNXsDR2iDVyTYupP_7PyE7BXf2po3sZLq1XEFA8DrI,6554
|
111
|
+
novel_downloader/locales/en.json,sha256=-bKxndkwJCTCt7ZZGRRKzNaulC7z8XB6Tu7T1SR-1S8,6840
|
112
|
+
novel_downloader/locales/zh.json,sha256=xzbUsKtkdQvQkehTgIURlQMPepOSWbQBgzTJ4SSJNZc,6699
|
113
|
+
novel_downloader/models/__init__.py,sha256=G5fYGdaFquJBcllFJ7-YgqkvP4vD3xVEI9MeYcrCr_s,1068
|
114
|
+
novel_downloader/models/browser.py,sha256=ly-jM7izQ77yTIG-oau51HJofDpBfrXpIJZJjoQyad8,435
|
115
|
+
novel_downloader/models/chapter.py,sha256=bdAQUDZIuuTVxoYjoOJrbS2u81b1B2mkuZkTSf0m2HQ,492
|
116
|
+
novel_downloader/models/config.py,sha256=d5G8sob9oNA8rr1N7BvDEJRVSCKJUtD_QBcvWZvGMyw,2792
|
117
|
+
novel_downloader/models/login.py,sha256=sY2Jom6PLpA9Z3Uy7plZKhda3Gq7awKOOIIaQ79PpWs,371
|
118
|
+
novel_downloader/models/site_rules.py,sha256=kzDB5F8lf4udAO0WVUrgBOR7ave3jsMBxt7cEoG0bnI,2721
|
119
|
+
novel_downloader/models/tasks.py,sha256=e4DYEXQQQewgQyCCHfc0UYnkPJ96LafmhG3oO5MQP0Q,465
|
120
|
+
novel_downloader/models/types.py,sha256=q1KDuGW0SVxQILKKoPXKRecfaKe2m8jUM0nyaeDJ6dE,394
|
121
|
+
novel_downloader/resources/config/settings.toml,sha256=A2B_EMh0zjTLi6UBCjhX__igz7xLCXnCqDzJMhiZn8E,4491
|
122
|
+
novel_downloader/resources/css_styles/main.css,sha256=WM6GePwdOGgM86fbbOxQ0_0oerTBDZeQHt8zRVfcJp8,1617
|
123
|
+
novel_downloader/resources/css_styles/volume-intro.css,sha256=6gaUnNKkrb2w8tYJRq1BGD1FwbhT1I5W2GI_Zelo9G4,1156
|
124
|
+
novel_downloader/resources/images/volume_border.png,sha256=2dEVimnTHKOfLMhi7bhkh_5joWNnrqg8duomLSNOZx4,28613
|
125
|
+
novel_downloader/resources/js_scripts/qidian_decrypt_node.js,sha256=spNrk_gXI7pPW9abr4XGc2LASMe1UuN4BUe4cH24L8s,2195
|
126
|
+
novel_downloader/resources/json/linovelib_font_map.json,sha256=F1IlEcvXGcagnZCu4Gw2vQ2NLnhy6cJOLhabukqnftw,67854
|
127
|
+
novel_downloader/resources/json/replace_word_map.json,sha256=ptL9sGO9aK7rnnAaOIyZ0OiH7gaT0BhFzficzYZSDks,55
|
128
|
+
novel_downloader/resources/text/blacklist.txt,sha256=sovK9JgARZP3lud5b1EZgvv8LSVKPthf4ADpCSZZgQ8,154
|
129
|
+
novel_downloader/tui/__init__.py,sha256=8RB8tBrPcoBzm1tpQlgZqnOZXrdHmlzMRxuk9wsN4m0,115
|
130
|
+
novel_downloader/tui/app.py,sha256=ytV1u15nGCRj_ff_GeAL3W1XlU6r5Lh_k3HBcAjPRx0,731
|
131
|
+
novel_downloader/tui/main.py,sha256=MBP8SrwEYTpGQm-V9W_4rKnTeslneORfkzFsU3Xj2yA,256
|
132
|
+
novel_downloader/tui/screens/__init__.py,sha256=QsUM5cUEKm7nluQh9acEt37xRWbkZU3vqIpBduepDCU,203
|
133
|
+
novel_downloader/tui/screens/home.py,sha256=ximy5vwHGrkUD88U6Gr9h3kT-wtOMMLBzB9aEZPuA5w,6716
|
134
|
+
novel_downloader/tui/screens/login.py,sha256=eEVmQFZKQX8mCt_qp96QK8t2pB15FeUrk_oV3jm_Mz4,2224
|
135
|
+
novel_downloader/tui/styles/home_layout.tcss,sha256=VNJs339qiwNUuqwwdK6VkYThCdsqlw-2mEoZVCspdrw,974
|
136
|
+
novel_downloader/tui/widgets/richlog_handler.py,sha256=bhFb0E7Z7-dRS07y_vMjxjPeCic9AD59MFPLhef_R5g,572
|
137
|
+
novel_downloader/utils/__init__.py,sha256=4iUXNUzxeAnGmpGWsB4K_jckUYEW0u_LqWp_OM7mtK8,78
|
138
|
+
novel_downloader/utils/cache.py,sha256=_jVEWAaMGY86kWVnAuuIvJA_hA8dH2ClI7o3p99mEvE,618
|
139
|
+
novel_downloader/utils/chapter_storage.py,sha256=wXXIzNjs1GfPPoqgYYPnQ9Two23McW6ZZNDmhfSC9aY,9831
|
140
|
+
novel_downloader/utils/constants.py,sha256=1emMOmGRuat0yX8ozZMM1pAUGdU0kYBhDVNW_6dDtps,5700
|
141
|
+
novel_downloader/utils/cookies.py,sha256=WuPBt_z7cF4n7QPIw1julATWt6dbDRCbNdgXHSikmjo,2042
|
142
|
+
novel_downloader/utils/crypto_utils.py,sha256=BRlVR9Nvbu8TQXocJb3po1-kD5HkbCV0yyT84nq_XtI,2052
|
143
|
+
novel_downloader/utils/hash_store.py,sha256=HfzthzcKbHbVaHNpqjaAs2wDeq7iIeY8Mzkt_4v80jQ,9388
|
144
|
+
novel_downloader/utils/hash_utils.py,sha256=7eC7WsO_kl25OnRYWzIXbCXsewxvCcvRCzetsf-wbTo,3023
|
145
|
+
novel_downloader/utils/i18n.py,sha256=pdAcSIA5Tp-uPEBwNByHL7C1NayTnpOsl7zFv9p2G1k,1033
|
146
|
+
novel_downloader/utils/logger.py,sha256=9h1iFS8_auiquNgOBd-Q2pbbcnAhAKL39yf3PKadu00,3339
|
147
|
+
novel_downloader/utils/model_loader.py,sha256=JKgRFrr4HlAW9zuDUBAuuo_Kk_T_g9dWiU8E3zYk0vo,1996
|
148
|
+
novel_downloader/utils/network.py,sha256=W0SVr55MSUjTmMPkUvvkH10SRgFx3GWrCN_fDavfk4A,9143
|
149
|
+
novel_downloader/utils/state.py,sha256=FcNJ85GvBu7uEIjy0QHGr4sXMbHPEMkCjwUKNg5EabI,5132
|
150
|
+
novel_downloader/utils/file_utils/__init__.py,sha256=zvOm2qSEmWd_mRGJceGBZb5MYMSDAlWYjS5MkVQNZgI,1159
|
151
|
+
novel_downloader/utils/file_utils/io.py,sha256=AZ3NUe6lifGsYt3iYyXyQ2BO41WV8j013LpZy4KSjJQ,7473
|
152
|
+
novel_downloader/utils/file_utils/normalize.py,sha256=MrsCq4FqmskKRkHRV_J0z0dmn69OerMum-9sqx2XOGM,2023
|
153
|
+
novel_downloader/utils/file_utils/sanitize.py,sha256=rE-u4vpDL10zH8FT8d9wqwWsz-7dR6PJ-LE45K8VaeE,2112
|
154
|
+
novel_downloader/utils/fontocr/__init__.py,sha256=fe-04om3xxBvFKt5BBCApXCzv-Z0K_AY7lv9IB1jEHM,543
|
155
|
+
novel_downloader/utils/fontocr/ocr_v1.py,sha256=bwkvqKXUcKsgBCrag8jHuIl8AOM_MbV28ZSQ_aO_X6s,11245
|
156
|
+
novel_downloader/utils/fontocr/ocr_v2.py,sha256=OJ_egORHa9KwVJX4kEABR25D7RRF0jVCRV4WgHUal7M,27307
|
157
|
+
novel_downloader/utils/text_utils/__init__.py,sha256=JQtEnJ22K9o_syY5PV4Bf_p4BKZonX5g9-A5eqlxpZs,806
|
158
|
+
novel_downloader/utils/text_utils/chapter_formatting.py,sha256=WAAEAcI7zI_uIeARDybZfXDdMvGio3VIkANFrK8-8Os,1378
|
159
|
+
novel_downloader/utils/text_utils/diff_display.py,sha256=aUvjMcYO-1_P8ZYiYbmYbJOByKo2bWoBV_ifRuAqwb8,2528
|
160
|
+
novel_downloader/utils/text_utils/font_mapping.py,sha256=Aos5skBhowDdPgnYmK0bpLtNm2hZg3RolNlTkxC9kO8,865
|
161
|
+
novel_downloader/utils/text_utils/text_cleaning.py,sha256=_Nahr8iv3341IyDXW-KpTn4XNG2hB-HajSM52pysPu8,1630
|
162
|
+
novel_downloader/utils/time_utils/__init__.py,sha256=725vY2PvqFhjbAz0hCOuIuhSCK8HrEqQ_k3YwvubmXo,624
|
163
|
+
novel_downloader/utils/time_utils/datetime_utils.py,sha256=1eyX8lTEqkQ-rEej_GrhbUpaIR5tsFdVSKT-q8s9X-g,4927
|
164
|
+
novel_downloader/utils/time_utils/sleep_utils.py,sha256=C4XYeAtxoVZC9Ju6vhhP9sbOrSpdZG2Nm-x1IYO_OFA,3233
|
165
|
+
novel_downloader-1.4.0.dist-info/licenses/LICENSE,sha256=XgmnH0mBf-qEiizoVAfJQAKzPB9y3rBa-ni7M0Aqv4A,1066
|
166
|
+
novel_downloader-1.4.0.dist-info/METADATA,sha256=iFXirg0_BDhczHRV37P5QgtbuUawakAx1kzY1aAfQeU,7027
|
167
|
+
novel_downloader-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
168
|
+
novel_downloader-1.4.0.dist-info/entry_points.txt,sha256=u1Ns5xI_QJyL4HAFCgJvJdib9ugu7M9I2tnQwZjJxrk,112
|
169
|
+
novel_downloader-1.4.0.dist-info/top_level.txt,sha256=hP4jYWM2LTm1jxsW4hqEB8N0dsRvldO2QdhggJT917I,17
|
170
|
+
novel_downloader-1.4.0.dist-info/RECORD,,
|
@@ -1,66 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.cli.interactive
|
4
|
-
--------------------------------
|
5
|
-
|
6
|
-
Interactive CLI mode for novel_downloader.
|
7
|
-
Supports multilingual prompt, input validation, and quit control.
|
8
|
-
"""
|
9
|
-
|
10
|
-
import click
|
11
|
-
from click import Context
|
12
|
-
|
13
|
-
from novel_downloader.cli.download import download_cli
|
14
|
-
from novel_downloader.utils.i18n import t
|
15
|
-
|
16
|
-
|
17
|
-
@click.group( # type: ignore
|
18
|
-
name="interactive", help=t("interactive_help"), invoke_without_command=True
|
19
|
-
)
|
20
|
-
@click.pass_context # type: ignore
|
21
|
-
def interactive_cli(ctx: Context) -> None:
|
22
|
-
"""Interactive mode for novel selection and preview."""
|
23
|
-
if ctx.invoked_subcommand is None:
|
24
|
-
click.echo(t("interactive_no_sub"))
|
25
|
-
|
26
|
-
options = [
|
27
|
-
t("interactive_option_download"),
|
28
|
-
t("interactive_option_browse"),
|
29
|
-
t("interactive_option_preview"),
|
30
|
-
t("interactive_option_exit"),
|
31
|
-
]
|
32
|
-
for idx, opt in enumerate(options, 1):
|
33
|
-
click.echo(f"{idx}. {opt}")
|
34
|
-
|
35
|
-
choice = click.prompt(t("interactive_prompt_choice"), type=int)
|
36
|
-
|
37
|
-
if choice == 1:
|
38
|
-
default_site = "qidian"
|
39
|
-
site: str = click.prompt(
|
40
|
-
t("download_option_site", default=default_site),
|
41
|
-
default_site,
|
42
|
-
)
|
43
|
-
ids_input: str = click.prompt(t("interactive_prompt_book_ids"))
|
44
|
-
book_ids = ids_input.strip().split()
|
45
|
-
ctx.invoke(download_cli, book_ids=book_ids, site=site)
|
46
|
-
elif choice == 2:
|
47
|
-
ctx.invoke(browse)
|
48
|
-
elif choice == 3:
|
49
|
-
ctx.invoke(preview)
|
50
|
-
else:
|
51
|
-
click.echo(t("interactive_exit"))
|
52
|
-
return
|
53
|
-
|
54
|
-
|
55
|
-
@interactive_cli.command(help=t("interactive_browse_help")) # type: ignore
|
56
|
-
@click.pass_context # type: ignore
|
57
|
-
def browse(ctx: Context) -> None:
|
58
|
-
"""Browse available novels interactively."""
|
59
|
-
click.echo(t("interactive_browse_start"))
|
60
|
-
|
61
|
-
|
62
|
-
@interactive_cli.command(help=t("interactive_preview_help")) # type: ignore
|
63
|
-
@click.pass_context # type: ignore
|
64
|
-
def preview(ctx: Context) -> None:
|
65
|
-
"""Preview chapters before downloading."""
|
66
|
-
click.echo(t("interactive_preview_start"))
|
novel_downloader/cli/settings.py
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.cli.settings
|
4
|
-
-----------------------------
|
5
|
-
|
6
|
-
Commands to configure novel downloader settings.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import shutil
|
10
|
-
from importlib.resources import as_file
|
11
|
-
from pathlib import Path
|
12
|
-
|
13
|
-
import click
|
14
|
-
from click import Context
|
15
|
-
|
16
|
-
from novel_downloader.config import save_config_file, save_rules_as_json
|
17
|
-
from novel_downloader.utils.constants import DEFAULT_SETTINGS_PATHS
|
18
|
-
from novel_downloader.utils.i18n import t
|
19
|
-
from novel_downloader.utils.logger import setup_logging
|
20
|
-
from novel_downloader.utils.state import state_mgr
|
21
|
-
|
22
|
-
|
23
|
-
@click.group(name="settings", help=t("settings_help")) # type: ignore
|
24
|
-
def settings_cli() -> None:
|
25
|
-
"""Configure downloader settings."""
|
26
|
-
setup_logging()
|
27
|
-
pass
|
28
|
-
|
29
|
-
|
30
|
-
@settings_cli.command(name="init", help=t("settings_init_help")) # type: ignore
|
31
|
-
@click.option("--force", is_flag=True, help=t("settings_init_force_help")) # type: ignore
|
32
|
-
def init_settings(force: bool) -> None:
|
33
|
-
"""Initialize default settings and rules in the current directory."""
|
34
|
-
cwd = Path.cwd()
|
35
|
-
|
36
|
-
for resource in DEFAULT_SETTINGS_PATHS:
|
37
|
-
target_path = cwd / resource.name
|
38
|
-
should_copy = True
|
39
|
-
|
40
|
-
if target_path.exists():
|
41
|
-
if force:
|
42
|
-
should_copy = True
|
43
|
-
click.echo(t("settings_init_overwrite", filename=resource.name))
|
44
|
-
else:
|
45
|
-
click.echo(t("settings_init_exists", filename=resource.name))
|
46
|
-
should_copy = click.confirm(
|
47
|
-
t("settings_init_confirm_overwrite", filename=resource.name),
|
48
|
-
default=False,
|
49
|
-
)
|
50
|
-
|
51
|
-
if not should_copy:
|
52
|
-
click.echo(t("settings_init_skip", filename=resource.name))
|
53
|
-
continue
|
54
|
-
|
55
|
-
try:
|
56
|
-
with as_file(resource) as actual_path:
|
57
|
-
shutil.copy(actual_path, target_path)
|
58
|
-
click.echo(t("settings_init_copy", filename=resource.name))
|
59
|
-
except Exception as e:
|
60
|
-
raise click.ClickException(
|
61
|
-
t("settings_init_error", filename=resource.name, err=e)
|
62
|
-
) from e
|
63
|
-
|
64
|
-
|
65
|
-
@settings_cli.command(name="set-lang", help=t("settings_set_lang_help")) # type: ignore
|
66
|
-
@click.argument("lang", type=click.Choice(["zh", "en"])) # type: ignore
|
67
|
-
@click.pass_context # type: ignore
|
68
|
-
def set_language(ctx: Context, lang: str) -> None:
|
69
|
-
"""Switch language between Chinese and English."""
|
70
|
-
state_mgr.set_language(lang)
|
71
|
-
click.echo(t("settings_set_lang", lang=lang))
|
72
|
-
|
73
|
-
|
74
|
-
@settings_cli.command(name="set-config", help=t("settings_set_config_help")) # type: ignore
|
75
|
-
@click.argument("path", type=click.Path(exists=True, dir_okay=False, resolve_path=True)) # type: ignore
|
76
|
-
def set_config(path: str) -> None:
|
77
|
-
"""Set and save a custom YAML configuration file."""
|
78
|
-
try:
|
79
|
-
save_config_file(path)
|
80
|
-
click.echo(t("settings_set_config", path=path))
|
81
|
-
except Exception as e:
|
82
|
-
raise click.ClickException(t("settings_set_config_fail", err=e)) from e
|
83
|
-
|
84
|
-
|
85
|
-
@settings_cli.command(name="update-rules", help=t("settings_update_rules_help")) # type: ignore
|
86
|
-
@click.argument("path", type=click.Path(exists=True, dir_okay=False, resolve_path=True)) # type: ignore
|
87
|
-
def update_rules(path: str) -> None:
|
88
|
-
"""Update site rules from a TOML/YAML/JSON file."""
|
89
|
-
try:
|
90
|
-
save_rules_as_json(path)
|
91
|
-
click.echo(t("settings_update_rules", path=path))
|
92
|
-
except Exception as e:
|
93
|
-
raise click.ClickException(t("settings_update_rules_fail", err=e)) from e
|
94
|
-
|
95
|
-
|
96
|
-
@settings_cli.command(
|
97
|
-
name="set-cookies", help=t("settings_set_cookies_help")
|
98
|
-
) # type: ignore
|
99
|
-
@click.argument("site", required=False) # type: ignore
|
100
|
-
@click.argument("cookies", required=False) # type: ignore
|
101
|
-
@click.pass_context # type: ignore
|
102
|
-
def set_cookies(ctx: Context, site: str, cookies: str) -> None:
|
103
|
-
"""
|
104
|
-
Set or update cookies for a site.
|
105
|
-
|
106
|
-
:param site: Site identifier (e.g. 'qidian', 'bqg').
|
107
|
-
If omitted, you will be prompted to enter it.
|
108
|
-
:param cookies: Cookie payload. Can be a JSON string (e.g. '{"k":"v"}')
|
109
|
-
or a browser-style string 'k1=v1; k2=v2'.
|
110
|
-
If omitted, you will be prompted to enter it.
|
111
|
-
"""
|
112
|
-
if not site:
|
113
|
-
site = click.prompt(t("settings_set_cookies_prompt_site"), type=str)
|
114
|
-
if not cookies:
|
115
|
-
cookies = click.prompt(t("settings_set_cookies_prompt_payload"), type=str)
|
116
|
-
|
117
|
-
try:
|
118
|
-
state_mgr.set_cookies(site, cookies)
|
119
|
-
click.echo(t("settings_set_cookies_success", site=site))
|
120
|
-
except Exception as e:
|
121
|
-
raise click.ClickException(t("settings_set_cookies_fail", err=e)) from e
|
122
|
-
|
123
|
-
|
124
|
-
@settings_cli.command(name="add-hash", help=t("settings_add_hash_help")) # type: ignore
|
125
|
-
@click.option(
|
126
|
-
"--path",
|
127
|
-
type=click.Path(exists=True, dir_okay=False),
|
128
|
-
help=t("settings_add_hash_path_help"),
|
129
|
-
) # type: ignore
|
130
|
-
def add_image_hashes(path: str | None) -> None:
|
131
|
-
"""
|
132
|
-
Add image hashes to internal store for matching.
|
133
|
-
Can be run in interactive mode (no --path), or with a JSON file.
|
134
|
-
"""
|
135
|
-
from novel_downloader.utils.hash_store import img_hash_store
|
136
|
-
|
137
|
-
if path:
|
138
|
-
try:
|
139
|
-
img_hash_store.add_from_map(path)
|
140
|
-
img_hash_store.save()
|
141
|
-
click.echo(t("settings_add_hash_loaded", path=path))
|
142
|
-
except Exception as e:
|
143
|
-
raise click.ClickException(
|
144
|
-
t("settings_add_hash_load_fail", err=str(e))
|
145
|
-
) from e
|
146
|
-
else:
|
147
|
-
click.echo(t("settings_add_hash_prompt_tip"))
|
148
|
-
while True:
|
149
|
-
img_path = click.prompt(
|
150
|
-
t("settings_add_hash_prompt_img"),
|
151
|
-
type=str,
|
152
|
-
default="",
|
153
|
-
show_default=False,
|
154
|
-
).strip()
|
155
|
-
if not img_path or img_path.lower() in {"exit", "quit"}:
|
156
|
-
break
|
157
|
-
if not Path(img_path).exists():
|
158
|
-
click.echo(t("settings_add_hash_path_invalid"))
|
159
|
-
continue
|
160
|
-
|
161
|
-
label = click.prompt(
|
162
|
-
t("settings_add_hash_prompt_label"),
|
163
|
-
type=str,
|
164
|
-
default="",
|
165
|
-
show_default=False,
|
166
|
-
).strip()
|
167
|
-
if not label or label.lower() in {"exit", "quit"}:
|
168
|
-
break
|
169
|
-
|
170
|
-
try:
|
171
|
-
img_hash_store.add_image(img_path, label)
|
172
|
-
click.echo(t("settings_add_hash_added", img=img_path, label=label))
|
173
|
-
except Exception as e:
|
174
|
-
click.echo(t("settings_add_hash_failed", err=str(e)))
|
175
|
-
|
176
|
-
img_hash_store.save()
|
177
|
-
click.echo(t("settings_add_hash_saved"))
|