novel-downloader 2.0.0__py3-none-any.whl → 2.0.2__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/download.py +14 -11
- novel_downloader/cli/export.py +19 -19
- novel_downloader/cli/ui.py +35 -8
- novel_downloader/config/adapter.py +216 -153
- novel_downloader/core/__init__.py +5 -6
- novel_downloader/core/archived/deqixs/fetcher.py +1 -28
- novel_downloader/core/downloaders/__init__.py +2 -0
- novel_downloader/core/downloaders/base.py +34 -85
- novel_downloader/core/downloaders/common.py +147 -171
- novel_downloader/core/downloaders/qianbi.py +30 -64
- novel_downloader/core/downloaders/qidian.py +157 -184
- novel_downloader/core/downloaders/qqbook.py +292 -0
- novel_downloader/core/downloaders/registry.py +2 -2
- novel_downloader/core/exporters/__init__.py +2 -0
- novel_downloader/core/exporters/base.py +37 -59
- novel_downloader/core/exporters/common.py +620 -0
- novel_downloader/core/exporters/linovelib.py +47 -0
- novel_downloader/core/exporters/qidian.py +41 -12
- novel_downloader/core/exporters/qqbook.py +28 -0
- novel_downloader/core/exporters/registry.py +2 -2
- novel_downloader/core/fetchers/__init__.py +4 -2
- novel_downloader/core/fetchers/aaatxt.py +2 -22
- novel_downloader/core/fetchers/b520.py +3 -23
- novel_downloader/core/fetchers/base.py +80 -105
- novel_downloader/core/fetchers/biquyuedu.py +2 -22
- novel_downloader/core/fetchers/dxmwx.py +10 -22
- novel_downloader/core/fetchers/esjzone.py +6 -29
- novel_downloader/core/fetchers/guidaye.py +2 -22
- novel_downloader/core/fetchers/hetushu.py +9 -29
- novel_downloader/core/fetchers/i25zw.py +2 -16
- novel_downloader/core/fetchers/ixdzs8.py +2 -16
- novel_downloader/core/fetchers/jpxs123.py +2 -16
- novel_downloader/core/fetchers/lewenn.py +2 -22
- novel_downloader/core/fetchers/linovelib.py +4 -20
- novel_downloader/core/fetchers/{eightnovel.py → n8novel.py} +12 -40
- novel_downloader/core/fetchers/piaotia.py +2 -16
- novel_downloader/core/fetchers/qbtr.py +2 -16
- novel_downloader/core/fetchers/qianbi.py +1 -20
- novel_downloader/core/fetchers/qidian.py +27 -68
- novel_downloader/core/fetchers/qqbook.py +177 -0
- novel_downloader/core/fetchers/quanben5.py +9 -29
- novel_downloader/core/fetchers/rate_limiter.py +22 -53
- novel_downloader/core/fetchers/sfacg.py +3 -16
- novel_downloader/core/fetchers/shencou.py +2 -16
- novel_downloader/core/fetchers/shuhaige.py +2 -22
- novel_downloader/core/fetchers/tongrenquan.py +2 -22
- novel_downloader/core/fetchers/ttkan.py +3 -14
- novel_downloader/core/fetchers/wanbengo.py +2 -22
- novel_downloader/core/fetchers/xiaoshuowu.py +2 -16
- novel_downloader/core/fetchers/xiguashuwu.py +4 -20
- novel_downloader/core/fetchers/xs63b.py +3 -15
- novel_downloader/core/fetchers/xshbook.py +2 -22
- novel_downloader/core/fetchers/yamibo.py +4 -28
- novel_downloader/core/fetchers/yibige.py +13 -26
- novel_downloader/core/interfaces/exporter.py +19 -7
- novel_downloader/core/interfaces/fetcher.py +23 -49
- novel_downloader/core/interfaces/parser.py +2 -2
- novel_downloader/core/parsers/__init__.py +4 -2
- novel_downloader/core/parsers/b520.py +2 -2
- novel_downloader/core/parsers/base.py +5 -39
- novel_downloader/core/parsers/esjzone.py +3 -3
- novel_downloader/core/parsers/{eightnovel.py → n8novel.py} +7 -7
- novel_downloader/core/parsers/qidian.py +717 -0
- novel_downloader/core/parsers/qqbook.py +709 -0
- novel_downloader/core/parsers/xiguashuwu.py +8 -15
- novel_downloader/core/searchers/__init__.py +2 -2
- novel_downloader/core/searchers/b520.py +1 -1
- novel_downloader/core/searchers/base.py +2 -2
- novel_downloader/core/searchers/{eightnovel.py → n8novel.py} +5 -5
- novel_downloader/locales/en.json +3 -3
- novel_downloader/locales/zh.json +3 -3
- novel_downloader/models/__init__.py +2 -0
- novel_downloader/models/book.py +1 -0
- novel_downloader/models/config.py +12 -0
- novel_downloader/resources/config/settings.toml +23 -5
- novel_downloader/resources/js_scripts/expr_to_json.js +14 -0
- novel_downloader/resources/js_scripts/qidian_decrypt_node.js +21 -16
- novel_downloader/resources/js_scripts/qq_decrypt_node.js +92 -0
- novel_downloader/utils/__init__.py +0 -2
- novel_downloader/utils/chapter_storage.py +2 -3
- novel_downloader/utils/constants.py +7 -3
- novel_downloader/utils/cookies.py +32 -17
- novel_downloader/utils/crypto_utils/__init__.py +0 -6
- novel_downloader/utils/crypto_utils/aes_util.py +1 -1
- novel_downloader/utils/crypto_utils/rc4.py +40 -50
- novel_downloader/utils/epub/__init__.py +2 -3
- novel_downloader/utils/epub/builder.py +6 -6
- novel_downloader/utils/epub/constants.py +1 -6
- novel_downloader/utils/epub/documents.py +7 -7
- novel_downloader/utils/epub/models.py +8 -8
- novel_downloader/utils/epub/utils.py +10 -10
- novel_downloader/utils/file_utils/io.py +48 -73
- novel_downloader/utils/file_utils/normalize.py +1 -7
- novel_downloader/utils/file_utils/sanitize.py +4 -11
- novel_downloader/utils/fontocr/__init__.py +13 -0
- novel_downloader/utils/{fontocr.py → fontocr/core.py} +72 -61
- novel_downloader/utils/fontocr/loader.py +52 -0
- novel_downloader/utils/logger.py +80 -56
- novel_downloader/utils/network.py +16 -40
- novel_downloader/utils/node_decryptor/__init__.py +13 -0
- novel_downloader/utils/node_decryptor/decryptor.py +342 -0
- novel_downloader/{core/parsers/qidian/utils → utils/node_decryptor}/decryptor_fetcher.py +5 -6
- novel_downloader/utils/text_utils/text_cleaner.py +39 -30
- novel_downloader/utils/text_utils/truncate_utils.py +3 -14
- novel_downloader/utils/time_utils/sleep_utils.py +53 -43
- novel_downloader/web/main.py +1 -1
- novel_downloader/web/pages/download.py +1 -1
- novel_downloader/web/pages/search.py +4 -4
- novel_downloader/web/services/task_manager.py +2 -0
- {novel_downloader-2.0.0.dist-info → novel_downloader-2.0.2.dist-info}/METADATA +5 -1
- novel_downloader-2.0.2.dist-info/RECORD +203 -0
- novel_downloader/core/exporters/common/__init__.py +0 -11
- novel_downloader/core/exporters/common/epub.py +0 -198
- novel_downloader/core/exporters/common/main_exporter.py +0 -64
- novel_downloader/core/exporters/common/txt.py +0 -146
- novel_downloader/core/exporters/epub_util.py +0 -215
- novel_downloader/core/exporters/linovelib/__init__.py +0 -11
- novel_downloader/core/exporters/linovelib/epub.py +0 -349
- novel_downloader/core/exporters/linovelib/main_exporter.py +0 -66
- novel_downloader/core/exporters/linovelib/txt.py +0 -139
- novel_downloader/core/exporters/txt_util.py +0 -67
- novel_downloader/core/parsers/qidian/__init__.py +0 -10
- novel_downloader/core/parsers/qidian/book_info_parser.py +0 -89
- novel_downloader/core/parsers/qidian/chapter_encrypted.py +0 -470
- novel_downloader/core/parsers/qidian/chapter_normal.py +0 -126
- novel_downloader/core/parsers/qidian/chapter_router.py +0 -68
- novel_downloader/core/parsers/qidian/main_parser.py +0 -101
- novel_downloader/core/parsers/qidian/utils/__init__.py +0 -30
- novel_downloader/core/parsers/qidian/utils/fontmap_recover.py +0 -143
- novel_downloader/core/parsers/qidian/utils/helpers.py +0 -110
- novel_downloader/core/parsers/qidian/utils/node_decryptor.py +0 -175
- novel_downloader-2.0.0.dist-info/RECORD +0 -210
- {novel_downloader-2.0.0.dist-info → novel_downloader-2.0.2.dist-info}/WHEEL +0 -0
- {novel_downloader-2.0.0.dist-info → novel_downloader-2.0.2.dist-info}/entry_points.txt +0 -0
- {novel_downloader-2.0.0.dist-info → novel_downloader-2.0.2.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-2.0.0.dist-info → novel_downloader-2.0.2.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,7 @@ from novel_downloader.models import (
|
|
20
20
|
|
21
21
|
|
22
22
|
@register_parser(
|
23
|
-
site_keys=["biquge", "
|
23
|
+
site_keys=["biquge", "b520"],
|
24
24
|
)
|
25
25
|
class BiqugeParser(BaseParser):
|
26
26
|
"""
|
@@ -112,5 +112,5 @@ class BiqugeParser(BaseParser):
|
|
112
112
|
"id": chapter_id,
|
113
113
|
"title": title,
|
114
114
|
"content": content,
|
115
|
-
"extra": {"site": "
|
115
|
+
"extra": {"site": "b520"},
|
116
116
|
}
|
@@ -12,18 +12,14 @@ from collections.abc import Iterable
|
|
12
12
|
from pathlib import Path
|
13
13
|
from typing import Any
|
14
14
|
|
15
|
-
from novel_downloader.core.interfaces import ParserProtocol
|
16
15
|
from novel_downloader.models import BookInfoDict, ChapterDict, ParserConfig
|
17
16
|
|
18
17
|
|
19
|
-
class BaseParser(
|
18
|
+
class BaseParser(abc.ABC):
|
20
19
|
"""
|
21
20
|
BaseParser defines the interface for extracting book metadata and chapter content
|
22
21
|
from raw HTML.
|
23
22
|
|
24
|
-
This base class manages internal book state (e.g. current book ID) and supports
|
25
|
-
configuration-driven behavior such as content cleaning or formatting.
|
26
|
-
|
27
23
|
Subclasses must implement actual parsing logic for specific sites.
|
28
24
|
"""
|
29
25
|
|
@@ -31,22 +27,20 @@ class BaseParser(ParserProtocol, abc.ABC):
|
|
31
27
|
|
32
28
|
_SPACE_RE = re.compile(r"\s+")
|
33
29
|
|
34
|
-
def __init__(
|
35
|
-
self,
|
36
|
-
config: ParserConfig,
|
37
|
-
):
|
30
|
+
def __init__(self, config: ParserConfig):
|
38
31
|
"""
|
39
32
|
Initialize the parser with a configuration object.
|
40
33
|
|
41
34
|
:param config: ParserConfig object controlling parsing behavior.
|
42
35
|
"""
|
43
|
-
self._config = config
|
44
36
|
self._book_id: str | None = None
|
45
37
|
|
38
|
+
self._fontocr_cfg = config.fontocr_cfg
|
39
|
+
self._save_font_debug = config.save_font_debug
|
46
40
|
self._decode_font: bool = config.decode_font
|
41
|
+
self._batch_size = config.batch_size
|
47
42
|
self._use_truncation = config.use_truncation
|
48
43
|
self._base_cache_dir = Path(config.cache_dir)
|
49
|
-
self._cache_dir = self._base_cache_dir
|
50
44
|
|
51
45
|
self._ad_pattern = self._compile_ads_pattern()
|
52
46
|
|
@@ -80,34 +74,6 @@ class BaseParser(ParserProtocol, abc.ABC):
|
|
80
74
|
"""
|
81
75
|
...
|
82
76
|
|
83
|
-
@property
|
84
|
-
def book_id(self) -> str | None:
|
85
|
-
"""
|
86
|
-
Current book ID in context.
|
87
|
-
|
88
|
-
:return: The current book identifier.
|
89
|
-
"""
|
90
|
-
return self._book_id
|
91
|
-
|
92
|
-
@book_id.setter
|
93
|
-
def book_id(self, value: str) -> None:
|
94
|
-
"""
|
95
|
-
Set current book ID and update debug paths if needed.
|
96
|
-
|
97
|
-
:param value: Book identifier.
|
98
|
-
"""
|
99
|
-
self._book_id = value
|
100
|
-
self._cache_dir = self._base_cache_dir / value
|
101
|
-
self._on_book_id_set()
|
102
|
-
|
103
|
-
def _on_book_id_set(self) -> None:
|
104
|
-
"""
|
105
|
-
Hook called when a new book ID is set.
|
106
|
-
Subclasses can override this to initialize
|
107
|
-
book-related folders or states.
|
108
|
-
"""
|
109
|
-
pass
|
110
|
-
|
111
77
|
def _compile_ads_pattern(self) -> re.Pattern[str] | None:
|
112
78
|
"""
|
113
79
|
Compile a regex pattern from the ADS list, or return None if no ADS.
|
@@ -128,9 +128,9 @@ class EsjzoneParser(BaseParser):
|
|
128
128
|
or tag == "summary"
|
129
129
|
):
|
130
130
|
# Handle possible volume title markers:
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
131
|
+
# * <h2>: standard volume header
|
132
|
+
# * <p class="non">: alternative volume header style
|
133
|
+
# * <summary>: fallback for stray <summary> tags outside <details>
|
134
134
|
_start_volume(node.xpath("string()"))
|
135
135
|
|
136
136
|
elif tag == "a":
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""
|
3
|
-
novel_downloader.core.parsers.
|
4
|
-
|
3
|
+
novel_downloader.core.parsers.n8novel
|
4
|
+
-------------------------------------
|
5
5
|
|
6
6
|
"""
|
7
7
|
|
@@ -21,9 +21,9 @@ from novel_downloader.models import (
|
|
21
21
|
|
22
22
|
|
23
23
|
@register_parser(
|
24
|
-
site_keys=["
|
24
|
+
site_keys=["n8novel", "8novel"],
|
25
25
|
)
|
26
|
-
class
|
26
|
+
class N8novelParser(BaseParser):
|
27
27
|
"""
|
28
28
|
Parser for 无限轻小说 book pages.
|
29
29
|
"""
|
@@ -177,7 +177,7 @@ class EightnovelParser(BaseParser):
|
|
177
177
|
"id": chapter_id,
|
178
178
|
"title": title,
|
179
179
|
"content": content,
|
180
|
-
"extra": {"site": "
|
180
|
+
"extra": {"site": "n8novel"},
|
181
181
|
}
|
182
182
|
|
183
183
|
@staticmethod
|
@@ -195,8 +195,8 @@ class EightnovelParser(BaseParser):
|
|
195
195
|
def _build_id_title_map(cls, html_str: str) -> dict[str, str]:
|
196
196
|
"""
|
197
197
|
Extracts two comma-split lists from html_str:
|
198
|
-
|
199
|
-
|
198
|
+
* A numeric list of IDs (one element longer)
|
199
|
+
* A list of titles
|
200
200
|
"""
|
201
201
|
id_list = None
|
202
202
|
title_list = None
|