novel-downloader 1.2.2__py3-none-any.whl → 1.3.1__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 -2
- novel_downloader/cli/__init__.py +0 -1
- novel_downloader/cli/clean.py +2 -10
- novel_downloader/cli/download.py +16 -22
- novel_downloader/cli/interactive.py +0 -1
- novel_downloader/cli/main.py +1 -3
- novel_downloader/cli/settings.py +8 -8
- novel_downloader/config/__init__.py +0 -1
- novel_downloader/config/adapter.py +32 -27
- novel_downloader/config/loader.py +116 -108
- novel_downloader/config/models.py +35 -29
- novel_downloader/config/site_rules.py +2 -4
- novel_downloader/core/__init__.py +0 -1
- novel_downloader/core/downloaders/__init__.py +4 -4
- novel_downloader/core/downloaders/base/__init__.py +14 -0
- novel_downloader/core/downloaders/{base_async_downloader.py → base/base_async.py} +49 -53
- novel_downloader/core/downloaders/{base_downloader.py → base/base_sync.py} +64 -43
- novel_downloader/core/downloaders/biquge/__init__.py +12 -0
- novel_downloader/core/downloaders/biquge/biquge_sync.py +25 -0
- novel_downloader/core/downloaders/common/__init__.py +14 -0
- novel_downloader/core/downloaders/{common_asynb_downloader.py → common/common_async.py} +42 -33
- novel_downloader/core/downloaders/{common_downloader.py → common/common_sync.py} +33 -21
- novel_downloader/core/downloaders/qidian/__init__.py +10 -0
- novel_downloader/core/downloaders/{qidian_downloader.py → qidian/qidian_sync.py} +79 -62
- novel_downloader/core/factory/__init__.py +4 -5
- novel_downloader/core/factory/{downloader_factory.py → downloader.py} +25 -26
- novel_downloader/core/factory/{parser_factory.py → parser.py} +12 -14
- novel_downloader/core/factory/{requester_factory.py → requester.py} +29 -16
- novel_downloader/core/factory/{saver_factory.py → saver.py} +4 -9
- novel_downloader/core/interfaces/__init__.py +8 -9
- novel_downloader/core/interfaces/{async_downloader_protocol.py → async_downloader.py} +4 -5
- novel_downloader/core/interfaces/{async_requester_protocol.py → async_requester.py} +23 -12
- novel_downloader/core/interfaces/{parser_protocol.py → parser.py} +11 -6
- novel_downloader/core/interfaces/{saver_protocol.py → saver.py} +2 -3
- novel_downloader/core/interfaces/{downloader_protocol.py → sync_downloader.py} +6 -7
- novel_downloader/core/interfaces/{requester_protocol.py → sync_requester.py} +31 -17
- novel_downloader/core/parsers/__init__.py +5 -4
- novel_downloader/core/parsers/{base_parser.py → base.py} +18 -9
- novel_downloader/core/parsers/biquge/__init__.py +10 -0
- novel_downloader/core/parsers/biquge/main_parser.py +126 -0
- novel_downloader/core/parsers/{common_parser → common}/__init__.py +2 -3
- novel_downloader/core/parsers/{common_parser → common}/helper.py +13 -13
- novel_downloader/core/parsers/{common_parser → common}/main_parser.py +15 -9
- novel_downloader/core/parsers/{qidian_parser → qidian}/__init__.py +2 -3
- novel_downloader/core/parsers/{qidian_parser → qidian}/browser/__init__.py +2 -3
- novel_downloader/core/parsers/{qidian_parser → qidian}/browser/chapter_encrypted.py +40 -48
- novel_downloader/core/parsers/{qidian_parser → qidian}/browser/chapter_normal.py +17 -21
- novel_downloader/core/parsers/{qidian_parser → qidian}/browser/chapter_router.py +10 -9
- novel_downloader/core/parsers/{qidian_parser → qidian}/browser/main_parser.py +14 -10
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/__init__.py +2 -3
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/chapter_encrypted.py +36 -44
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/chapter_normal.py +19 -23
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/chapter_router.py +10 -9
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/main_parser.py +14 -10
- novel_downloader/core/parsers/{qidian_parser → qidian}/session/node_decryptor.py +7 -10
- novel_downloader/core/parsers/{qidian_parser → qidian}/shared/__init__.py +2 -3
- novel_downloader/core/parsers/{qidian_parser → qidian}/shared/book_info_parser.py +5 -6
- novel_downloader/core/parsers/{qidian_parser → qidian}/shared/helpers.py +7 -8
- novel_downloader/core/requesters/__init__.py +9 -5
- novel_downloader/core/requesters/base/__init__.py +16 -0
- novel_downloader/core/requesters/{base_async_session.py → base/async_session.py} +177 -73
- novel_downloader/core/requesters/base/browser.py +340 -0
- novel_downloader/core/requesters/base/session.py +364 -0
- novel_downloader/core/requesters/biquge/__init__.py +12 -0
- novel_downloader/core/requesters/biquge/session.py +90 -0
- novel_downloader/core/requesters/{common_requester → common}/__init__.py +4 -5
- novel_downloader/core/requesters/common/async_session.py +96 -0
- novel_downloader/core/requesters/common/session.py +113 -0
- novel_downloader/core/requesters/qidian/__init__.py +21 -0
- novel_downloader/core/requesters/qidian/broswer.py +307 -0
- novel_downloader/core/requesters/qidian/session.py +287 -0
- novel_downloader/core/savers/__init__.py +5 -3
- novel_downloader/core/savers/{base_saver.py → base.py} +12 -13
- novel_downloader/core/savers/biquge.py +25 -0
- novel_downloader/core/savers/{common_saver → common}/__init__.py +2 -3
- novel_downloader/core/savers/{common_saver/common_epub.py → common/epub.py} +23 -51
- novel_downloader/core/savers/{common_saver → common}/main_saver.py +43 -9
- novel_downloader/core/savers/{common_saver/common_txt.py → common/txt.py} +16 -46
- novel_downloader/core/savers/epub_utils/__init__.py +0 -1
- novel_downloader/core/savers/epub_utils/css_builder.py +13 -7
- novel_downloader/core/savers/epub_utils/initializer.py +4 -5
- novel_downloader/core/savers/epub_utils/text_to_html.py +2 -3
- novel_downloader/core/savers/epub_utils/volume_intro.py +1 -3
- novel_downloader/core/savers/{qidian_saver.py → qidian.py} +12 -6
- novel_downloader/locales/en.json +8 -4
- novel_downloader/locales/zh.json +5 -1
- novel_downloader/resources/config/settings.toml +88 -0
- novel_downloader/utils/cache.py +2 -2
- novel_downloader/utils/chapter_storage.py +340 -0
- novel_downloader/utils/constants.py +6 -4
- novel_downloader/utils/crypto_utils.py +3 -3
- novel_downloader/utils/file_utils/__init__.py +0 -1
- novel_downloader/utils/file_utils/io.py +12 -17
- novel_downloader/utils/file_utils/normalize.py +1 -3
- novel_downloader/utils/file_utils/sanitize.py +2 -9
- novel_downloader/utils/fontocr/__init__.py +0 -1
- novel_downloader/utils/fontocr/ocr_v1.py +19 -22
- novel_downloader/utils/fontocr/ocr_v2.py +147 -60
- novel_downloader/utils/hash_store.py +19 -20
- novel_downloader/utils/hash_utils.py +0 -1
- novel_downloader/utils/i18n.py +3 -4
- novel_downloader/utils/logger.py +5 -6
- novel_downloader/utils/model_loader.py +5 -8
- novel_downloader/utils/network.py +9 -10
- novel_downloader/utils/state.py +6 -7
- novel_downloader/utils/text_utils/__init__.py +0 -1
- novel_downloader/utils/text_utils/chapter_formatting.py +2 -7
- novel_downloader/utils/text_utils/diff_display.py +0 -1
- novel_downloader/utils/text_utils/font_mapping.py +1 -4
- novel_downloader/utils/text_utils/text_cleaning.py +0 -1
- novel_downloader/utils/time_utils/__init__.py +0 -1
- novel_downloader/utils/time_utils/datetime_utils.py +8 -10
- novel_downloader/utils/time_utils/sleep_utils.py +1 -3
- {novel_downloader-1.2.2.dist-info → novel_downloader-1.3.1.dist-info}/METADATA +14 -17
- novel_downloader-1.3.1.dist-info/RECORD +127 -0
- {novel_downloader-1.2.2.dist-info → novel_downloader-1.3.1.dist-info}/WHEEL +1 -1
- novel_downloader/core/requesters/base_browser.py +0 -214
- novel_downloader/core/requesters/base_session.py +0 -246
- novel_downloader/core/requesters/common_requester/common_async_session.py +0 -98
- novel_downloader/core/requesters/common_requester/common_session.py +0 -126
- novel_downloader/core/requesters/qidian_requester/__init__.py +0 -22
- novel_downloader/core/requesters/qidian_requester/qidian_broswer.py +0 -396
- novel_downloader/core/requesters/qidian_requester/qidian_session.py +0 -202
- novel_downloader/resources/config/settings.yaml +0 -76
- novel_downloader-1.2.2.dist-info/RECORD +0 -115
- {novel_downloader-1.2.2.dist-info → novel_downloader-1.3.1.dist-info}/entry_points.txt +0 -0
- {novel_downloader-1.2.2.dist-info → novel_downloader-1.3.1.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-1.2.2.dist-info → novel_downloader-1.3.1.dist-info}/top_level.txt +0 -0
@@ -1,202 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
# -*- coding: utf-8 -*-
|
3
|
-
"""
|
4
|
-
novel_downloader.core.requesters.qidian_requester.qidian_session
|
5
|
-
----------------------------------------------------------------
|
6
|
-
|
7
|
-
This module defines the QidianRequester class for interacting with
|
8
|
-
the Qidian website.
|
9
|
-
It extends the BaseSession by adding methods for logging in and
|
10
|
-
retrieving book information.
|
11
|
-
"""
|
12
|
-
|
13
|
-
from __future__ import annotations
|
14
|
-
|
15
|
-
import base64
|
16
|
-
import logging
|
17
|
-
import time
|
18
|
-
from typing import Any, Dict, Optional
|
19
|
-
|
20
|
-
from requests import Response
|
21
|
-
|
22
|
-
from novel_downloader.config.models import RequesterConfig
|
23
|
-
from novel_downloader.core.requesters.base_session import BaseSession
|
24
|
-
from novel_downloader.utils.crypto_utils import patch_qd_payload_token
|
25
|
-
from novel_downloader.utils.state import state_mgr
|
26
|
-
from novel_downloader.utils.time_utils import sleep_with_random_delay
|
27
|
-
|
28
|
-
logger = logging.getLogger(__name__)
|
29
|
-
|
30
|
-
|
31
|
-
class QidianSession(BaseSession):
|
32
|
-
"""
|
33
|
-
A concrete :class:`BaseSession` for the Qidian site. Besides the usual
|
34
|
-
``get``/``post`` helpers provided by the base class, this subclass adds:
|
35
|
-
|
36
|
-
* URL builders for book info / chapter / bookcase pages
|
37
|
-
* High-level convenience wrappers that:
|
38
|
-
1. sleep a configurable (jittered) amount of time;
|
39
|
-
2. retry on failures;
|
40
|
-
3. automatically persist fresh cookies to :pydata:`state_mgr`
|
41
|
-
so that the next run can reuse them.
|
42
|
-
"""
|
43
|
-
|
44
|
-
DEFAULT_SCHEME = "https:"
|
45
|
-
QIDIAN_BASE_URL = "www.qidian.com"
|
46
|
-
QIDIAN_BOOKCASE_URL = f"{DEFAULT_SCHEME}//my.qidian.com/bookcase/"
|
47
|
-
QIDIAN_BOOK_INFO_URL_1 = f"{DEFAULT_SCHEME}//www.qidian.com/book"
|
48
|
-
QIDIAN_BOOK_INFO_URL_2 = f"{DEFAULT_SCHEME}//book.qidian.com/info"
|
49
|
-
QIDIAN_CHAPTER_URL = f"{DEFAULT_SCHEME}//www.qidian.com/chapter"
|
50
|
-
|
51
|
-
def __init__(self, config: RequesterConfig):
|
52
|
-
"""
|
53
|
-
Initialise the underlying :class:`requests.Session`.
|
54
|
-
"""
|
55
|
-
self._init_session(config=config)
|
56
|
-
|
57
|
-
def get(
|
58
|
-
self,
|
59
|
-
url: str,
|
60
|
-
params: Optional[Dict[str, Any]] = None,
|
61
|
-
**kwargs: Any,
|
62
|
-
) -> Response:
|
63
|
-
"""
|
64
|
-
Same as :py:meth:`BaseSession.get`, but transparently refreshes
|
65
|
-
a cookie-based token used for request validation.
|
66
|
-
|
67
|
-
The method:
|
68
|
-
1. Reads the existing cookie (if any);
|
69
|
-
2. Generates a new value tied to *url*;
|
70
|
-
3. Updates both the live ``requests.Session`` and the internal cache;
|
71
|
-
4. Delegates the actual request to ``super().get``.
|
72
|
-
"""
|
73
|
-
if self._session is None: # defensive - mirrors BaseSession check
|
74
|
-
raise RuntimeError("Session is not initialized or has been shut down.")
|
75
|
-
|
76
|
-
# ---- 1. refresh token cookie --------------------------------------
|
77
|
-
cookie_key = base64.b64decode("d190c2Zw").decode()
|
78
|
-
old_token = self._session.cookies.get(cookie_key, "")
|
79
|
-
|
80
|
-
if old_token:
|
81
|
-
refreshed_token = patch_qd_payload_token(old_token, url)
|
82
|
-
self._session.cookies.set(cookie_key, refreshed_token)
|
83
|
-
self._cookies[cookie_key] = refreshed_token
|
84
|
-
|
85
|
-
# ---- 2. perform the real GET --------------------------------------------
|
86
|
-
resp: Response = super().get(url, params=params, **kwargs)
|
87
|
-
|
88
|
-
# ---- 3. persist any server-set cookies (optional) --------------
|
89
|
-
self.update_cookies(self._session.cookies.get_dict(), overwrite=True)
|
90
|
-
state_mgr.set_cookies("qidian", self._cookies)
|
91
|
-
|
92
|
-
return resp
|
93
|
-
|
94
|
-
def login(self, max_retries: int = 3, manual_login: bool = False) -> bool:
|
95
|
-
"""
|
96
|
-
Restore cookies persisted by the browser-based workflow.
|
97
|
-
"""
|
98
|
-
cookies: Dict[str, str] = state_mgr.get_cookies("qidian")
|
99
|
-
if not cookies:
|
100
|
-
logger.info(
|
101
|
-
"[session] No stored cookies found: session remains unauthenticated."
|
102
|
-
)
|
103
|
-
return False
|
104
|
-
|
105
|
-
# Merge cookies into both the internal cache and the live session
|
106
|
-
self.update_cookies(cookies, overwrite=True)
|
107
|
-
logger.info("[session] Loaded %d cookie(s) from state.", len(cookies))
|
108
|
-
self.get("https://www.qidian.com")
|
109
|
-
return True
|
110
|
-
|
111
|
-
def get_book_info(self, book_id: str, wait_time: Optional[float] = None) -> str:
|
112
|
-
"""
|
113
|
-
Fetch the raw HTML of the book info page.
|
114
|
-
|
115
|
-
:param book_id: The book identifier.
|
116
|
-
:param wait_time: Base number of seconds to wait before returning content.
|
117
|
-
:return: The page content as a string.
|
118
|
-
"""
|
119
|
-
url = f"{self.QIDIAN_BOOK_INFO_URL_2}/{book_id}/"
|
120
|
-
base_delay = wait_time or self._config.wait_time
|
121
|
-
|
122
|
-
for attempt in range(1, self.retry_times + 1):
|
123
|
-
try:
|
124
|
-
resp = self.get(url)
|
125
|
-
resp.raise_for_status()
|
126
|
-
sleep_with_random_delay(base_delay, mul_spread=1.2)
|
127
|
-
return resp.text
|
128
|
-
except Exception as exc:
|
129
|
-
logger.warning(
|
130
|
-
"[session] get_book_info(%s) attempt %s/%s failed: %s",
|
131
|
-
book_id,
|
132
|
-
attempt,
|
133
|
-
self.retry_times,
|
134
|
-
exc,
|
135
|
-
)
|
136
|
-
if attempt == self.retry_times:
|
137
|
-
raise
|
138
|
-
time.sleep(self.retry_interval)
|
139
|
-
|
140
|
-
raise RuntimeError("Unexpected fall-through in get_book_info")
|
141
|
-
|
142
|
-
def get_book_chapter(
|
143
|
-
self, book_id: str, chapter_id: str, wait_time: Optional[float] = None
|
144
|
-
) -> str:
|
145
|
-
"""
|
146
|
-
Fetch the HTML of a single chapter.
|
147
|
-
|
148
|
-
:param book_id: The book identifier.
|
149
|
-
:param chapter_id: The chapter identifier.
|
150
|
-
:param wait_time: Base number of seconds to wait before returning content.
|
151
|
-
:return: The chapter content as a string.
|
152
|
-
"""
|
153
|
-
url = f"{self.QIDIAN_CHAPTER_URL}/{book_id}/{chapter_id}/"
|
154
|
-
base_delay = wait_time or self._config.wait_time
|
155
|
-
|
156
|
-
for attempt in range(1, self.retry_times + 1):
|
157
|
-
try:
|
158
|
-
resp = self.get(url)
|
159
|
-
resp.raise_for_status()
|
160
|
-
sleep_with_random_delay(base_delay, mul_spread=1.2)
|
161
|
-
return resp.text
|
162
|
-
except Exception as exc:
|
163
|
-
logger.warning(
|
164
|
-
"[session] get_book_chapter(%s, %s) attempt %s/%s failed: %s",
|
165
|
-
book_id,
|
166
|
-
chapter_id,
|
167
|
-
attempt,
|
168
|
-
self.retry_times,
|
169
|
-
exc,
|
170
|
-
)
|
171
|
-
if attempt == self.retry_times:
|
172
|
-
raise
|
173
|
-
time.sleep(self.retry_interval)
|
174
|
-
|
175
|
-
raise RuntimeError("Unexpected fall-through in get_book_chapter")
|
176
|
-
|
177
|
-
def get_bookcase(self, wait_time: Optional[float] = None) -> str:
|
178
|
-
"""
|
179
|
-
Retrieve the user's *bookcase* page.
|
180
|
-
|
181
|
-
:param wait_time: Base number of seconds to wait before returning content.
|
182
|
-
:return: The HTML markup of the bookcase page.
|
183
|
-
"""
|
184
|
-
base_delay = wait_time or self._config.wait_time
|
185
|
-
for attempt in range(1, self.retry_times + 1):
|
186
|
-
try:
|
187
|
-
resp = self.get(self.QIDIAN_BOOKCASE_URL, allow_redirects=True)
|
188
|
-
resp.raise_for_status()
|
189
|
-
sleep_with_random_delay(base_delay, mul_spread=1.2)
|
190
|
-
return resp.text
|
191
|
-
except Exception as exc:
|
192
|
-
logger.warning(
|
193
|
-
"[session] get_bookcase attempt %s/%s failed: %s",
|
194
|
-
attempt,
|
195
|
-
self.retry_times,
|
196
|
-
exc,
|
197
|
-
)
|
198
|
-
if attempt == self.retry_times:
|
199
|
-
raise
|
200
|
-
time.sleep(self.retry_interval)
|
201
|
-
|
202
|
-
raise RuntimeError("Unexpected fall-through in get_bookcase")
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# 网络请求层设置
|
2
|
-
requests:
|
3
|
-
wait_time: 5.0 # 每次请求等待时间 (秒)
|
4
|
-
retry_times: 3 # 请求失败重试次数
|
5
|
-
retry_interval: 5.0
|
6
|
-
timeout: 30.0 # 页面加载超时时间 (秒)
|
7
|
-
max_rps: null # 最大请求速率 (requests per second), 为 null 则不限制
|
8
|
-
# DrissionPage 专用设置
|
9
|
-
headless: false # 是否以无头模式启动浏览器
|
10
|
-
user_data_folder: "" # 浏览器用户数据目录: 为空则使用默认目录
|
11
|
-
profile_name: "" # 使用的用户配置名称: 为空则使用默认配置
|
12
|
-
auto_close: true # 页面抓取完是否自动关闭浏览器
|
13
|
-
disable_images: false # 是否禁用图片加载 (加速)
|
14
|
-
mute_audio: true # 是否静音
|
15
|
-
|
16
|
-
# 全局通用设置
|
17
|
-
general:
|
18
|
-
request_interval: 5.0 # 同一本书各章节请求间隔 (秒)
|
19
|
-
raw_data_dir: "./raw_data" # 原始章节 HTML/JSON 存放目录
|
20
|
-
output_dir: "./downloads" # 最终输出文件存放目录
|
21
|
-
cache_dir: "./novel_cache" # 本地缓存目录 (字体 / 图片等)
|
22
|
-
download_workers: 4 # 并发下载线程数
|
23
|
-
parser_workers: 4 # 并发解析线程数
|
24
|
-
use_process_pool: false # 是否使用多进程池来处理任务
|
25
|
-
skip_existing: true # 是否跳过已存在章节
|
26
|
-
debug:
|
27
|
-
save_html: false # 是否将抓取到的原始 HTML 保留到磁盘
|
28
|
-
log_level: "INFO" # 日志级别: DEBUG, INFO, WARNING, ERROR
|
29
|
-
font_ocr:
|
30
|
-
decode_font: false # 是否尝试本地解码混淆字体
|
31
|
-
use_freq: false # 是否使用频率分析
|
32
|
-
ocr_version: "v2.0" # "v1.0" / "v2.0"
|
33
|
-
use_ocr: true # 是否使用 OCR 辅助识别文本
|
34
|
-
use_vec: false # 是否使用 Vector 辅助识别文本
|
35
|
-
save_font_debug: false # 是否保存字体解码调试数据
|
36
|
-
batch_size: 32
|
37
|
-
gpu_mem: 500 # GPU 显存限制 (MB)
|
38
|
-
gpu_id: null # 使用哪个 GPU
|
39
|
-
ocr_weight: 0.6
|
40
|
-
vec_weight: 0.4
|
41
|
-
|
42
|
-
# 各站点的特定配置
|
43
|
-
sites:
|
44
|
-
qidian:
|
45
|
-
# 小说 ID 列表
|
46
|
-
# 例如: 访问 https://www.qidian.com/book/1010868264/
|
47
|
-
# 该小说的 ID 就是 1010868264
|
48
|
-
book_ids:
|
49
|
-
- "0000000000"
|
50
|
-
- "0000000000"
|
51
|
-
mode: "browser" # browser / session
|
52
|
-
login_required: true # 是否需要登录才能访问
|
53
|
-
#
|
54
|
-
sample_site:
|
55
|
-
book_ids:
|
56
|
-
- "ABCDEF"
|
57
|
-
api_key: "your_api_key"
|
58
|
-
special_flag: 42
|
59
|
-
common:
|
60
|
-
mode: "session" # async / session
|
61
|
-
login_required: false # 是否需要登录才能访问
|
62
|
-
|
63
|
-
# 输出文件格式及相关选项
|
64
|
-
output:
|
65
|
-
clean_text: true # 是否对章节文本做清理
|
66
|
-
formats:
|
67
|
-
make_txt: true # 是否生成完整 TXT 文件
|
68
|
-
make_epub: false # 是否生成 EPUB
|
69
|
-
make_md: false # 是否生成 Markdown (未实现)
|
70
|
-
make_pdf: false # 可能支持 PDF 输出 (未实现)
|
71
|
-
naming:
|
72
|
-
append_timestamp: false # 在文件名中追加时间戳
|
73
|
-
filename_template: "{title}_{author}" # 文件命名规则
|
74
|
-
epub:
|
75
|
-
include_cover: true # 是否在 EPUB 中包含封面
|
76
|
-
include_toc: false # 是否自动生成目录
|
@@ -1,115 +0,0 @@
|
|
1
|
-
novel_downloader/__init__.py,sha256=LCdmt0Int1WSZ3n25_tdJ7Mm-gknw2F-Sg4xKyMLWJs,242
|
2
|
-
novel_downloader/cli/__init__.py,sha256=ocGwOO4kmkby8VNol92UikMI1RPUJLv9i5xmB7wbpmw,198
|
3
|
-
novel_downloader/cli/clean.py,sha256=9_hOrxKg8nY7q6cyR8iNech0vSREGagPBmdB4k8Te2U,3937
|
4
|
-
novel_downloader/cli/download.py,sha256=WZLnf8cckAGe9t7hI6WWgjrm_KRa67pTwEC-YJBAmFc,4223
|
5
|
-
novel_downloader/cli/interactive.py,sha256=6vROwPsvupb_TWH1dd_78FDqvtAaiPfyEBvQVai9E9c,2154
|
6
|
-
novel_downloader/cli/main.py,sha256=km1MwHzIVZFcxUlKLRiiMctJlGHWKZNjRKrgAGQjkMs,1183
|
7
|
-
novel_downloader/cli/settings.py,sha256=bV3Hgg502V9goeP3g2xSiF-PMQB9G32qGmjb8ncTENA,6522
|
8
|
-
novel_downloader/config/__init__.py,sha256=tJ2k7nwZbxgqw1kKgJM4g1yu5-2fsx2LXU3VTadrTJ4,1129
|
9
|
-
novel_downloader/config/adapter.py,sha256=R1y1g7uDBxtDz_sVsDGl2-iasQNAtWSmYdSk-mcFoAA,6698
|
10
|
-
novel_downloader/config/loader.py,sha256=_rm9rp1lmHYg-A7F_0PQETWjlXbvtyJYaqQD5oI-1O0,5690
|
11
|
-
novel_downloader/config/models.py,sha256=i7i1yQzY5lAZWDBhi5ZXqzthlanhvhAc3oViMMoJFyw,5139
|
12
|
-
novel_downloader/config/site_rules.py,sha256=WRw12Tfue-ErAPGKq506gRIqKOxWU-u96kay3JDgTNc,3031
|
13
|
-
novel_downloader/core/__init__.py,sha256=D-ACiIqP0rdARZmjBnF6WMKGvvjVtxGRIM7GhOS9kh4,779
|
14
|
-
novel_downloader/core/downloaders/__init__.py,sha256=Qp0q4p7zTy7lReQQF0hDP7ALUQnNflSNNIl4F7iPGz0,601
|
15
|
-
novel_downloader/core/downloaders/base_async_downloader.py,sha256=8lMSVLU-VtGIdEMGkS0s_rEJpqCgu2WaljBvsEDyPN4,4281
|
16
|
-
novel_downloader/core/downloaders/base_downloader.py,sha256=kFw_yn3QRbWqU9jXJni4IGA8P3AxZf9gfjgfu01TauY,5371
|
17
|
-
novel_downloader/core/downloaders/common_asynb_downloader.py,sha256=u1ODvh_n13CSGWwjkBIMoThTbCeACX5mOhv5ub2Cd0c,7120
|
18
|
-
novel_downloader/core/downloaders/common_downloader.py,sha256=-HT7pi8bCSAdIcrU9CFHz26iqgtPhlUTI2MoE7ldCfY,6506
|
19
|
-
novel_downloader/core/downloaders/qidian_downloader.py,sha256=KH-rPvwhWsZ9hyuvZxhQ9Q42LDFiAABpMlgReeX2nzI,7328
|
20
|
-
novel_downloader/core/factory/__init__.py,sha256=qGqeROj8Dp_5iNtgWytkrUNI0ICab7SCNK3lba3H_NU,743
|
21
|
-
novel_downloader/core/factory/downloader_factory.py,sha256=ldWFZ3189rxW2cWTNcwidiPisJNuaxD8OYB5YyjOXRU,5110
|
22
|
-
novel_downloader/core/factory/parser_factory.py,sha256=4PxiagtSKY58azFsmEWfq2f5vhVbtMFm5gAXS3oQF08,1828
|
23
|
-
novel_downloader/core/factory/requester_factory.py,sha256=OEK2S-rj8vw4IdDTMTEWcb7k7lRmmWBnfijhYnlOCc0,3173
|
24
|
-
novel_downloader/core/factory/saver_factory.py,sha256=OgZPDOWVIfhxLFiVBKI5jaNOEKmzP9f3YWDOnw63Hfc,1275
|
25
|
-
novel_downloader/core/interfaces/__init__.py,sha256=jeT8BmEEjIazVyX80ZdzQXgTccEj-ktG6Bbjs9uAVUM,843
|
26
|
-
novel_downloader/core/interfaces/async_downloader_protocol.py,sha256=QWjdhNc39hC3bD8Q1lUpBv2GqX3roxVxzKWh6cgwLhk,1002
|
27
|
-
novel_downloader/core/interfaces/async_requester_protocol.py,sha256=Jd54mJWnNt_BE2RRGYGmGDe93MM0I4xBLL4m6u6V_Is,2344
|
28
|
-
novel_downloader/core/interfaces/downloader_protocol.py,sha256=YJdSAE9uBWF7wNLWmlKsYd3J7M4rXOjqDV5m9O7kfio,947
|
29
|
-
novel_downloader/core/interfaces/parser_protocol.py,sha256=A2wIe7shEGdeKsNDFpMuPI8HFrK_H34HOseVAzqcnTo,1280
|
30
|
-
novel_downloader/core/interfaces/requester_protocol.py,sha256=Zskzwom104GWjB0LrV-VvAR7vfTB3LAcHvV110ISdo0,2058
|
31
|
-
novel_downloader/core/interfaces/saver_protocol.py,sha256=_3ha4koF-xBrogJwvCOsQM3GEXfLn3_aYZHvmRd1ZR4,1623
|
32
|
-
novel_downloader/core/parsers/__init__.py,sha256=TSarXiYxthyjFgruRFkpMEucqmylrCtR_4Y1C1RVMhk,544
|
33
|
-
novel_downloader/core/parsers/base_parser.py,sha256=mRv6tmbWIuX5XnXYnSP9JMsXECgykZymq4zWNNk7wDQ,2936
|
34
|
-
novel_downloader/core/parsers/common_parser/__init__.py,sha256=GmV7Yj57zbLK0-WYmPtv6x1AhKwa3lzKlqsU7mc3lzg,379
|
35
|
-
novel_downloader/core/parsers/common_parser/helper.py,sha256=gY3HHYnXGHHiCaig59T7IlI7Fa7XEqlmAAKWGmeSmXI,12090
|
36
|
-
novel_downloader/core/parsers/common_parser/main_parser.py,sha256=ANvkZMYACZEwaYLz56lLyBz9dc_XqZMvWp2_jWWoF3g,2868
|
37
|
-
novel_downloader/core/parsers/qidian_parser/__init__.py,sha256=mYbZvWMn4oFFX3qGhGx6Qo6oqvE5I71b-jbanWsTOSI,522
|
38
|
-
novel_downloader/core/parsers/qidian_parser/browser/__init__.py,sha256=E8kMkQW_LdmVFYpHbbYtJTLNTYOy9XItQf_h7KcnGIU,353
|
39
|
-
novel_downloader/core/parsers/qidian_parser/browser/chapter_encrypted.py,sha256=v-sCfQYyRNOdZ12Qlb9b5Tqq69rcOS_CKBUG5XG9WUs,17713
|
40
|
-
novel_downloader/core/parsers/qidian_parser/browser/chapter_normal.py,sha256=SZ9Ncw6yLCRo4gJNEtv4V8N2WfONvEAc8lftJREsBTY,3190
|
41
|
-
novel_downloader/core/parsers/qidian_parser/browser/chapter_router.py,sha256=qjN10SpQCUMjFcCaWnqIZhcLDx5sN5jzDfWIrBSbnyo,2101
|
42
|
-
novel_downloader/core/parsers/qidian_parser/browser/main_parser.py,sha256=8nmmTlhgina3JNrKoIMkFoNF6d9ztki7kAcCyGysy4g,3856
|
43
|
-
novel_downloader/core/parsers/qidian_parser/session/__init__.py,sha256=Rs2Sz1vNn1-UdpY0O_reECBN4kgb3JYHQZoZ20P7lHU,358
|
44
|
-
novel_downloader/core/parsers/qidian_parser/session/chapter_encrypted.py,sha256=XbQV0MQVsiumyrwGddAUaK9JrZpWZlfbZ0_2vBhGupU,16016
|
45
|
-
novel_downloader/core/parsers/qidian_parser/session/chapter_normal.py,sha256=ySQ7vUs4dLCkHv_nPSifDnH3xq3wqxa9FWGy_ETX-uw,3875
|
46
|
-
novel_downloader/core/parsers/qidian_parser/session/chapter_router.py,sha256=ob8ULDhNdnJgU3rlA-tLy0w0PqbC20vi8auFqQipJww,1978
|
47
|
-
novel_downloader/core/parsers/qidian_parser/session/main_parser.py,sha256=fL-IYhd99Rbb2eHCOy0DmYpmHeIOSe3DIFbtQKCj53s,3947
|
48
|
-
novel_downloader/core/parsers/qidian_parser/session/node_decryptor.py,sha256=7ZuneGzL7HX1g8taMzn-2qkJXLDHgrVee-FDkMZtIIw,5755
|
49
|
-
novel_downloader/core/parsers/qidian_parser/shared/__init__.py,sha256=K5HX7pgiRiJuTLdbQDbtm60mO-sXgr6bo5Ft8H1-JLs,978
|
50
|
-
novel_downloader/core/parsers/qidian_parser/shared/book_info_parser.py,sha256=CGoJXRrf65CjJU3wPjZ8FRy96zV2rkYyWSMEyEFUrzE,4853
|
51
|
-
novel_downloader/core/parsers/qidian_parser/shared/helpers.py,sha256=zQqcts8f_JddtKvQjvVJBJQvN5HjeaqlP2I3ztwO75o,4306
|
52
|
-
novel_downloader/core/requesters/__init__.py,sha256=U2jDvt5RxF5P9yL2lwyZ-cRueJBZgRnjil3_5TvAh3Y,798
|
53
|
-
novel_downloader/core/requesters/base_async_session.py,sha256=xojNO_TCLUHmkuk379ttoiScHwmLCNhQAFzQKSpk5AM,10635
|
54
|
-
novel_downloader/core/requesters/base_browser.py,sha256=HceDLOkl86K_nAkZR1XGIzSa-4KyFGt0dG5PyhefJ3c,6899
|
55
|
-
novel_downloader/core/requesters/base_session.py,sha256=0yl3wR-myu-r9NrtwnGWzEFMzWPxcD3ROT5x9xeX6zQ,8328
|
56
|
-
novel_downloader/core/requesters/common_requester/__init__.py,sha256=kVKZyrS7PVlUnaV1xGsZdoW2J9XuyQ11A4oMV9Cc64Q,523
|
57
|
-
novel_downloader/core/requesters/common_requester/common_async_session.py,sha256=Bt_pgiJdxfoSDswMANeiZxaUQ4E5YitqEmcTlL4ImLY,3556
|
58
|
-
novel_downloader/core/requesters/common_requester/common_session.py,sha256=hzah5pvRqFBTzmz1J5d7GE5jbpKSOZWBPz-lh18cTv4,4686
|
59
|
-
novel_downloader/core/requesters/qidian_requester/__init__.py,sha256=s0ldqNvfqUsEnm_biM_bXEGN7gz88Z5IAx1OBvGW1lY,682
|
60
|
-
novel_downloader/core/requesters/qidian_requester/qidian_broswer.py,sha256=BkweHqf-TEC2VCGKFxdUp24lPDuQPUepfHPFUXUgTh0,15146
|
61
|
-
novel_downloader/core/requesters/qidian_requester/qidian_session.py,sha256=R-B6Hc61v5C-KGdEckDJWBt7Bnn_dbpW5ukQgh3x--Q,7664
|
62
|
-
novel_downloader/core/savers/__init__.py,sha256=p9O6p8ZUblrSheDVJoTSuDr6s1mJpQi8mz3QmQ16nHs,391
|
63
|
-
novel_downloader/core/savers/base_saver.py,sha256=VocVl8go80IkzAp9qY4dgZjmLbK8TVkg48Ugl53pxrc,5513
|
64
|
-
novel_downloader/core/savers/qidian_saver.py,sha256=MVAcWdM-IX_qsRW5It2aIkx9QPdRCLcZGcD3ihfm3gU,627
|
65
|
-
novel_downloader/core/savers/common_saver/__init__.py,sha256=Pg52cjAwG9fgT5qWgVer5oLMACU-duNFNbtfcq4t5xA,292
|
66
|
-
novel_downloader/core/savers/common_saver/common_epub.py,sha256=80a-ibhhTy08wsZr7uiqrlvmITcsd1MH-z1OAj1Dl3c,7182
|
67
|
-
novel_downloader/core/savers/common_saver/common_txt.py,sha256=fgBoKPApmODeUoxCi54txoD322G7mlU9o8HEM5X5atk,5765
|
68
|
-
novel_downloader/core/savers/common_saver/main_saver.py,sha256=scjERGgC7X2R3f0KuLwf462VHkFJ2D2duod53aWlMkg,2765
|
69
|
-
novel_downloader/core/savers/epub_utils/__init__.py,sha256=rqWUMkdebZ2dO-aZRYSutZ-w5uKgFVwe83nBJbYx40E,738
|
70
|
-
novel_downloader/core/savers/epub_utils/css_builder.py,sha256=ZiYEAuC4_u3BWBcf6-kILrKH8YHDcserzBP4luxmOro,2028
|
71
|
-
novel_downloader/core/savers/epub_utils/initializer.py,sha256=QuPWuChq2dcFlGp-PeZBrhfqSwoM7Nko-zHe9beluZw,3255
|
72
|
-
novel_downloader/core/savers/epub_utils/text_to_html.py,sha256=UW70pMmc9HdgSCMKVEgukONFdlNCmQIKs9PCDLNAFQU,4117
|
73
|
-
novel_downloader/core/savers/epub_utils/volume_intro.py,sha256=1NhnLKRL_ieoDgXTRt3vTNeENGvUj7JTZxTME4TmYm8,1820
|
74
|
-
novel_downloader/locales/en.json,sha256=4Zn2cD2vGkHHIam2j_Ig-gpicD14L3ufKX_lq0k0yR4,5531
|
75
|
-
novel_downloader/locales/zh.json,sha256=nKmxyb84gmq9tg9DFLSx1r0MWLmo4Jwzf27S4ggDzV4,5420
|
76
|
-
novel_downloader/resources/config/rules.toml,sha256=hrED6h3Z3cjSY5hRPQhp4TFAU5QXnN9xHfVABOJQNrM,4979
|
77
|
-
novel_downloader/resources/config/settings.yaml,sha256=NxtYrf2HWJQyGwIuj3f3JKA72Do5WPvSghonPM0Q7SM,3493
|
78
|
-
novel_downloader/resources/css_styles/main.css,sha256=WM6GePwdOGgM86fbbOxQ0_0oerTBDZeQHt8zRVfcJp8,1617
|
79
|
-
novel_downloader/resources/css_styles/volume-intro.css,sha256=6gaUnNKkrb2w8tYJRq1BGD1FwbhT1I5W2GI_Zelo9G4,1156
|
80
|
-
novel_downloader/resources/images/volume_border.png,sha256=2dEVimnTHKOfLMhi7bhkh_5joWNnrqg8duomLSNOZx4,28613
|
81
|
-
novel_downloader/resources/js_scripts/qidian_decrypt_node.js,sha256=spNrk_gXI7pPW9abr4XGc2LASMe1UuN4BUe4cH24L8s,2195
|
82
|
-
novel_downloader/resources/json/replace_word_map.json,sha256=ptL9sGO9aK7rnnAaOIyZ0OiH7gaT0BhFzficzYZSDks,55
|
83
|
-
novel_downloader/resources/text/blacklist.txt,sha256=sovK9JgARZP3lud5b1EZgvv8LSVKPthf4ADpCSZZgQ8,154
|
84
|
-
novel_downloader/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
85
|
-
novel_downloader/utils/cache.py,sha256=NB5j7CWNscfE4eFA0A9O5mYR1eW-216M-ljlMo0LDqE,615
|
86
|
-
novel_downloader/utils/constants.py,sha256=geLu9ufkM1plktIbF2VRzS5N5_N2XuHn0T03Kc0lGCQ,5520
|
87
|
-
novel_downloader/utils/crypto_utils.py,sha256=whGgir2oi_17pNteiIRztiMNaB-ZP63GMP3KPJkXA80,4178
|
88
|
-
novel_downloader/utils/hash_store.py,sha256=rpr61GsvZ9wT_1fEn4_83JZ-nWc1KLtcvb56ZqHawdk,9826
|
89
|
-
novel_downloader/utils/hash_utils.py,sha256=6S4-Q_uLNzdEDkBOUG9QEcflbuPFNDAYe6Gx718AOo4,2998
|
90
|
-
novel_downloader/utils/i18n.py,sha256=9vwBEuwk37ED29WI321-FWmA1_K4yv_qw84XUNbSr1s,1068
|
91
|
-
novel_downloader/utils/logger.py,sha256=Jk65uXuF4lyuygQHcnlJjIOCMgqn-in-Dz-K3mSItlE,3439
|
92
|
-
novel_downloader/utils/model_loader.py,sha256=zJETCQULf8GdW1eDV-Ez9W0GxFsQaqbCg9CTtr8G9LU,2079
|
93
|
-
novel_downloader/utils/network.py,sha256=5XXDTnKfpL2IQFY6y1N23rBsxn5NhgwrArcmn0gsbHo,8705
|
94
|
-
novel_downloader/utils/state.py,sha256=9ePYYSRMB43ob-OZ5KVUaq-6OlSsqTxQ2ItOw-47cvQ,5175
|
95
|
-
novel_downloader/utils/file_utils/__init__.py,sha256=L0xvZDnnskCITPFzU8PUUbGjw__5wJf1OqKhZUOamaY,1183
|
96
|
-
novel_downloader/utils/file_utils/io.py,sha256=Q1noPQ-MofSXFK5BwmBfgZqKctBRqzOQFlmI6lSkrAQ,7598
|
97
|
-
novel_downloader/utils/file_utils/normalize.py,sha256=7lqtVAMQO6z1JoCihLo-cf9PYniz6jU97Cf3zpkU8tQ,2078
|
98
|
-
novel_downloader/utils/file_utils/sanitize.py,sha256=dRgdtJx33G6DTFgEK0f1CFyTGUBKG5jxej2A-f7grQU,2324
|
99
|
-
novel_downloader/utils/fontocr/__init__.py,sha256=j8IrSs7wUPX8shg18wafo15hgQmqwUaqrfExbHJAaMY,567
|
100
|
-
novel_downloader/utils/fontocr/ocr_v1.py,sha256=hWB7cv6qQATpmrM0mVtRPlhBRmYKxJ9xNMiBrmo6__U,11351
|
101
|
-
novel_downloader/utils/fontocr/ocr_v2.py,sha256=RSmHfrilrRudExAjzkBm-_PknDNT9blp_2Eu2wCw54M,24457
|
102
|
-
novel_downloader/utils/text_utils/__init__.py,sha256=Iq6ZuS93J_M54nv1zPECryuPXJ-a0b3OE2wnyWqo-qs,830
|
103
|
-
novel_downloader/utils/text_utils/chapter_formatting.py,sha256=NeRKvZFspA5fcBrxhgqf4ZP-zq1vr8zNZ3viNOXhwhM,1347
|
104
|
-
novel_downloader/utils/text_utils/diff_display.py,sha256=cLjpeAOtpLOVMHnjgq2yv91fHvH0LvL1lMB80v3bPjQ,2552
|
105
|
-
novel_downloader/utils/text_utils/font_mapping.py,sha256=lai3lZSaxvSL1BZWgD6JLWdI56aWlZDeZ3zUYQS8pkc,916
|
106
|
-
novel_downloader/utils/text_utils/text_cleaning.py,sha256=1yuaDeUBHqBRkkWhw43rV1i8TL5rx1yK0I78FyEwcTw,1656
|
107
|
-
novel_downloader/utils/time_utils/__init__.py,sha256=bRpO14eorfH5C5xfqvW7QwSe3fQHhpr34j4O3qY5cGc,580
|
108
|
-
novel_downloader/utils/time_utils/datetime_utils.py,sha256=BX6W2dWpqEDMpAXF0pm2bPT7xZsy_Q_TZAiwd3dsiiE,4883
|
109
|
-
novel_downloader/utils/time_utils/sleep_utils.py,sha256=xClrFcjn4DdOO5KskO5WkGKt6LKZx0Cb8SMH8mQrlT0,1864
|
110
|
-
novel_downloader-1.2.2.dist-info/licenses/LICENSE,sha256=XgmnH0mBf-qEiizoVAfJQAKzPB9y3rBa-ni7M0Aqv4A,1066
|
111
|
-
novel_downloader-1.2.2.dist-info/METADATA,sha256=IjqO-vr2DU20Tdz3JEHo5hSWI6-3qDuXsbFAW8Af68c,6291
|
112
|
-
novel_downloader-1.2.2.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
113
|
-
novel_downloader-1.2.2.dist-info/entry_points.txt,sha256=v23QrJrfrAcYpxUYslCVxubOVRRTaTw7vlG_tfMsFP8,65
|
114
|
-
novel_downloader-1.2.2.dist-info/top_level.txt,sha256=hP4jYWM2LTm1jxsW4hqEB8N0dsRvldO2QdhggJT917I,17
|
115
|
-
novel_downloader-1.2.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|