novel-downloader 1.4.5__py3-none-any.whl → 1.5.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/__init__.py +2 -2
- novel_downloader/cli/config.py +1 -83
- novel_downloader/cli/download.py +4 -5
- novel_downloader/cli/export.py +4 -1
- novel_downloader/cli/main.py +2 -0
- novel_downloader/cli/search.py +123 -0
- novel_downloader/config/__init__.py +3 -10
- novel_downloader/config/adapter.py +190 -54
- novel_downloader/config/loader.py +2 -3
- novel_downloader/core/__init__.py +13 -13
- novel_downloader/core/downloaders/__init__.py +10 -11
- novel_downloader/core/downloaders/base.py +152 -26
- novel_downloader/core/downloaders/biquge.py +5 -1
- novel_downloader/core/downloaders/common.py +157 -378
- novel_downloader/core/downloaders/esjzone.py +5 -1
- novel_downloader/core/downloaders/linovelib.py +5 -1
- novel_downloader/core/downloaders/qianbi.py +291 -4
- novel_downloader/core/downloaders/qidian.py +199 -285
- novel_downloader/core/downloaders/registry.py +67 -0
- novel_downloader/core/downloaders/sfacg.py +5 -1
- novel_downloader/core/downloaders/yamibo.py +5 -1
- novel_downloader/core/exporters/__init__.py +10 -11
- novel_downloader/core/exporters/base.py +87 -7
- novel_downloader/core/exporters/biquge.py +5 -8
- novel_downloader/core/exporters/common/__init__.py +2 -2
- novel_downloader/core/exporters/common/epub.py +82 -166
- novel_downloader/core/exporters/common/main_exporter.py +0 -60
- novel_downloader/core/exporters/common/txt.py +82 -83
- novel_downloader/core/exporters/epub_util.py +157 -1330
- novel_downloader/core/exporters/esjzone.py +5 -8
- novel_downloader/core/exporters/linovelib/__init__.py +2 -2
- novel_downloader/core/exporters/linovelib/epub.py +157 -212
- novel_downloader/core/exporters/linovelib/main_exporter.py +2 -59
- novel_downloader/core/exporters/linovelib/txt.py +67 -63
- novel_downloader/core/exporters/qianbi.py +5 -8
- novel_downloader/core/exporters/qidian.py +14 -4
- novel_downloader/core/exporters/registry.py +53 -0
- novel_downloader/core/exporters/sfacg.py +5 -8
- novel_downloader/core/exporters/txt_util.py +67 -0
- novel_downloader/core/exporters/yamibo.py +5 -8
- novel_downloader/core/fetchers/__init__.py +19 -24
- novel_downloader/core/fetchers/base/__init__.py +3 -3
- novel_downloader/core/fetchers/base/browser.py +23 -4
- novel_downloader/core/fetchers/base/session.py +30 -5
- novel_downloader/core/fetchers/biquge/__init__.py +3 -3
- novel_downloader/core/fetchers/biquge/browser.py +5 -0
- novel_downloader/core/fetchers/biquge/session.py +6 -1
- novel_downloader/core/fetchers/esjzone/__init__.py +3 -3
- novel_downloader/core/fetchers/esjzone/browser.py +5 -0
- novel_downloader/core/fetchers/esjzone/session.py +6 -1
- novel_downloader/core/fetchers/linovelib/__init__.py +3 -3
- novel_downloader/core/fetchers/linovelib/browser.py +6 -1
- novel_downloader/core/fetchers/linovelib/session.py +6 -1
- novel_downloader/core/fetchers/qianbi/__init__.py +3 -3
- novel_downloader/core/fetchers/qianbi/browser.py +5 -0
- novel_downloader/core/fetchers/qianbi/session.py +5 -0
- novel_downloader/core/fetchers/qidian/__init__.py +3 -3
- novel_downloader/core/fetchers/qidian/browser.py +12 -4
- novel_downloader/core/fetchers/qidian/session.py +11 -3
- novel_downloader/core/fetchers/registry.py +71 -0
- novel_downloader/core/fetchers/sfacg/__init__.py +3 -3
- novel_downloader/core/fetchers/sfacg/browser.py +5 -0
- novel_downloader/core/fetchers/sfacg/session.py +5 -0
- novel_downloader/core/fetchers/yamibo/__init__.py +3 -3
- novel_downloader/core/fetchers/yamibo/browser.py +5 -0
- novel_downloader/core/fetchers/yamibo/session.py +6 -1
- novel_downloader/core/interfaces/__init__.py +7 -5
- novel_downloader/core/interfaces/searcher.py +18 -0
- novel_downloader/core/parsers/__init__.py +10 -11
- novel_downloader/core/parsers/{biquge/main_parser.py → biquge.py} +7 -2
- novel_downloader/core/parsers/{esjzone/main_parser.py → esjzone.py} +7 -2
- novel_downloader/core/parsers/{linovelib/main_parser.py → linovelib.py} +7 -2
- novel_downloader/core/parsers/{qianbi/main_parser.py → qianbi.py} +7 -2
- novel_downloader/core/parsers/qidian/__init__.py +2 -2
- novel_downloader/core/parsers/qidian/chapter_encrypted.py +23 -21
- novel_downloader/core/parsers/qidian/chapter_normal.py +1 -1
- novel_downloader/core/parsers/qidian/main_parser.py +10 -21
- novel_downloader/core/parsers/qidian/utils/__init__.py +11 -11
- novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +5 -6
- novel_downloader/core/parsers/qidian/utils/node_decryptor.py +2 -2
- novel_downloader/core/parsers/registry.py +68 -0
- novel_downloader/core/parsers/{sfacg/main_parser.py → sfacg.py} +7 -2
- novel_downloader/core/parsers/{yamibo/main_parser.py → yamibo.py} +7 -2
- novel_downloader/core/searchers/__init__.py +20 -0
- novel_downloader/core/searchers/base.py +92 -0
- novel_downloader/core/searchers/biquge.py +83 -0
- novel_downloader/core/searchers/esjzone.py +84 -0
- novel_downloader/core/searchers/qianbi.py +131 -0
- novel_downloader/core/searchers/qidian.py +87 -0
- novel_downloader/core/searchers/registry.py +63 -0
- novel_downloader/locales/en.json +12 -4
- novel_downloader/locales/zh.json +12 -4
- novel_downloader/models/__init__.py +4 -30
- novel_downloader/models/config.py +12 -6
- novel_downloader/models/search.py +16 -0
- novel_downloader/models/types.py +0 -2
- novel_downloader/resources/config/settings.toml +31 -4
- novel_downloader/resources/css_styles/intro.css +83 -0
- novel_downloader/resources/css_styles/main.css +30 -89
- novel_downloader/utils/__init__.py +52 -0
- novel_downloader/utils/chapter_storage.py +244 -224
- novel_downloader/utils/constants.py +1 -21
- novel_downloader/utils/epub/__init__.py +34 -0
- novel_downloader/utils/epub/builder.py +377 -0
- novel_downloader/utils/epub/constants.py +77 -0
- novel_downloader/utils/epub/documents.py +403 -0
- novel_downloader/utils/epub/models.py +134 -0
- novel_downloader/utils/epub/utils.py +212 -0
- novel_downloader/utils/file_utils/__init__.py +10 -14
- novel_downloader/utils/file_utils/io.py +20 -51
- novel_downloader/utils/file_utils/normalize.py +2 -2
- novel_downloader/utils/file_utils/sanitize.py +2 -3
- novel_downloader/utils/fontocr/__init__.py +5 -5
- novel_downloader/utils/{hash_store.py → fontocr/hash_store.py} +4 -3
- novel_downloader/utils/{hash_utils.py → fontocr/hash_utils.py} +2 -2
- novel_downloader/utils/fontocr/ocr_v1.py +13 -1
- novel_downloader/utils/fontocr/ocr_v2.py +13 -1
- novel_downloader/utils/fontocr/ocr_v3.py +744 -0
- novel_downloader/utils/i18n.py +2 -0
- novel_downloader/utils/logger.py +2 -0
- novel_downloader/utils/network.py +110 -251
- novel_downloader/utils/state.py +1 -0
- novel_downloader/utils/text_utils/__init__.py +18 -17
- novel_downloader/utils/text_utils/diff_display.py +4 -5
- novel_downloader/utils/text_utils/numeric_conversion.py +253 -0
- novel_downloader/utils/text_utils/text_cleaner.py +179 -0
- novel_downloader/utils/text_utils/truncate_utils.py +62 -0
- novel_downloader/utils/time_utils/__init__.py +3 -3
- novel_downloader/utils/time_utils/datetime_utils.py +4 -5
- novel_downloader/utils/time_utils/sleep_utils.py +2 -3
- {novel_downloader-1.4.5.dist-info → novel_downloader-1.5.0.dist-info}/METADATA +2 -2
- novel_downloader-1.5.0.dist-info/RECORD +164 -0
- novel_downloader/config/site_rules.py +0 -94
- novel_downloader/core/factory/__init__.py +0 -20
- novel_downloader/core/factory/downloader.py +0 -73
- novel_downloader/core/factory/exporter.py +0 -58
- novel_downloader/core/factory/fetcher.py +0 -96
- novel_downloader/core/factory/parser.py +0 -86
- novel_downloader/core/fetchers/common/__init__.py +0 -14
- novel_downloader/core/fetchers/common/browser.py +0 -79
- novel_downloader/core/fetchers/common/session.py +0 -79
- novel_downloader/core/parsers/biquge/__init__.py +0 -10
- novel_downloader/core/parsers/common/__init__.py +0 -13
- novel_downloader/core/parsers/common/helper.py +0 -323
- novel_downloader/core/parsers/common/main_parser.py +0 -106
- novel_downloader/core/parsers/esjzone/__init__.py +0 -10
- novel_downloader/core/parsers/linovelib/__init__.py +0 -10
- novel_downloader/core/parsers/qianbi/__init__.py +0 -10
- novel_downloader/core/parsers/sfacg/__init__.py +0 -10
- novel_downloader/core/parsers/yamibo/__init__.py +0 -10
- novel_downloader/models/browser.py +0 -21
- novel_downloader/models/site_rules.py +0 -99
- novel_downloader/models/tasks.py +0 -33
- novel_downloader/resources/css_styles/volume-intro.css +0 -56
- novel_downloader/resources/json/replace_word_map.json +0 -4
- novel_downloader/resources/text/blacklist.txt +0 -22
- novel_downloader/utils/text_utils/chapter_formatting.py +0 -46
- novel_downloader/utils/text_utils/font_mapping.py +0 -28
- novel_downloader/utils/text_utils/text_cleaning.py +0 -107
- novel_downloader-1.4.5.dist-info/RECORD +0 -165
- {novel_downloader-1.4.5.dist-info → novel_downloader-1.5.0.dist-info}/WHEEL +0 -0
- {novel_downloader-1.4.5.dist-info → novel_downloader-1.5.0.dist-info}/entry_points.txt +0 -0
- {novel_downloader-1.4.5.dist-info → novel_downloader-1.5.0.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-1.4.5.dist-info → novel_downloader-1.5.0.dist-info}/top_level.txt +0 -0
@@ -1,99 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.models.site_rules
|
4
|
-
----------------------------------
|
5
|
-
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import Any, Literal, TypedDict
|
9
|
-
|
10
|
-
|
11
|
-
class RuleStep(TypedDict, total=False):
|
12
|
-
# —— 操作类型 —— #
|
13
|
-
type: Literal[
|
14
|
-
"attr",
|
15
|
-
"select_one",
|
16
|
-
"select",
|
17
|
-
"find",
|
18
|
-
"find_all",
|
19
|
-
"exclude",
|
20
|
-
"regex",
|
21
|
-
"text",
|
22
|
-
"strip",
|
23
|
-
"replace",
|
24
|
-
"split",
|
25
|
-
"join",
|
26
|
-
]
|
27
|
-
|
28
|
-
# —— BeautifulSoup 相关 —— #
|
29
|
-
selector: str | None # CSS 选择器, 用于 select/select_one/exclude
|
30
|
-
name: str | None # 标签名称, 用于 find/find_all
|
31
|
-
attrs: dict[str, Any] | None # 属性过滤, 用于 find/find_all
|
32
|
-
limit: int | None # find_all 的最大匹配数
|
33
|
-
attr: str | None # 从元素获取属性值 (select/select_one/select_all)
|
34
|
-
|
35
|
-
# —— 正则相关 —— #
|
36
|
-
pattern: str | None # 正则表达式
|
37
|
-
flags: int | None # re.I, re.M 等
|
38
|
-
group: int | None # 匹配结果中的第几个分组 (默认 0)
|
39
|
-
template: str | None # 自定义组合, 比如 "$1$2字"
|
40
|
-
|
41
|
-
# —— 文本处理 —— #
|
42
|
-
chars: str | None # strip 要去除的字符集
|
43
|
-
old: str | None # replace 中要被替换的子串
|
44
|
-
new: str | None # replace 中新的子串
|
45
|
-
count: int | None # replace 中的最大替换次数
|
46
|
-
sep: str | None # split/join 的分隔符
|
47
|
-
index: int | None # split/select_all/select 之后取第几个元素
|
48
|
-
|
49
|
-
|
50
|
-
class FieldRules(TypedDict):
|
51
|
-
steps: list[RuleStep]
|
52
|
-
|
53
|
-
|
54
|
-
class ChapterFieldRules(TypedDict):
|
55
|
-
key: str
|
56
|
-
steps: list[RuleStep]
|
57
|
-
|
58
|
-
|
59
|
-
class VolumesRulesOptional(TypedDict, total=False):
|
60
|
-
volume_selector: str # 有卷时选择 volume 块的 selector
|
61
|
-
volume_name_steps: list[RuleStep]
|
62
|
-
volume_mode: str # Optional: "normal" (default) or "mixed"
|
63
|
-
list_selector: str # Optional: If "mixed" mode, parent container selector
|
64
|
-
|
65
|
-
|
66
|
-
class VolumesRules(VolumesRulesOptional):
|
67
|
-
has_volume: bool # 是否存在卷,false=未分卷
|
68
|
-
chapter_selector: str # 选择 chapter 节点的 selector
|
69
|
-
chapter_steps: list[ChapterFieldRules] # 提取章节信息的步骤列表
|
70
|
-
|
71
|
-
|
72
|
-
class BookInfoRules(TypedDict, total=False):
|
73
|
-
book_name: FieldRules
|
74
|
-
author: FieldRules
|
75
|
-
cover_url: FieldRules
|
76
|
-
update_time: FieldRules
|
77
|
-
serial_status: FieldRules
|
78
|
-
word_count: FieldRules
|
79
|
-
summary: FieldRules
|
80
|
-
volumes: VolumesRules
|
81
|
-
|
82
|
-
|
83
|
-
class ChapterRules(TypedDict, total=False):
|
84
|
-
title: FieldRules
|
85
|
-
content: FieldRules
|
86
|
-
|
87
|
-
|
88
|
-
class SiteProfile(TypedDict):
|
89
|
-
book_info_url: str
|
90
|
-
chapter_url: str
|
91
|
-
|
92
|
-
|
93
|
-
class SiteRules(TypedDict):
|
94
|
-
profile: SiteProfile
|
95
|
-
book_info: BookInfoRules
|
96
|
-
chapter: ChapterRules
|
97
|
-
|
98
|
-
|
99
|
-
SiteRulesDict = dict[str, SiteRules]
|
novel_downloader/models/tasks.py
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.models.tasks
|
4
|
-
-----------------------------
|
5
|
-
|
6
|
-
"""
|
7
|
-
|
8
|
-
from dataclasses import dataclass
|
9
|
-
|
10
|
-
|
11
|
-
@dataclass
|
12
|
-
class CidTask:
|
13
|
-
prev_cid: str | None
|
14
|
-
cid: str
|
15
|
-
retry: int = 0
|
16
|
-
vol_idx: int = 0
|
17
|
-
chap_idx: int = 0
|
18
|
-
|
19
|
-
|
20
|
-
@dataclass
|
21
|
-
class RestoreTask:
|
22
|
-
vol_idx: int
|
23
|
-
chap_idx: int
|
24
|
-
prev_cid: str
|
25
|
-
|
26
|
-
|
27
|
-
@dataclass
|
28
|
-
class HtmlTask:
|
29
|
-
cid: str
|
30
|
-
retry: int
|
31
|
-
html_list: list[str]
|
32
|
-
vol_idx: int = 0
|
33
|
-
chap_idx: int = 0
|
@@ -1,56 +0,0 @@
|
|
1
|
-
/*标题页*/
|
2
|
-
|
3
|
-
h1.volume-title-line1 {
|
4
|
-
font-size: 1.25rem; /* 第一行较大 */
|
5
|
-
font-weight: bold;
|
6
|
-
text-align: center;
|
7
|
-
text-indent: 0em;
|
8
|
-
duokan-text-indent: 0em;
|
9
|
-
color: #6e471c;
|
10
|
-
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8);
|
11
|
-
margin: 0;
|
12
|
-
display: block;
|
13
|
-
}
|
14
|
-
|
15
|
-
p.volume-title-line2 {
|
16
|
-
font-size: 1rem; /* 第二行稍小 */
|
17
|
-
font-weight: bold;
|
18
|
-
text-align: center;
|
19
|
-
text-indent: 0em;
|
20
|
-
duokan-text-indent: 0em;
|
21
|
-
color: #6e471c;
|
22
|
-
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8);
|
23
|
-
margin: 0;
|
24
|
-
display: block;
|
25
|
-
}
|
26
|
-
|
27
|
-
div.border1 {
|
28
|
-
margin: 35% auto 0 auto;
|
29
|
-
text-align: center;
|
30
|
-
text-indent: 0em;
|
31
|
-
duokan-text-indent: 0em;
|
32
|
-
}
|
33
|
-
|
34
|
-
div.border2 {
|
35
|
-
margin: 0 auto 0 auto;
|
36
|
-
text-align: center;
|
37
|
-
text-indent: 0em;
|
38
|
-
duokan-text-indent: 0em;
|
39
|
-
transform: rotate(180deg);
|
40
|
-
-ms-transform: rotate(180deg);
|
41
|
-
/* IE 9 */
|
42
|
-
-moz-transform: rotate(180deg);
|
43
|
-
/* Firefox */
|
44
|
-
-webkit-transform: rotate(180deg);
|
45
|
-
/* Safari 和 Chrome */
|
46
|
-
-o-transform: rotate(180deg);
|
47
|
-
/* Opera */;
|
48
|
-
}
|
49
|
-
|
50
|
-
img.border1 {
|
51
|
-
width: 100%;
|
52
|
-
}
|
53
|
-
|
54
|
-
img.border2 {
|
55
|
-
width: 80%;
|
56
|
-
}
|
@@ -1,46 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.utils.text_utils.chapter_formatting
|
4
|
-
----------------------------------------------------
|
5
|
-
|
6
|
-
Format chapter content with title, paragraph blocks, and optional author notes.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import re
|
10
|
-
|
11
|
-
_IMG_TAG_RE = re.compile(r"<img[^>]*>")
|
12
|
-
|
13
|
-
|
14
|
-
def format_chapter(title: str, paragraphs: str, author_say: str | None = None) -> str:
|
15
|
-
"""
|
16
|
-
Build a formatted chapter string with title, paragraphs, and optional author note.
|
17
|
-
|
18
|
-
:param title: The chapter title.
|
19
|
-
:param paragraphs: Raw multi-line string; lines are treated as paragraphs.
|
20
|
-
:param author_say: Optional author comment to append at the end.
|
21
|
-
:return: A single string where title, paragraphs, and author note
|
22
|
-
are separated by blank lines.
|
23
|
-
"""
|
24
|
-
parts: list[str] = [title.strip()]
|
25
|
-
|
26
|
-
# add each nonempty paragraph line
|
27
|
-
paragraphs = _IMG_TAG_RE.sub("", paragraphs)
|
28
|
-
for ln in paragraphs.splitlines():
|
29
|
-
line = ln.strip()
|
30
|
-
if line:
|
31
|
-
parts.append(line)
|
32
|
-
|
33
|
-
# add author_say lines if present
|
34
|
-
if author_say:
|
35
|
-
author_lines = [ln.strip() for ln in author_say.splitlines() if ln.strip()]
|
36
|
-
if author_lines:
|
37
|
-
parts.append("---")
|
38
|
-
parts.append("作者说:")
|
39
|
-
parts.extend(author_lines)
|
40
|
-
|
41
|
-
return "\n\n".join(parts)
|
42
|
-
|
43
|
-
|
44
|
-
__all__ = [
|
45
|
-
"format_chapter",
|
46
|
-
]
|
@@ -1,28 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.utils.text_utils.font_mapping
|
4
|
-
----------------------------------------------
|
5
|
-
|
6
|
-
Utility for decoding obfuscated text by applying character-level font mapping.
|
7
|
-
|
8
|
-
This is commonly used to reverse font-based obfuscation in scraped content,
|
9
|
-
where characters are visually disguised via custom font glyphs but can be
|
10
|
-
recovered using a known mapping.
|
11
|
-
"""
|
12
|
-
|
13
|
-
|
14
|
-
def apply_font_mapping(text: str, font_map: dict[str, str]) -> str:
|
15
|
-
"""
|
16
|
-
Replace each character in `text` using `font_map`,
|
17
|
-
leaving unmapped characters unchanged.
|
18
|
-
|
19
|
-
:param text: The input string, possibly containing obfuscated font chars.
|
20
|
-
:param font_map: A dict mapping obfuscated chars to real chars.
|
21
|
-
:return: The de-obfuscated text.
|
22
|
-
"""
|
23
|
-
return "".join(font_map.get(ch, ch) for ch in text)
|
24
|
-
|
25
|
-
|
26
|
-
__all__ = [
|
27
|
-
"apply_font_mapping",
|
28
|
-
]
|
@@ -1,107 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.utils.text_utils.text_cleaning
|
4
|
-
-----------------------------------------------
|
5
|
-
|
6
|
-
Tools for detecting and removing promotional or ad-like content from text.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import math
|
10
|
-
import re
|
11
|
-
|
12
|
-
from novel_downloader.utils.file_utils.io import load_blacklisted_words
|
13
|
-
|
14
|
-
# --- Constants & Precompiled Patterns ---
|
15
|
-
|
16
|
-
_BLACKLISTED_WORDS = load_blacklisted_words()
|
17
|
-
|
18
|
-
_BRACKET_PATTERN = re.compile(r"[\((](.*?)[\))]")
|
19
|
-
_K_PROMO_PATTERN = re.compile(r"\b\d{1,4}k\b", re.IGNORECASE)
|
20
|
-
|
21
|
-
|
22
|
-
def clean_chapter_title(title: str) -> str:
|
23
|
-
"""
|
24
|
-
Remove bracketed promotional content from a chapter title.
|
25
|
-
|
26
|
-
If any blacklisted word appears inside parentheses (Chinese or English),
|
27
|
-
the entire bracketed section is stripped.
|
28
|
-
|
29
|
-
:param title: Original title, possibly containing ad text in brackets.
|
30
|
-
:return: Title with offending bracketed sections removed.
|
31
|
-
"""
|
32
|
-
cleaned = title
|
33
|
-
for content in _BRACKET_PATTERN.findall(title):
|
34
|
-
if any(bw in content for bw in _BLACKLISTED_WORDS):
|
35
|
-
cleaned = re.sub(rf"[\((]{re.escape(content)}[\))]", "", cleaned)
|
36
|
-
return cleaned.strip()
|
37
|
-
|
38
|
-
|
39
|
-
def is_promotional_line(line: str) -> bool:
|
40
|
-
"""
|
41
|
-
Check if a line of text likely contains promotional or ad-like content.
|
42
|
-
|
43
|
-
:param line: A single line of text.
|
44
|
-
:return: True if it contains promo keywords or a '###k' vote count pattern.
|
45
|
-
"""
|
46
|
-
low = line.lower()
|
47
|
-
if any(kw in low for kw in _BLACKLISTED_WORDS):
|
48
|
-
return True
|
49
|
-
if _K_PROMO_PATTERN.search(low):
|
50
|
-
return True
|
51
|
-
return False
|
52
|
-
|
53
|
-
|
54
|
-
def content_prefix(
|
55
|
-
text: str,
|
56
|
-
n: int,
|
57
|
-
ignore_chars: set[str] | None = None,
|
58
|
-
) -> str:
|
59
|
-
"""
|
60
|
-
Return the prefix of `text` containing the first `n` non-ignored characters.
|
61
|
-
|
62
|
-
:param text: The full input string.
|
63
|
-
:param n: Number of content characters to include.
|
64
|
-
:param ignore_chars: Characters to ignore when counting content.
|
65
|
-
:return: Truncated string preserving original whitespace and line breaks.
|
66
|
-
"""
|
67
|
-
ignore = ignore_chars or set()
|
68
|
-
cnt = 0
|
69
|
-
|
70
|
-
for i, ch in enumerate(text):
|
71
|
-
if ch not in ignore:
|
72
|
-
cnt += 1
|
73
|
-
if cnt >= n:
|
74
|
-
return text[: i + 1]
|
75
|
-
|
76
|
-
return text
|
77
|
-
|
78
|
-
|
79
|
-
def truncate_half_lines(text: str) -> str:
|
80
|
-
"""
|
81
|
-
Keep the first half of the lines (rounded up), preserving line breaks.
|
82
|
-
|
83
|
-
:param text: Full input text
|
84
|
-
:return: Truncated text with first half of lines
|
85
|
-
"""
|
86
|
-
lines = text.splitlines()
|
87
|
-
non_empty_lines = [line for line in lines if line.strip()]
|
88
|
-
keep_count = math.ceil(len(non_empty_lines) / 2)
|
89
|
-
|
90
|
-
result_lines = []
|
91
|
-
count = 0
|
92
|
-
for line in lines:
|
93
|
-
result_lines.append(line)
|
94
|
-
if line.strip():
|
95
|
-
count += 1
|
96
|
-
if count >= keep_count:
|
97
|
-
break
|
98
|
-
|
99
|
-
return "\n".join(result_lines)
|
100
|
-
|
101
|
-
|
102
|
-
__all__ = [
|
103
|
-
"clean_chapter_title",
|
104
|
-
"is_promotional_line",
|
105
|
-
"content_prefix",
|
106
|
-
"truncate_half_lines",
|
107
|
-
]
|
@@ -1,165 +0,0 @@
|
|
1
|
-
novel_downloader/__init__.py,sha256=D4TLFZz_e2GGLXLUmjASiuLDco00RW6Lg3AI38kcgUg,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=wj6wW4osxdB0VA0VeO5Tt2f6HY5CL0Gp8BeoaMzb9Is,6801
|
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=Kp_QOE-ntj5yWBYUnrdNj7ab-R9ZcmBNnMi_dHkv4Gs,8395
|
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=sYwhveDjNQu0oKfS9obWVJGmbxyN8lIWIRiGvGOBZRI,989
|
13
|
-
novel_downloader/core/downloaders/__init__.py,sha256=AK5zeetVXOn_irgHp-NORPYW65UJM4CsF8ysxf2vKD4,1064
|
14
|
-
novel_downloader/core/downloaders/base.py,sha256=aZECG_HkCPNOGoGY6n8hEue769J2tlAqHz5LHGSwwNw,6525
|
15
|
-
novel_downloader/core/downloaders/biquge.py,sha256=u1HkO3UvIq9lrQGJrU8UCBEqMnqPstL_AnfTRcK0J3c,583
|
16
|
-
novel_downloader/core/downloaders/common.py,sha256=TAojiAhVGXDaIxbCpAvB4FecLh1TSj8oQDuY9tNynC4,16259
|
17
|
-
novel_downloader/core/downloaders/esjzone.py,sha256=rRT2zMft-js2aOMxL71tsWR-to9FIIzua48DzKVwpgM,587
|
18
|
-
novel_downloader/core/downloaders/linovelib.py,sha256=tMRuZPRBBt-w0Te7A0Kc2Jjqz-Y_c3TmLhHxJSdxGXo,595
|
19
|
-
novel_downloader/core/downloaders/qianbi.py,sha256=ZuwRjMW-2VZRxJxUg3n3168hyhX779cLRC3VSlUYZBU,583
|
20
|
-
novel_downloader/core/downloaders/qidian.py,sha256=Zix-9dLMgt2kuMSOPbl9zdZ-TMawfOV5VkGRIrM6-T8,13003
|
21
|
-
novel_downloader/core/downloaders/sfacg.py,sha256=kEp3N4ycXJFNh3XqLfIV8MJzy9zi5OOH9XYlXDOO3nY,579
|
22
|
-
novel_downloader/core/downloaders/yamibo.py,sha256=oV4VpwCMtvWdEfDUijozId-LRZPlZkLlnkyyLx7_ZuM,583
|
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/epub_util.py,sha256=uSMB_55v6xKJcKyFjJZghl0ZgCFsdGbJJHH22G-BkeQ,37377
|
27
|
-
novel_downloader/core/exporters/esjzone.py,sha256=UP9gtTOv6komWjgvwXkttqDYJJPjjbJdiG3yz9RxHSQ,467
|
28
|
-
novel_downloader/core/exporters/qianbi.py,sha256=x841MNIxpS5eY8u91ODC0cpIhpT-ENnFqs_Yx6HwtdM,462
|
29
|
-
novel_downloader/core/exporters/qidian.py,sha256=ecaZcgqXyLvJtT2J5QXw4qS9gY3d72mgUnV-0frJvhQ,724
|
30
|
-
novel_downloader/core/exporters/sfacg.py,sha256=j4_H-ixvDxd_OJfIvD4Lbs24LaiFjaYqhvhZcks-ItI,457
|
31
|
-
novel_downloader/core/exporters/yamibo.py,sha256=QaY13llqpyxIgmMnMVFtR5yFMIpyMHHdCmVDW4Dq-bo,462
|
32
|
-
novel_downloader/core/exporters/common/__init__.py,sha256=qIOZ_TgnnQZ6p45YQsxpTcB69e0Jq9XMG3IY0NBVsTM,274
|
33
|
-
novel_downloader/core/exporters/common/epub.py,sha256=_hFoc3aVRf7xxrWCvukN7Iv5ulYbkSq53nQMfaZb75E,8833
|
34
|
-
novel_downloader/core/exporters/common/main_exporter.py,sha256=-MRZEpAdsfdRt3VxIv4krMaw2UJnrvCnyj5Jde93zuA,3926
|
35
|
-
novel_downloader/core/exporters/common/txt.py,sha256=b5cNvH0hrjaBO89Uddn1IUY1BFhkHJdTd7WjSWk4ndk,4719
|
36
|
-
novel_downloader/core/exporters/linovelib/__init__.py,sha256=zD7A7OhluipwICssnp27c_oenYozevZH9g0Qj5WOMWY,195
|
37
|
-
novel_downloader/core/exporters/linovelib/epub.py,sha256=yVqv-lnc7Nh-COd4POvQ0vbsAw18NJ8oFO88-zKedb4,13048
|
38
|
-
novel_downloader/core/exporters/linovelib/main_exporter.py,sha256=cHkAp_jdF6uji5Avu1l8z6mR0nSrWYgX6ETDEezkjoE,3700
|
39
|
-
novel_downloader/core/exporters/linovelib/txt.py,sha256=ALlZUl5nNtg4OmYlurMC0acjmTOBV7G8c13DPrxbG4w,4407
|
40
|
-
novel_downloader/core/factory/__init__.py,sha256=_IY3N35onhWD_nw_TyxKOxa6e7Uak9Cv0bp4pK9yb0M,464
|
41
|
-
novel_downloader/core/factory/downloader.py,sha256=M3yGIdHhthYdvUmXP-jJiVojmBcOf293q5YftgjWzfg,1923
|
42
|
-
novel_downloader/core/factory/exporter.py,sha256=CjDJGnWBDk-S1zYntIDAEo1hLM2q55tlJOjTXKn0hAI,1533
|
43
|
-
novel_downloader/core/factory/fetcher.py,sha256=stfRJnh5ZXLqRsDtQC1BDeTe0yaZI-mgm3Qx03nWUP4,2402
|
44
|
-
novel_downloader/core/factory/parser.py,sha256=0PXepJhlE6aGs9_t81vyho1eCw84-6XRBGb98_phvSQ,2237
|
45
|
-
novel_downloader/core/fetchers/__init__.py,sha256=C1OykEdCzj3fpLRRhVrvwClpzz-pzTzTilH306crgYg,1440
|
46
|
-
novel_downloader/core/fetchers/base/__init__.py,sha256=p9be-q2YjiHcQhv4_KMeZmHgaAYYyUDWoBo6Gvwughc,224
|
47
|
-
novel_downloader/core/fetchers/base/browser.py,sha256=6bXhCLc4hxzQgCoEoMspAY1Hn3TT1hjQNIJX0CSNzgw,11927
|
48
|
-
novel_downloader/core/fetchers/base/rate_limiter.py,sha256=zUYH_PjnKfUzJpcbUPtMkwXxIlF0SH-ZTFlbCUrq060,2724
|
49
|
-
novel_downloader/core/fetchers/base/session.py,sha256=Elfpov2cqojunCrLaaSL9ZgWLNVanUDZvgOoIfk5sSc,13251
|
50
|
-
novel_downloader/core/fetchers/biquge/__init__.py,sha256=9EW4eerGeob4QGoDr11A8Mv7xvcfWVFU57M3VT9vzPI,236
|
51
|
-
novel_downloader/core/fetchers/biquge/browser.py,sha256=vplaCRAz8ECxk-yXm7DxSxW3EyX8GCYJMeImUut53RI,2390
|
52
|
-
novel_downloader/core/fetchers/biquge/session.py,sha256=waxv_dPsBl2SeudaINjt-eUwpW-FcDP2zFN_1-NXhr8,2400
|
53
|
-
novel_downloader/core/fetchers/common/__init__.py,sha256=ur_zQHrmJdPsFvpyC8AWjsZptHLbBHLb3EuKLt6LRVc,236
|
54
|
-
novel_downloader/core/fetchers/common/browser.py,sha256=RgNOizfgi_59Xaee6lTlpfiCMGjz_4luNDlHLQqUpl0,2289
|
55
|
-
novel_downloader/core/fetchers/common/session.py,sha256=Ydtwun9lPN4VEIIEIA7Skm6_GOiF_9VDUPkjGQQTdtM,2299
|
56
|
-
novel_downloader/core/fetchers/esjzone/__init__.py,sha256=Cr30WpKEnCrG_vVqttfI9T0zdkwDsLFOnCxQz4EAQQA,242
|
57
|
-
novel_downloader/core/fetchers/esjzone/browser.py,sha256=bs9o97FRbtx8VSp1AfS0sljD0Izc16JDWqB_EL6GHT4,6278
|
58
|
-
novel_downloader/core/fetchers/esjzone/session.py,sha256=hwvS9LMWm5PYHTTZqYkBgWqkVqkrCfQcaFh6NBICt1Q,7218
|
59
|
-
novel_downloader/core/fetchers/linovelib/__init__.py,sha256=sMNXSBvn8gaZxNX5x4Ork8RzXxL7PhuigquWx6zQ6A4,254
|
60
|
-
novel_downloader/core/fetchers/linovelib/browser.py,sha256=9rQzmJwtu_FHDDQvgDrVIZdwHA7CjnBkIgdyBuy7X50,6086
|
61
|
-
novel_downloader/core/fetchers/linovelib/session.py,sha256=2BpYe7kqIhHLbrH6Lk4TA4f8d_OHVO6lxHzZ-VVuG30,6096
|
62
|
-
novel_downloader/core/fetchers/qianbi/__init__.py,sha256=h4Rve7fO1GcSJ-DlNC5zw7fjoldJy4chG9RZQf5DuCU,236
|
63
|
-
novel_downloader/core/fetchers/qianbi/browser.py,sha256=1EmrSwpqSYhEO_ID3RJbUaAOhcqvVnMnch6iOafXbTA,3162
|
64
|
-
novel_downloader/core/fetchers/qianbi/session.py,sha256=c3pJcgi9C1x9QYTBihvazHcgT7XTp2HBYfStTn6gSEg,3141
|
65
|
-
novel_downloader/core/fetchers/qidian/__init__.py,sha256=2LshlX82lFpWZMV6yujHsfue9KM0-F1O3HvMCopIv9M,236
|
66
|
-
novel_downloader/core/fetchers/qidian/browser.py,sha256=0L2iUyOlFNmgKtSb89VMrF7L-MjiJy4E6SSKWxzeSC8,10448
|
67
|
-
novel_downloader/core/fetchers/qidian/session.py,sha256=dsawkalQGjbS-E9lcOZMTr9qZz6w__gnmAg-uRUtDKI,9809
|
68
|
-
novel_downloader/core/fetchers/sfacg/__init__.py,sha256=bQAIwERsX9XOKrP2LteFKX8Jlhw4oeUNwpZTHXn5RRg,230
|
69
|
-
novel_downloader/core/fetchers/sfacg/browser.py,sha256=15PVS75PxEKR5W7mQbqVxoN0d4V1XVYVF0l1yy_sv_Y,5681
|
70
|
-
novel_downloader/core/fetchers/sfacg/session.py,sha256=9K4emQCRq45vzYn-ZDX549tK2F92x2CBMp4ODohNOjc,5085
|
71
|
-
novel_downloader/core/fetchers/yamibo/__init__.py,sha256=5ds6DNNvpo6F6U5dboEaIsJoKSPorkPte_HWVnXMdXo,236
|
72
|
-
novel_downloader/core/fetchers/yamibo/browser.py,sha256=rkLgIIxLeFV2r4oAT0pOgiKgnp9HJ6X_fwfQIShhgj0,7265
|
73
|
-
novel_downloader/core/fetchers/yamibo/session.py,sha256=434EArdKgEYIBZkb1nMub3PQXdRTS-Ov2_1u9MESjOs,7212
|
74
|
-
novel_downloader/core/interfaces/__init__.py,sha256=hB1SjBzuN7qnZx_h3RV4w_roj3ZwShbIG3CV9jGMB14,602
|
75
|
-
novel_downloader/core/interfaces/downloader.py,sha256=H0S4o5MW22JcvNVECv1bCdwAN0drBwHY31IbvVHn-X0,1557
|
76
|
-
novel_downloader/core/interfaces/exporter.py,sha256=zwIaJ5FXo_JmKYg2UZV9FTWX7xZ2e0QuL4RTNGRtI04,1610
|
77
|
-
novel_downloader/core/interfaces/fetcher.py,sha256=XlP3d-Q_xvuVextZCdLOxDf8BwBbx799L_WLJx0WTB8,4096
|
78
|
-
novel_downloader/core/interfaces/parser.py,sha256=iZeUgNl-zE-wsf1eW4GVCPjEaLSvQrNJi_mVEOU9ulY,1353
|
79
|
-
novel_downloader/core/parsers/__init__.py,sha256=lrpt5E1YMiI0WY_cco1lEDhBQZJ_ZEV4b5fR6Fs3ZwA,832
|
80
|
-
novel_downloader/core/parsers/base.py,sha256=GifJANFm0auYyzYuqYox9LFgDskW8G2vR0DaMrRcG1w,2962
|
81
|
-
novel_downloader/core/parsers/biquge/__init__.py,sha256=oaLgBLdMW7DcdsEGXW-S91Z6_p5XmBcBIp7TX79hmV4,173
|
82
|
-
novel_downloader/core/parsers/biquge/main_parser.py,sha256=mbrEjJ8iSvWZ7SU4RH8pHxs1jnEwwlag_KkhTYoU0sY,4572
|
83
|
-
novel_downloader/core/parsers/common/__init__.py,sha256=MzNUUxvf7jmeO0LvQ_FRW0QLKuYVXkkTgJ4CxWZKF-Y,341
|
84
|
-
novel_downloader/core/parsers/common/helper.py,sha256=U5SzhVJJ5lGRNhLoOdEQw9LfBuPv17dmyT_MbdgnCl0,12052
|
85
|
-
novel_downloader/core/parsers/common/main_parser.py,sha256=znuXTJC-TXsgBTB3Hyqi87L65bqyM90TYyjU1KEhswc,3229
|
86
|
-
novel_downloader/core/parsers/esjzone/__init__.py,sha256=RSsUdOvaiqv-rTaYVc-qO25jytRCj9X2EYErMltA_b8,177
|
87
|
-
novel_downloader/core/parsers/esjzone/main_parser.py,sha256=jF7WPAwN5S2uUOdXk3fCkM3PSS5DPhI-SzmP00GFItw,8520
|
88
|
-
novel_downloader/core/parsers/linovelib/__init__.py,sha256=t5xzMEb4Q9MZxOvedOnot2HR6nCtU5YnAxGUk2lJoMA,185
|
89
|
-
novel_downloader/core/parsers/linovelib/main_parser.py,sha256=LqC6W-Lk7sdbiqhYvqQAh2z31v23OtMzyp1kAelsugI,7565
|
90
|
-
novel_downloader/core/parsers/qianbi/__init__.py,sha256=CNmoER8U2u4-ix5S0DDq-pHTtkLR0IZf2SLaTTYXee4,173
|
91
|
-
novel_downloader/core/parsers/qianbi/main_parser.py,sha256=kMjGew_dmqjI9oIThyHgxThZZgS3IaESB_tNf1nkCKk,5069
|
92
|
-
novel_downloader/core/parsers/qidian/__init__.py,sha256=fWWFeyythX0gpDCJ-2AslrRl2hq4vW2bx9hHh1W7mAw,173
|
93
|
-
novel_downloader/core/parsers/qidian/book_info_parser.py,sha256=TbP8nghoxzBi435cSJKAzWttBRUq49MHw6kn0klfZrU,3056
|
94
|
-
novel_downloader/core/parsers/qidian/chapter_encrypted.py,sha256=uIVmRH96O_G0hcvg2nufUQDrZzq_XRhfvB_8YRW22g8,18532
|
95
|
-
novel_downloader/core/parsers/qidian/chapter_normal.py,sha256=CClt6zVph7qjZ0HaiYzMPYlcFgnPIY783-SLVIXNL7E,4738
|
96
|
-
novel_downloader/core/parsers/qidian/chapter_router.py,sha256=foVMlWtE-qUOvJD_4EDiuAVaNkFdeV_ZTCvS5IL7Orc,1957
|
97
|
-
novel_downloader/core/parsers/qidian/main_parser.py,sha256=jeo7Ypnf-tsBGucjBYBdPzXGd8N4N2eOERuHREloT0o,4504
|
98
|
-
novel_downloader/core/parsers/qidian/utils/__init__.py,sha256=-7-nNMtX-KONSN3Q6-f3Yaxt9Oc3Y63kg5ZvNl6xlkY,588
|
99
|
-
novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py,sha256=8ytJnAfiJIxj0wlke9UwYA6vngUyLxVZt8PbfkNUhss,4687
|
100
|
-
novel_downloader/core/parsers/qidian/utils/helpers.py,sha256=v64zTDQ6qbKnGXM7MPzCsS7yQ-w730vPVrDD19Bgx4Q,3514
|
101
|
-
novel_downloader/core/parsers/qidian/utils/node_decryptor.py,sha256=gjqirr5RECScFw0C6DET7ZMaLTcqGcPOmlkwFUJbTHQ,5965
|
102
|
-
novel_downloader/core/parsers/sfacg/__init__.py,sha256=O2nscvtOweMXHMONdvySTsLSy1ulhv53WTp4r6J47tI,169
|
103
|
-
novel_downloader/core/parsers/sfacg/main_parser.py,sha256=yW18MALAZisJdFO-7peI1h-4XVloEDXeCJvXUz5hJ1A,5899
|
104
|
-
novel_downloader/core/parsers/yamibo/__init__.py,sha256=KJ_fCcakoQrsG36OOd0paXXB1cAIwMirKaA8ZLUKUKI,173
|
105
|
-
novel_downloader/core/parsers/yamibo/main_parser.py,sha256=9sNXsDR2iDVyTYupP_7PyE7BXf2po3sZLq1XEFA8DrI,6554
|
106
|
-
novel_downloader/locales/en.json,sha256=mcGv24zHS2FFimwCYRLMD8CYzAzngTv1tODZP64GWvY,7002
|
107
|
-
novel_downloader/locales/zh.json,sha256=7kkKGt1fudSC9LvmFyAgXfyCC512XfCoyf5by8Egqnc,6849
|
108
|
-
novel_downloader/models/__init__.py,sha256=5aQ24IeU8OJDhBZdZ8Ov-xWoLlZm6Qg24r5FPyLTa6Q,1102
|
109
|
-
novel_downloader/models/browser.py,sha256=ly-jM7izQ77yTIG-oau51HJofDpBfrXpIJZJjoQyad8,435
|
110
|
-
novel_downloader/models/chapter.py,sha256=bdAQUDZIuuTVxoYjoOJrbS2u81b1B2mkuZkTSf0m2HQ,492
|
111
|
-
novel_downloader/models/config.py,sha256=mFrGZALhZzalWn9wtgRdwGnmgwh6xE0dXAaO7mFIrRc,3013
|
112
|
-
novel_downloader/models/login.py,sha256=sY2Jom6PLpA9Z3Uy7plZKhda3Gq7awKOOIIaQ79PpWs,371
|
113
|
-
novel_downloader/models/site_rules.py,sha256=kzDB5F8lf4udAO0WVUrgBOR7ave3jsMBxt7cEoG0bnI,2721
|
114
|
-
novel_downloader/models/tasks.py,sha256=e4DYEXQQQewgQyCCHfc0UYnkPJ96LafmhG3oO5MQP0Q,465
|
115
|
-
novel_downloader/models/types.py,sha256=q1KDuGW0SVxQILKKoPXKRecfaKe2m8jUM0nyaeDJ6dE,394
|
116
|
-
novel_downloader/resources/config/settings.toml,sha256=gp5RrnSHJmnvrx75QwFxadKZVLWh8mnCy99aCwqirdQ,4580
|
117
|
-
novel_downloader/resources/css_styles/main.css,sha256=WM6GePwdOGgM86fbbOxQ0_0oerTBDZeQHt8zRVfcJp8,1617
|
118
|
-
novel_downloader/resources/css_styles/volume-intro.css,sha256=6gaUnNKkrb2w8tYJRq1BGD1FwbhT1I5W2GI_Zelo9G4,1156
|
119
|
-
novel_downloader/resources/images/volume_border.png,sha256=2dEVimnTHKOfLMhi7bhkh_5joWNnrqg8duomLSNOZx4,28613
|
120
|
-
novel_downloader/resources/js_scripts/qidian_decrypt_node.js,sha256=spNrk_gXI7pPW9abr4XGc2LASMe1UuN4BUe4cH24L8s,2195
|
121
|
-
novel_downloader/resources/json/linovelib_font_map.json,sha256=F1IlEcvXGcagnZCu4Gw2vQ2NLnhy6cJOLhabukqnftw,67854
|
122
|
-
novel_downloader/resources/json/replace_word_map.json,sha256=ptL9sGO9aK7rnnAaOIyZ0OiH7gaT0BhFzficzYZSDks,55
|
123
|
-
novel_downloader/resources/text/blacklist.txt,sha256=sovK9JgARZP3lud5b1EZgvv8LSVKPthf4ADpCSZZgQ8,154
|
124
|
-
novel_downloader/tui/__init__.py,sha256=8RB8tBrPcoBzm1tpQlgZqnOZXrdHmlzMRxuk9wsN4m0,115
|
125
|
-
novel_downloader/tui/app.py,sha256=ytV1u15nGCRj_ff_GeAL3W1XlU6r5Lh_k3HBcAjPRx0,731
|
126
|
-
novel_downloader/tui/main.py,sha256=MBP8SrwEYTpGQm-V9W_4rKnTeslneORfkzFsU3Xj2yA,256
|
127
|
-
novel_downloader/tui/screens/__init__.py,sha256=QsUM5cUEKm7nluQh9acEt37xRWbkZU3vqIpBduepDCU,203
|
128
|
-
novel_downloader/tui/screens/home.py,sha256=nH3pRuCOFcSvNV4AYC6RRkWpphmRgY1bNK36OkSVfCg,6994
|
129
|
-
novel_downloader/tui/screens/login.py,sha256=GK8dXCtH5lGu3ilT1Cv2VmFCwHMspDNpzw0logj2lz0,2225
|
130
|
-
novel_downloader/tui/styles/home_layout.tcss,sha256=VNJs339qiwNUuqwwdK6VkYThCdsqlw-2mEoZVCspdrw,974
|
131
|
-
novel_downloader/tui/widgets/richlog_handler.py,sha256=bhFb0E7Z7-dRS07y_vMjxjPeCic9AD59MFPLhef_R5g,572
|
132
|
-
novel_downloader/utils/__init__.py,sha256=4iUXNUzxeAnGmpGWsB4K_jckUYEW0u_LqWp_OM7mtK8,78
|
133
|
-
novel_downloader/utils/cache.py,sha256=_jVEWAaMGY86kWVnAuuIvJA_hA8dH2ClI7o3p99mEvE,618
|
134
|
-
novel_downloader/utils/chapter_storage.py,sha256=wXXIzNjs1GfPPoqgYYPnQ9Two23McW6ZZNDmhfSC9aY,9831
|
135
|
-
novel_downloader/utils/constants.py,sha256=EaxQllQ_dIce5_eRTgAJ-OXRtEk3cMhLUbOKA359198,4435
|
136
|
-
novel_downloader/utils/cookies.py,sha256=WuPBt_z7cF4n7QPIw1julATWt6dbDRCbNdgXHSikmjo,2042
|
137
|
-
novel_downloader/utils/crypto_utils.py,sha256=BRlVR9Nvbu8TQXocJb3po1-kD5HkbCV0yyT84nq_XtI,2052
|
138
|
-
novel_downloader/utils/hash_store.py,sha256=HfzthzcKbHbVaHNpqjaAs2wDeq7iIeY8Mzkt_4v80jQ,9388
|
139
|
-
novel_downloader/utils/hash_utils.py,sha256=7eC7WsO_kl25OnRYWzIXbCXsewxvCcvRCzetsf-wbTo,3023
|
140
|
-
novel_downloader/utils/i18n.py,sha256=pdAcSIA5Tp-uPEBwNByHL7C1NayTnpOsl7zFv9p2G1k,1033
|
141
|
-
novel_downloader/utils/logger.py,sha256=9h1iFS8_auiquNgOBd-Q2pbbcnAhAKL39yf3PKadu00,3339
|
142
|
-
novel_downloader/utils/network.py,sha256=W0SVr55MSUjTmMPkUvvkH10SRgFx3GWrCN_fDavfk4A,9143
|
143
|
-
novel_downloader/utils/state.py,sha256=FcNJ85GvBu7uEIjy0QHGr4sXMbHPEMkCjwUKNg5EabI,5132
|
144
|
-
novel_downloader/utils/file_utils/__init__.py,sha256=zvOm2qSEmWd_mRGJceGBZb5MYMSDAlWYjS5MkVQNZgI,1159
|
145
|
-
novel_downloader/utils/file_utils/io.py,sha256=AZ3NUe6lifGsYt3iYyXyQ2BO41WV8j013LpZy4KSjJQ,7473
|
146
|
-
novel_downloader/utils/file_utils/normalize.py,sha256=MrsCq4FqmskKRkHRV_J0z0dmn69OerMum-9sqx2XOGM,2023
|
147
|
-
novel_downloader/utils/file_utils/sanitize.py,sha256=rE-u4vpDL10zH8FT8d9wqwWsz-7dR6PJ-LE45K8VaeE,2112
|
148
|
-
novel_downloader/utils/fontocr/__init__.py,sha256=fe-04om3xxBvFKt5BBCApXCzv-Z0K_AY7lv9IB1jEHM,543
|
149
|
-
novel_downloader/utils/fontocr/model_loader.py,sha256=aBPZlwZ-rx2tDsWtN3BnB15vceqNkqTEBX1h2pMZf3E,2012
|
150
|
-
novel_downloader/utils/fontocr/ocr_v1.py,sha256=S8GAuDUiVv3mciQvgHEibAhJ2DIow6bHs_ZSYvboC4c,11224
|
151
|
-
novel_downloader/utils/fontocr/ocr_v2.py,sha256=XiTHNeRcCw4Q441Tfdox6Sq91dHPfUYg5MecO8qfcB8,27286
|
152
|
-
novel_downloader/utils/text_utils/__init__.py,sha256=tAO8oCryMAwQoCCpTKaLJagQ6UK8tJXU55MYomWI-6c,913
|
153
|
-
novel_downloader/utils/text_utils/chapter_formatting.py,sha256=WAAEAcI7zI_uIeARDybZfXDdMvGio3VIkANFrK8-8Os,1378
|
154
|
-
novel_downloader/utils/text_utils/diff_display.py,sha256=aUvjMcYO-1_P8ZYiYbmYbJOByKo2bWoBV_ifRuAqwb8,2528
|
155
|
-
novel_downloader/utils/text_utils/font_mapping.py,sha256=Aos5skBhowDdPgnYmK0bpLtNm2hZg3RolNlTkxC9kO8,865
|
156
|
-
novel_downloader/utils/text_utils/text_cleaning.py,sha256=zufXt0pc0vnUwgSHD_8LAef3ffqmX9rJ11YzW4rgwLA,2940
|
157
|
-
novel_downloader/utils/time_utils/__init__.py,sha256=725vY2PvqFhjbAz0hCOuIuhSCK8HrEqQ_k3YwvubmXo,624
|
158
|
-
novel_downloader/utils/time_utils/datetime_utils.py,sha256=3sPdUjDC7Y7dcX6kaQSBu49BU1tnpERNKq0v9lnD170,4932
|
159
|
-
novel_downloader/utils/time_utils/sleep_utils.py,sha256=C4XYeAtxoVZC9Ju6vhhP9sbOrSpdZG2Nm-x1IYO_OFA,3233
|
160
|
-
novel_downloader-1.4.5.dist-info/licenses/LICENSE,sha256=XgmnH0mBf-qEiizoVAfJQAKzPB9y3rBa-ni7M0Aqv4A,1066
|
161
|
-
novel_downloader-1.4.5.dist-info/METADATA,sha256=Et3KgvnjS1RjOo-dX-GRZg6q4TU8uIzg1vMYfPR7sxs,7253
|
162
|
-
novel_downloader-1.4.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
163
|
-
novel_downloader-1.4.5.dist-info/entry_points.txt,sha256=u1Ns5xI_QJyL4HAFCgJvJdib9ugu7M9I2tnQwZjJxrk,112
|
164
|
-
novel_downloader-1.4.5.dist-info/top_level.txt,sha256=hP4jYWM2LTm1jxsW4hqEB8N0dsRvldO2QdhggJT917I,17
|
165
|
-
novel_downloader-1.4.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|