novel-downloader 1.4.1__py3-none-any.whl → 1.4.3__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 +70 -11
- novel_downloader/config/adapter.py +43 -9
- novel_downloader/core/__init__.py +19 -1
- novel_downloader/core/downloaders/base.py +26 -29
- novel_downloader/core/downloaders/biquge.py +1 -3
- novel_downloader/core/downloaders/common.py +41 -7
- novel_downloader/core/downloaders/esjzone.py +1 -3
- novel_downloader/core/downloaders/linovelib.py +1 -3
- novel_downloader/core/downloaders/qianbi.py +1 -3
- novel_downloader/core/downloaders/qidian.py +61 -37
- novel_downloader/core/downloaders/sfacg.py +1 -3
- novel_downloader/core/downloaders/yamibo.py +1 -3
- novel_downloader/core/exporters/common/epub.py +153 -68
- novel_downloader/core/exporters/epub_util.py +1358 -0
- novel_downloader/core/exporters/linovelib/epub.py +147 -190
- novel_downloader/core/factory/downloader.py +3 -6
- novel_downloader/core/fetchers/base/browser.py +32 -12
- novel_downloader/core/fetchers/esjzone/browser.py +8 -6
- novel_downloader/core/fetchers/qidian/browser.py +62 -10
- novel_downloader/core/fetchers/yamibo/browser.py +3 -3
- novel_downloader/core/interfaces/downloader.py +13 -12
- novel_downloader/core/parsers/qidian/chapter_encrypted.py +11 -2
- novel_downloader/core/parsers/qidian/chapter_normal.py +8 -1
- novel_downloader/core/parsers/qidian/main_parser.py +7 -2
- novel_downloader/core/parsers/qidian/utils/__init__.py +2 -0
- novel_downloader/core/parsers/qidian/utils/helpers.py +9 -0
- novel_downloader/locales/en.json +2 -0
- novel_downloader/locales/zh.json +2 -0
- novel_downloader/models/__init__.py +2 -0
- novel_downloader/models/config.py +9 -0
- novel_downloader/resources/config/settings.toml +1 -0
- novel_downloader/tui/screens/home.py +13 -6
- novel_downloader/utils/constants.py +0 -29
- novel_downloader/utils/{model_loader.py → fontocr/model_loader.py} +2 -2
- novel_downloader/utils/fontocr/ocr_v1.py +2 -1
- novel_downloader/utils/fontocr/ocr_v2.py +2 -1
- novel_downloader/utils/text_utils/__init__.py +8 -1
- novel_downloader/utils/text_utils/text_cleaning.py +51 -0
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.dist-info}/METADATA +5 -2
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.dist-info}/RECORD +45 -50
- novel_downloader/core/exporters/epub_utils/__init__.py +0 -40
- novel_downloader/core/exporters/epub_utils/css_builder.py +0 -75
- novel_downloader/core/exporters/epub_utils/image_loader.py +0 -131
- novel_downloader/core/exporters/epub_utils/initializer.py +0 -100
- novel_downloader/core/exporters/epub_utils/text_to_html.py +0 -178
- novel_downloader/core/exporters/epub_utils/volume_intro.py +0 -60
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.dist-info}/WHEEL +0 -0
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.dist-info}/entry_points.txt +0 -0
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.dist-info}/licenses/LICENSE +0 -0
- {novel_downloader-1.4.1.dist-info → novel_downloader-1.4.3.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.4.
|
3
|
+
Version: 1.4.3
|
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
|
@@ -46,7 +46,6 @@ Requires-Dist: aiohttp
|
|
46
46
|
Requires-Dist: playwright
|
47
47
|
Requires-Dist: lxml
|
48
48
|
Requires-Dist: platformdirs
|
49
|
-
Requires-Dist: ebooklib
|
50
49
|
Provides-Extra: dev
|
51
50
|
Requires-Dist: black; extra == "dev"
|
52
51
|
Requires-Dist: mypy; extra == "dev"
|
@@ -55,6 +54,7 @@ Requires-Dist: pytest; extra == "dev"
|
|
55
54
|
Requires-Dist: pytest-cov; extra == "dev"
|
56
55
|
Requires-Dist: pytest-mock; extra == "dev"
|
57
56
|
Requires-Dist: types-requests; extra == "dev"
|
57
|
+
Requires-Dist: types-lxml; extra == "dev"
|
58
58
|
Requires-Dist: types-PyYAML; extra == "dev"
|
59
59
|
Requires-Dist: pre-commit; extra == "dev"
|
60
60
|
Requires-Dist: commitizen; extra == "dev"
|
@@ -109,6 +109,8 @@ playwright install
|
|
109
109
|
pip install novel-downloader[font-recovery]
|
110
110
|
```
|
111
111
|
|
112
|
+
- 详细可见: [安装](https://github.com/BowenZ217/novel-downloader/blob/main/docs/1-installation.md)
|
113
|
+
|
112
114
|
---
|
113
115
|
|
114
116
|
### CLI 模式
|
@@ -180,6 +182,7 @@ pip install .
|
|
180
182
|
- [CLI 使用示例](https://github.com/BowenZ217/novel-downloader/blob/main/docs/6-cli-usage-examples.md)
|
181
183
|
- [复制 Cookies](https://github.com/BowenZ217/novel-downloader/blob/main/docs/copy-cookies.md)
|
182
184
|
- [文件保存](https://github.com/BowenZ217/novel-downloader/blob/main/docs/file-saving.md)
|
185
|
+
- [模块与接口文档](https://github.com/BowenZ217/novel-downloader/blob/main/docs/api/README.md)
|
183
186
|
- [TODO](https://github.com/BowenZ217/novel-downloader/blob/main/docs/todo.md)
|
184
187
|
- [开发](https://github.com/BowenZ217/novel-downloader/blob/main/docs/develop.md)
|
185
188
|
- [项目说明](#项目说明)
|
@@ -1,55 +1,50 @@
|
|
1
|
-
novel_downloader/__init__.py,sha256=
|
1
|
+
novel_downloader/__init__.py,sha256=JN4ThR5xMeCKx_BPUuZvUrtJJaTH5Tx7ORZZURIY0iY,218
|
2
2
|
novel_downloader/cli/__init__.py,sha256=-2HAut_U1e67MZGdvbpEJ1n5J-bRchzto6L4c-nWeXY,174
|
3
3
|
novel_downloader/cli/clean.py,sha256=hOk8SJQwBCw2oOObTdEI79wpnmZ25uB1s9LQK1-4LNU,4487
|
4
4
|
novel_downloader/cli/config.py,sha256=C6QLfegZLp4legmu8KenqyYKNdrk47bH0z86ujLP0pY,6509
|
5
|
-
novel_downloader/cli/download.py,sha256=
|
5
|
+
novel_downloader/cli/download.py,sha256=wj6wW4osxdB0VA0VeO5Tt2f6HY5CL0Gp8BeoaMzb9Is,6801
|
6
6
|
novel_downloader/cli/export.py,sha256=x9uvyLuvkuaDZGoH212aHZ7XyPT9b2S78AmTN6rkAu4,2283
|
7
7
|
novel_downloader/cli/main.py,sha256=9J8KMuYwL01X6chIaXpQNeS5d3pHnwB9vA9XjKd8RrM,919
|
8
8
|
novel_downloader/config/__init__.py,sha256=2mnf33MQOUnLGCnL1NtNV_rHBejNxBNIbobIGN0tw4E,666
|
9
|
-
novel_downloader/config/adapter.py,sha256=
|
9
|
+
novel_downloader/config/adapter.py,sha256=Kp_QOE-ntj5yWBYUnrdNj7ab-R9ZcmBNnMi_dHkv4Gs,8395
|
10
10
|
novel_downloader/config/loader.py,sha256=jo_1rr3UKZRAFFYgO-oHpYLRhF431chmfx4fLGh0MKw,5743
|
11
11
|
novel_downloader/config/site_rules.py,sha256=CJksBSvVAC4sR6cEruf4pM1Jv0zTJb1lcHq0Yn6LPFM,2979
|
12
|
-
novel_downloader/core/__init__.py,sha256=
|
12
|
+
novel_downloader/core/__init__.py,sha256=sYwhveDjNQu0oKfS9obWVJGmbxyN8lIWIRiGvGOBZRI,989
|
13
13
|
novel_downloader/core/downloaders/__init__.py,sha256=AK5zeetVXOn_irgHp-NORPYW65UJM4CsF8ysxf2vKD4,1064
|
14
|
-
novel_downloader/core/downloaders/base.py,sha256=
|
15
|
-
novel_downloader/core/downloaders/biquge.py,sha256=
|
16
|
-
novel_downloader/core/downloaders/common.py,sha256=
|
17
|
-
novel_downloader/core/downloaders/esjzone.py,sha256=
|
18
|
-
novel_downloader/core/downloaders/linovelib.py,sha256=
|
19
|
-
novel_downloader/core/downloaders/qianbi.py,sha256=
|
20
|
-
novel_downloader/core/downloaders/qidian.py,sha256=
|
21
|
-
novel_downloader/core/downloaders/sfacg.py,sha256=
|
22
|
-
novel_downloader/core/downloaders/yamibo.py,sha256=
|
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
23
|
novel_downloader/core/exporters/__init__.py,sha256=ATkkdh6RUIaM19mG1XjFiaMnGRgFFGT3ixsqVkU13Q0,867
|
24
24
|
novel_downloader/core/exporters/base.py,sha256=duIdLnj9kKNZ9r2aJV0Rzl-rnQCP8olk12uzduT9PtE,6146
|
25
25
|
novel_downloader/core/exporters/biquge.py,sha256=SJCChYtDLJKrOpwDCT8IeR0v1LoiUQuTTejfGmRnxX8,462
|
26
|
+
novel_downloader/core/exporters/epub_util.py,sha256=uSMB_55v6xKJcKyFjJZghl0ZgCFsdGbJJHH22G-BkeQ,37377
|
26
27
|
novel_downloader/core/exporters/esjzone.py,sha256=UP9gtTOv6komWjgvwXkttqDYJJPjjbJdiG3yz9RxHSQ,467
|
27
28
|
novel_downloader/core/exporters/qianbi.py,sha256=x841MNIxpS5eY8u91ODC0cpIhpT-ENnFqs_Yx6HwtdM,462
|
28
29
|
novel_downloader/core/exporters/qidian.py,sha256=ecaZcgqXyLvJtT2J5QXw4qS9gY3d72mgUnV-0frJvhQ,724
|
29
30
|
novel_downloader/core/exporters/sfacg.py,sha256=j4_H-ixvDxd_OJfIvD4Lbs24LaiFjaYqhvhZcks-ItI,457
|
30
31
|
novel_downloader/core/exporters/yamibo.py,sha256=QaY13llqpyxIgmMnMVFtR5yFMIpyMHHdCmVDW4Dq-bo,462
|
31
32
|
novel_downloader/core/exporters/common/__init__.py,sha256=qIOZ_TgnnQZ6p45YQsxpTcB69e0Jq9XMG3IY0NBVsTM,274
|
32
|
-
novel_downloader/core/exporters/common/epub.py,sha256=
|
33
|
+
novel_downloader/core/exporters/common/epub.py,sha256=_hFoc3aVRf7xxrWCvukN7Iv5ulYbkSq53nQMfaZb75E,8833
|
33
34
|
novel_downloader/core/exporters/common/main_exporter.py,sha256=-MRZEpAdsfdRt3VxIv4krMaw2UJnrvCnyj5Jde93zuA,3926
|
34
35
|
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
36
|
novel_downloader/core/exporters/linovelib/__init__.py,sha256=zD7A7OhluipwICssnp27c_oenYozevZH9g0Qj5WOMWY,195
|
42
|
-
novel_downloader/core/exporters/linovelib/epub.py,sha256=
|
37
|
+
novel_downloader/core/exporters/linovelib/epub.py,sha256=yVqv-lnc7Nh-COd4POvQ0vbsAw18NJ8oFO88-zKedb4,13048
|
43
38
|
novel_downloader/core/exporters/linovelib/main_exporter.py,sha256=cHkAp_jdF6uji5Avu1l8z6mR0nSrWYgX6ETDEezkjoE,3700
|
44
39
|
novel_downloader/core/exporters/linovelib/txt.py,sha256=ALlZUl5nNtg4OmYlurMC0acjmTOBV7G8c13DPrxbG4w,4407
|
45
40
|
novel_downloader/core/factory/__init__.py,sha256=_IY3N35onhWD_nw_TyxKOxa6e7Uak9Cv0bp4pK9yb0M,464
|
46
|
-
novel_downloader/core/factory/downloader.py,sha256=
|
41
|
+
novel_downloader/core/factory/downloader.py,sha256=M3yGIdHhthYdvUmXP-jJiVojmBcOf293q5YftgjWzfg,1923
|
47
42
|
novel_downloader/core/factory/exporter.py,sha256=CjDJGnWBDk-S1zYntIDAEo1hLM2q55tlJOjTXKn0hAI,1533
|
48
43
|
novel_downloader/core/factory/fetcher.py,sha256=stfRJnh5ZXLqRsDtQC1BDeTe0yaZI-mgm3Qx03nWUP4,2402
|
49
44
|
novel_downloader/core/factory/parser.py,sha256=0PXepJhlE6aGs9_t81vyho1eCw84-6XRBGb98_phvSQ,2237
|
50
45
|
novel_downloader/core/fetchers/__init__.py,sha256=C1OykEdCzj3fpLRRhVrvwClpzz-pzTzTilH306crgYg,1440
|
51
46
|
novel_downloader/core/fetchers/base/__init__.py,sha256=p9be-q2YjiHcQhv4_KMeZmHgaAYYyUDWoBo6Gvwughc,224
|
52
|
-
novel_downloader/core/fetchers/base/browser.py,sha256=
|
47
|
+
novel_downloader/core/fetchers/base/browser.py,sha256=6bXhCLc4hxzQgCoEoMspAY1Hn3TT1hjQNIJX0CSNzgw,11927
|
53
48
|
novel_downloader/core/fetchers/base/rate_limiter.py,sha256=zUYH_PjnKfUzJpcbUPtMkwXxIlF0SH-ZTFlbCUrq060,2724
|
54
49
|
novel_downloader/core/fetchers/base/session.py,sha256=Elfpov2cqojunCrLaaSL9ZgWLNVanUDZvgOoIfk5sSc,13251
|
55
50
|
novel_downloader/core/fetchers/biquge/__init__.py,sha256=9EW4eerGeob4QGoDr11A8Mv7xvcfWVFU57M3VT9vzPI,236
|
@@ -59,7 +54,7 @@ novel_downloader/core/fetchers/common/__init__.py,sha256=ur_zQHrmJdPsFvpyC8AWjsZ
|
|
59
54
|
novel_downloader/core/fetchers/common/browser.py,sha256=RgNOizfgi_59Xaee6lTlpfiCMGjz_4luNDlHLQqUpl0,2289
|
60
55
|
novel_downloader/core/fetchers/common/session.py,sha256=Ydtwun9lPN4VEIIEIA7Skm6_GOiF_9VDUPkjGQQTdtM,2299
|
61
56
|
novel_downloader/core/fetchers/esjzone/__init__.py,sha256=Cr30WpKEnCrG_vVqttfI9T0zdkwDsLFOnCxQz4EAQQA,242
|
62
|
-
novel_downloader/core/fetchers/esjzone/browser.py,sha256=
|
57
|
+
novel_downloader/core/fetchers/esjzone/browser.py,sha256=bs9o97FRbtx8VSp1AfS0sljD0Izc16JDWqB_EL6GHT4,6278
|
63
58
|
novel_downloader/core/fetchers/esjzone/session.py,sha256=hwvS9LMWm5PYHTTZqYkBgWqkVqkrCfQcaFh6NBICt1Q,7218
|
64
59
|
novel_downloader/core/fetchers/linovelib/__init__.py,sha256=sMNXSBvn8gaZxNX5x4Ork8RzXxL7PhuigquWx6zQ6A4,254
|
65
60
|
novel_downloader/core/fetchers/linovelib/browser.py,sha256=9rQzmJwtu_FHDDQvgDrVIZdwHA7CjnBkIgdyBuy7X50,6086
|
@@ -68,16 +63,16 @@ novel_downloader/core/fetchers/qianbi/__init__.py,sha256=h4Rve7fO1GcSJ-DlNC5zw7f
|
|
68
63
|
novel_downloader/core/fetchers/qianbi/browser.py,sha256=1EmrSwpqSYhEO_ID3RJbUaAOhcqvVnMnch6iOafXbTA,3162
|
69
64
|
novel_downloader/core/fetchers/qianbi/session.py,sha256=c3pJcgi9C1x9QYTBihvazHcgT7XTp2HBYfStTn6gSEg,3141
|
70
65
|
novel_downloader/core/fetchers/qidian/__init__.py,sha256=2LshlX82lFpWZMV6yujHsfue9KM0-F1O3HvMCopIv9M,236
|
71
|
-
novel_downloader/core/fetchers/qidian/browser.py,sha256=
|
66
|
+
novel_downloader/core/fetchers/qidian/browser.py,sha256=cUgJMrFe_MITHh4MGrDI2-a-MCqXSsoeJsbDus0l2LY,10448
|
72
67
|
novel_downloader/core/fetchers/qidian/session.py,sha256=WrHsov15PoRDYbb1ZRaScJQGRZv6axz9_hVEC1Wt1PM,9746
|
73
68
|
novel_downloader/core/fetchers/sfacg/__init__.py,sha256=bQAIwERsX9XOKrP2LteFKX8Jlhw4oeUNwpZTHXn5RRg,230
|
74
69
|
novel_downloader/core/fetchers/sfacg/browser.py,sha256=15PVS75PxEKR5W7mQbqVxoN0d4V1XVYVF0l1yy_sv_Y,5681
|
75
70
|
novel_downloader/core/fetchers/sfacg/session.py,sha256=9K4emQCRq45vzYn-ZDX549tK2F92x2CBMp4ODohNOjc,5085
|
76
71
|
novel_downloader/core/fetchers/yamibo/__init__.py,sha256=5ds6DNNvpo6F6U5dboEaIsJoKSPorkPte_HWVnXMdXo,236
|
77
|
-
novel_downloader/core/fetchers/yamibo/browser.py,sha256=
|
72
|
+
novel_downloader/core/fetchers/yamibo/browser.py,sha256=rkLgIIxLeFV2r4oAT0pOgiKgnp9HJ6X_fwfQIShhgj0,7265
|
78
73
|
novel_downloader/core/fetchers/yamibo/session.py,sha256=434EArdKgEYIBZkb1nMub3PQXdRTS-Ov2_1u9MESjOs,7212
|
79
74
|
novel_downloader/core/interfaces/__init__.py,sha256=hB1SjBzuN7qnZx_h3RV4w_roj3ZwShbIG3CV9jGMB14,602
|
80
|
-
novel_downloader/core/interfaces/downloader.py,sha256=
|
75
|
+
novel_downloader/core/interfaces/downloader.py,sha256=H0S4o5MW22JcvNVECv1bCdwAN0drBwHY31IbvVHn-X0,1557
|
81
76
|
novel_downloader/core/interfaces/exporter.py,sha256=zwIaJ5FXo_JmKYg2UZV9FTWX7xZ2e0QuL4RTNGRtI04,1610
|
82
77
|
novel_downloader/core/interfaces/fetcher.py,sha256=XlP3d-Q_xvuVextZCdLOxDf8BwBbx799L_WLJx0WTB8,4096
|
83
78
|
novel_downloader/core/interfaces/parser.py,sha256=iZeUgNl-zE-wsf1eW4GVCPjEaLSvQrNJi_mVEOU9ulY,1353
|
@@ -96,29 +91,29 @@ novel_downloader/core/parsers/qianbi/__init__.py,sha256=CNmoER8U2u4-ix5S0DDq-pHT
|
|
96
91
|
novel_downloader/core/parsers/qianbi/main_parser.py,sha256=kMjGew_dmqjI9oIThyHgxThZZgS3IaESB_tNf1nkCKk,5069
|
97
92
|
novel_downloader/core/parsers/qidian/__init__.py,sha256=fWWFeyythX0gpDCJ-2AslrRl2hq4vW2bx9hHh1W7mAw,173
|
98
93
|
novel_downloader/core/parsers/qidian/book_info_parser.py,sha256=h5oAVJOOSZMV4U2GnSezVHPJOEUKUic_oD2gl94mEPQ,3721
|
99
|
-
novel_downloader/core/parsers/qidian/chapter_encrypted.py,sha256=
|
100
|
-
novel_downloader/core/parsers/qidian/chapter_normal.py,sha256=
|
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
|
101
96
|
novel_downloader/core/parsers/qidian/chapter_router.py,sha256=foVMlWtE-qUOvJD_4EDiuAVaNkFdeV_ZTCvS5IL7Orc,1957
|
102
|
-
novel_downloader/core/parsers/qidian/main_parser.py,sha256=
|
103
|
-
novel_downloader/core/parsers/qidian/utils/__init__.py,sha256
|
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
|
104
99
|
novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py,sha256=8ytJnAfiJIxj0wlke9UwYA6vngUyLxVZt8PbfkNUhss,4687
|
105
|
-
novel_downloader/core/parsers/qidian/utils/helpers.py,sha256
|
100
|
+
novel_downloader/core/parsers/qidian/utils/helpers.py,sha256=v64zTDQ6qbKnGXM7MPzCsS7yQ-w730vPVrDD19Bgx4Q,3514
|
106
101
|
novel_downloader/core/parsers/qidian/utils/node_decryptor.py,sha256=gjqirr5RECScFw0C6DET7ZMaLTcqGcPOmlkwFUJbTHQ,5965
|
107
102
|
novel_downloader/core/parsers/sfacg/__init__.py,sha256=O2nscvtOweMXHMONdvySTsLSy1ulhv53WTp4r6J47tI,169
|
108
103
|
novel_downloader/core/parsers/sfacg/main_parser.py,sha256=yW18MALAZisJdFO-7peI1h-4XVloEDXeCJvXUz5hJ1A,5899
|
109
104
|
novel_downloader/core/parsers/yamibo/__init__.py,sha256=KJ_fCcakoQrsG36OOd0paXXB1cAIwMirKaA8ZLUKUKI,173
|
110
105
|
novel_downloader/core/parsers/yamibo/main_parser.py,sha256=9sNXsDR2iDVyTYupP_7PyE7BXf2po3sZLq1XEFA8DrI,6554
|
111
|
-
novel_downloader/locales/en.json,sha256
|
112
|
-
novel_downloader/locales/zh.json,sha256=
|
113
|
-
novel_downloader/models/__init__.py,sha256=
|
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
|
114
109
|
novel_downloader/models/browser.py,sha256=ly-jM7izQ77yTIG-oau51HJofDpBfrXpIJZJjoQyad8,435
|
115
110
|
novel_downloader/models/chapter.py,sha256=bdAQUDZIuuTVxoYjoOJrbS2u81b1B2mkuZkTSf0m2HQ,492
|
116
|
-
novel_downloader/models/config.py,sha256=
|
111
|
+
novel_downloader/models/config.py,sha256=mFrGZALhZzalWn9wtgRdwGnmgwh6xE0dXAaO7mFIrRc,3013
|
117
112
|
novel_downloader/models/login.py,sha256=sY2Jom6PLpA9Z3Uy7plZKhda3Gq7awKOOIIaQ79PpWs,371
|
118
113
|
novel_downloader/models/site_rules.py,sha256=kzDB5F8lf4udAO0WVUrgBOR7ave3jsMBxt7cEoG0bnI,2721
|
119
114
|
novel_downloader/models/tasks.py,sha256=e4DYEXQQQewgQyCCHfc0UYnkPJ96LafmhG3oO5MQP0Q,465
|
120
115
|
novel_downloader/models/types.py,sha256=q1KDuGW0SVxQILKKoPXKRecfaKe2m8jUM0nyaeDJ6dE,394
|
121
|
-
novel_downloader/resources/config/settings.toml,sha256=
|
116
|
+
novel_downloader/resources/config/settings.toml,sha256=gp5RrnSHJmnvrx75QwFxadKZVLWh8mnCy99aCwqirdQ,4580
|
122
117
|
novel_downloader/resources/css_styles/main.css,sha256=WM6GePwdOGgM86fbbOxQ0_0oerTBDZeQHt8zRVfcJp8,1617
|
123
118
|
novel_downloader/resources/css_styles/volume-intro.css,sha256=6gaUnNKkrb2w8tYJRq1BGD1FwbhT1I5W2GI_Zelo9G4,1156
|
124
119
|
novel_downloader/resources/images/volume_border.png,sha256=2dEVimnTHKOfLMhi7bhkh_5joWNnrqg8duomLSNOZx4,28613
|
@@ -130,21 +125,20 @@ novel_downloader/tui/__init__.py,sha256=8RB8tBrPcoBzm1tpQlgZqnOZXrdHmlzMRxuk9wsN
|
|
130
125
|
novel_downloader/tui/app.py,sha256=ytV1u15nGCRj_ff_GeAL3W1XlU6r5Lh_k3HBcAjPRx0,731
|
131
126
|
novel_downloader/tui/main.py,sha256=MBP8SrwEYTpGQm-V9W_4rKnTeslneORfkzFsU3Xj2yA,256
|
132
127
|
novel_downloader/tui/screens/__init__.py,sha256=QsUM5cUEKm7nluQh9acEt37xRWbkZU3vqIpBduepDCU,203
|
133
|
-
novel_downloader/tui/screens/home.py,sha256=
|
128
|
+
novel_downloader/tui/screens/home.py,sha256=nH3pRuCOFcSvNV4AYC6RRkWpphmRgY1bNK36OkSVfCg,6994
|
134
129
|
novel_downloader/tui/screens/login.py,sha256=eEVmQFZKQX8mCt_qp96QK8t2pB15FeUrk_oV3jm_Mz4,2224
|
135
130
|
novel_downloader/tui/styles/home_layout.tcss,sha256=VNJs339qiwNUuqwwdK6VkYThCdsqlw-2mEoZVCspdrw,974
|
136
131
|
novel_downloader/tui/widgets/richlog_handler.py,sha256=bhFb0E7Z7-dRS07y_vMjxjPeCic9AD59MFPLhef_R5g,572
|
137
132
|
novel_downloader/utils/__init__.py,sha256=4iUXNUzxeAnGmpGWsB4K_jckUYEW0u_LqWp_OM7mtK8,78
|
138
133
|
novel_downloader/utils/cache.py,sha256=_jVEWAaMGY86kWVnAuuIvJA_hA8dH2ClI7o3p99mEvE,618
|
139
134
|
novel_downloader/utils/chapter_storage.py,sha256=wXXIzNjs1GfPPoqgYYPnQ9Two23McW6ZZNDmhfSC9aY,9831
|
140
|
-
novel_downloader/utils/constants.py,sha256=
|
135
|
+
novel_downloader/utils/constants.py,sha256=EaxQllQ_dIce5_eRTgAJ-OXRtEk3cMhLUbOKA359198,4435
|
141
136
|
novel_downloader/utils/cookies.py,sha256=WuPBt_z7cF4n7QPIw1julATWt6dbDRCbNdgXHSikmjo,2042
|
142
137
|
novel_downloader/utils/crypto_utils.py,sha256=BRlVR9Nvbu8TQXocJb3po1-kD5HkbCV0yyT84nq_XtI,2052
|
143
138
|
novel_downloader/utils/hash_store.py,sha256=HfzthzcKbHbVaHNpqjaAs2wDeq7iIeY8Mzkt_4v80jQ,9388
|
144
139
|
novel_downloader/utils/hash_utils.py,sha256=7eC7WsO_kl25OnRYWzIXbCXsewxvCcvRCzetsf-wbTo,3023
|
145
140
|
novel_downloader/utils/i18n.py,sha256=pdAcSIA5Tp-uPEBwNByHL7C1NayTnpOsl7zFv9p2G1k,1033
|
146
141
|
novel_downloader/utils/logger.py,sha256=9h1iFS8_auiquNgOBd-Q2pbbcnAhAKL39yf3PKadu00,3339
|
147
|
-
novel_downloader/utils/model_loader.py,sha256=JKgRFrr4HlAW9zuDUBAuuo_Kk_T_g9dWiU8E3zYk0vo,1996
|
148
142
|
novel_downloader/utils/network.py,sha256=W0SVr55MSUjTmMPkUvvkH10SRgFx3GWrCN_fDavfk4A,9143
|
149
143
|
novel_downloader/utils/state.py,sha256=FcNJ85GvBu7uEIjy0QHGr4sXMbHPEMkCjwUKNg5EabI,5132
|
150
144
|
novel_downloader/utils/file_utils/__init__.py,sha256=zvOm2qSEmWd_mRGJceGBZb5MYMSDAlWYjS5MkVQNZgI,1159
|
@@ -152,19 +146,20 @@ novel_downloader/utils/file_utils/io.py,sha256=AZ3NUe6lifGsYt3iYyXyQ2BO41WV8j013
|
|
152
146
|
novel_downloader/utils/file_utils/normalize.py,sha256=MrsCq4FqmskKRkHRV_J0z0dmn69OerMum-9sqx2XOGM,2023
|
153
147
|
novel_downloader/utils/file_utils/sanitize.py,sha256=rE-u4vpDL10zH8FT8d9wqwWsz-7dR6PJ-LE45K8VaeE,2112
|
154
148
|
novel_downloader/utils/fontocr/__init__.py,sha256=fe-04om3xxBvFKt5BBCApXCzv-Z0K_AY7lv9IB1jEHM,543
|
155
|
-
novel_downloader/utils/fontocr/
|
156
|
-
novel_downloader/utils/fontocr/
|
157
|
-
novel_downloader/utils/
|
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
|
158
153
|
novel_downloader/utils/text_utils/chapter_formatting.py,sha256=WAAEAcI7zI_uIeARDybZfXDdMvGio3VIkANFrK8-8Os,1378
|
159
154
|
novel_downloader/utils/text_utils/diff_display.py,sha256=aUvjMcYO-1_P8ZYiYbmYbJOByKo2bWoBV_ifRuAqwb8,2528
|
160
155
|
novel_downloader/utils/text_utils/font_mapping.py,sha256=Aos5skBhowDdPgnYmK0bpLtNm2hZg3RolNlTkxC9kO8,865
|
161
|
-
novel_downloader/utils/text_utils/text_cleaning.py,sha256=
|
156
|
+
novel_downloader/utils/text_utils/text_cleaning.py,sha256=zufXt0pc0vnUwgSHD_8LAef3ffqmX9rJ11YzW4rgwLA,2940
|
162
157
|
novel_downloader/utils/time_utils/__init__.py,sha256=725vY2PvqFhjbAz0hCOuIuhSCK8HrEqQ_k3YwvubmXo,624
|
163
158
|
novel_downloader/utils/time_utils/datetime_utils.py,sha256=1eyX8lTEqkQ-rEej_GrhbUpaIR5tsFdVSKT-q8s9X-g,4927
|
164
159
|
novel_downloader/utils/time_utils/sleep_utils.py,sha256=C4XYeAtxoVZC9Ju6vhhP9sbOrSpdZG2Nm-x1IYO_OFA,3233
|
165
|
-
novel_downloader-1.4.
|
166
|
-
novel_downloader-1.4.
|
167
|
-
novel_downloader-1.4.
|
168
|
-
novel_downloader-1.4.
|
169
|
-
novel_downloader-1.4.
|
170
|
-
novel_downloader-1.4.
|
160
|
+
novel_downloader-1.4.3.dist-info/licenses/LICENSE,sha256=XgmnH0mBf-qEiizoVAfJQAKzPB9y3rBa-ni7M0Aqv4A,1066
|
161
|
+
novel_downloader-1.4.3.dist-info/METADATA,sha256=MiScyRXyeXncWbjtBIZsFDJqGfL925DraPy7v6TvakQ,7253
|
162
|
+
novel_downloader-1.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
163
|
+
novel_downloader-1.4.3.dist-info/entry_points.txt,sha256=u1Ns5xI_QJyL4HAFCgJvJdib9ugu7M9I2tnQwZjJxrk,112
|
164
|
+
novel_downloader-1.4.3.dist-info/top_level.txt,sha256=hP4jYWM2LTm1jxsW4hqEB8N0dsRvldO2QdhggJT917I,17
|
165
|
+
novel_downloader-1.4.3.dist-info/RECORD,,
|
@@ -1,40 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.exporters.epub_utils
|
4
|
-
------------------------------------------
|
5
|
-
|
6
|
-
This package provides utility functions for constructing EPUB files,
|
7
|
-
including:
|
8
|
-
|
9
|
-
- CSS inclusion (css_builder)
|
10
|
-
- Image embedding (image_loader)
|
11
|
-
- EPUB book initialization (initializer)
|
12
|
-
- Chapter text-to-HTML conversion (text_to_html)
|
13
|
-
- Volume intro HTML generation (volume_intro)
|
14
|
-
"""
|
15
|
-
|
16
|
-
from .css_builder import create_css_items
|
17
|
-
from .image_loader import (
|
18
|
-
add_images_from_dir,
|
19
|
-
add_images_from_dirs,
|
20
|
-
add_images_from_list,
|
21
|
-
)
|
22
|
-
from .initializer import init_epub
|
23
|
-
from .text_to_html import (
|
24
|
-
chapter_txt_to_html,
|
25
|
-
generate_book_intro_html,
|
26
|
-
inline_remote_images,
|
27
|
-
)
|
28
|
-
from .volume_intro import create_volume_intro
|
29
|
-
|
30
|
-
__all__ = [
|
31
|
-
"create_css_items",
|
32
|
-
"add_images_from_dir",
|
33
|
-
"add_images_from_dirs",
|
34
|
-
"add_images_from_list",
|
35
|
-
"init_epub",
|
36
|
-
"chapter_txt_to_html",
|
37
|
-
"create_volume_intro",
|
38
|
-
"generate_book_intro_html",
|
39
|
-
"inline_remote_images",
|
40
|
-
]
|
@@ -1,75 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.exporters.epub_utils.css_builder
|
4
|
-
------------------------------------------------------
|
5
|
-
|
6
|
-
Reads local CSS files and wraps them into epub.EpubItem objects,
|
7
|
-
returning a list ready to be added to the EPUB.
|
8
|
-
"""
|
9
|
-
|
10
|
-
import logging
|
11
|
-
from importlib.abc import Traversable
|
12
|
-
from typing import TypedDict
|
13
|
-
|
14
|
-
from ebooklib import epub
|
15
|
-
|
16
|
-
from novel_downloader.utils.constants import (
|
17
|
-
CSS_MAIN_PATH,
|
18
|
-
CSS_VOLUME_INTRO_PATH,
|
19
|
-
)
|
20
|
-
|
21
|
-
logger = logging.getLogger(__name__)
|
22
|
-
|
23
|
-
|
24
|
-
class CssConfig(TypedDict):
|
25
|
-
include: bool
|
26
|
-
path: Traversable
|
27
|
-
uid: str
|
28
|
-
file_name: str
|
29
|
-
|
30
|
-
|
31
|
-
def create_css_items(
|
32
|
-
include_main: bool = True,
|
33
|
-
include_volume: bool = True,
|
34
|
-
) -> list[epub.EpubItem]:
|
35
|
-
"""
|
36
|
-
:param include_main: Whether to load the main stylesheet.
|
37
|
-
:param include_volume: Whether to load the “volume intro” stylesheet.
|
38
|
-
:returns: A list of epub.EpubItem ready to add to the book.
|
39
|
-
"""
|
40
|
-
css_config: list[CssConfig] = [
|
41
|
-
{
|
42
|
-
"include": include_main,
|
43
|
-
"path": CSS_MAIN_PATH,
|
44
|
-
"uid": "style",
|
45
|
-
"file_name": "Styles/main.css",
|
46
|
-
},
|
47
|
-
{
|
48
|
-
"include": include_volume,
|
49
|
-
"path": CSS_VOLUME_INTRO_PATH,
|
50
|
-
"uid": "volume_style",
|
51
|
-
"file_name": "Styles/volume-intro.css",
|
52
|
-
},
|
53
|
-
]
|
54
|
-
css_items: list[epub.EpubItem] = []
|
55
|
-
|
56
|
-
for css in css_config:
|
57
|
-
if css["include"]:
|
58
|
-
path = css["path"]
|
59
|
-
try:
|
60
|
-
content: str = path.read_text(encoding="utf-8")
|
61
|
-
content_bytes: bytes = content.encode("utf-8")
|
62
|
-
css_items.append(
|
63
|
-
epub.EpubItem(
|
64
|
-
uid=css["uid"],
|
65
|
-
file_name=css["file_name"],
|
66
|
-
media_type="text/css",
|
67
|
-
content=content_bytes,
|
68
|
-
)
|
69
|
-
)
|
70
|
-
except FileNotFoundError:
|
71
|
-
logger.info(f"[epub] CSS 文件不存在: {css['path']}")
|
72
|
-
except UnicodeDecodeError:
|
73
|
-
logger.info(f"[epub] 无法解码文件: {css['path']}")
|
74
|
-
|
75
|
-
return css_items
|
@@ -1,131 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.exporters.epub_utils.image_loader
|
4
|
-
-------------------------------------------------------
|
5
|
-
|
6
|
-
Utilities for embedding image files into an EpubBook.
|
7
|
-
"""
|
8
|
-
|
9
|
-
import logging
|
10
|
-
from collections.abc import Iterable, Sequence
|
11
|
-
from pathlib import Path
|
12
|
-
|
13
|
-
from ebooklib import epub
|
14
|
-
|
15
|
-
from novel_downloader.utils.constants import EPUB_IMAGE_FOLDER
|
16
|
-
|
17
|
-
logger = logging.getLogger(__name__)
|
18
|
-
|
19
|
-
_SUPPORTED_IMAGE_MEDIA_TYPES: dict[str, str] = {
|
20
|
-
"png": "image/png",
|
21
|
-
"jpg": "image/jpeg",
|
22
|
-
"jpeg": "image/jpeg",
|
23
|
-
"gif": "image/gif",
|
24
|
-
"svg": "image/svg+xml",
|
25
|
-
"webp": "image/webp",
|
26
|
-
}
|
27
|
-
_DEFAULT_IMAGE_MEDIA_TYPE = "image/jpeg"
|
28
|
-
|
29
|
-
|
30
|
-
def add_images_from_list(
|
31
|
-
book: epub.EpubBook,
|
32
|
-
image_list: Sequence[str | Path],
|
33
|
-
) -> epub.EpubBook:
|
34
|
-
"""
|
35
|
-
Add a list of image files to the EPUB's image folder.
|
36
|
-
|
37
|
-
:param book: The EpubBook object to modify.
|
38
|
-
:param image_list: List of paths to image files.
|
39
|
-
:return: The same EpubBook instance, with images added.
|
40
|
-
"""
|
41
|
-
for img_path in image_list:
|
42
|
-
img_path = Path(img_path)
|
43
|
-
if not img_path.is_file():
|
44
|
-
continue
|
45
|
-
|
46
|
-
suffix = img_path.suffix.lower().lstrip(".")
|
47
|
-
media_type = _SUPPORTED_IMAGE_MEDIA_TYPES.get(suffix)
|
48
|
-
if media_type is None:
|
49
|
-
media_type = _DEFAULT_IMAGE_MEDIA_TYPE
|
50
|
-
logger.warning(
|
51
|
-
"Unknown image suffix '%s' - defaulting media_type to %s",
|
52
|
-
suffix,
|
53
|
-
media_type,
|
54
|
-
)
|
55
|
-
|
56
|
-
try:
|
57
|
-
content = img_path.read_bytes()
|
58
|
-
item = epub.EpubItem(
|
59
|
-
uid=f"img_{img_path.stem}",
|
60
|
-
file_name=f"{EPUB_IMAGE_FOLDER}/{img_path.name}",
|
61
|
-
media_type=media_type,
|
62
|
-
content=content,
|
63
|
-
)
|
64
|
-
book.add_item(item)
|
65
|
-
logger.debug("Embedded image: %s", img_path.name)
|
66
|
-
except Exception:
|
67
|
-
logger.exception("Failed to embed image %s", img_path)
|
68
|
-
|
69
|
-
return book
|
70
|
-
|
71
|
-
|
72
|
-
def add_images_from_dir(
|
73
|
-
book: epub.EpubBook,
|
74
|
-
image_dir: str | Path,
|
75
|
-
) -> epub.EpubBook:
|
76
|
-
"""
|
77
|
-
Load every file in `image_dir` into the EPUB's image folder.
|
78
|
-
|
79
|
-
:param book: The EpubBook object to modify.
|
80
|
-
:param image_dir: Path to the directory containing image files.
|
81
|
-
:return: The same EpubBook instance, with images added.
|
82
|
-
"""
|
83
|
-
image_dir = Path(image_dir)
|
84
|
-
if not image_dir.is_dir():
|
85
|
-
logger.warning("Image directory not found or not a directory: %s", image_dir)
|
86
|
-
return book
|
87
|
-
|
88
|
-
for img_path in image_dir.iterdir():
|
89
|
-
if not img_path.is_file():
|
90
|
-
continue
|
91
|
-
|
92
|
-
suffix = img_path.suffix.lower().lstrip(".")
|
93
|
-
media_type = _SUPPORTED_IMAGE_MEDIA_TYPES.get(suffix)
|
94
|
-
if media_type is None:
|
95
|
-
media_type = _DEFAULT_IMAGE_MEDIA_TYPE
|
96
|
-
logger.warning(
|
97
|
-
"Unknown image suffix '%s' - defaulting media_type to %s",
|
98
|
-
suffix,
|
99
|
-
media_type,
|
100
|
-
)
|
101
|
-
|
102
|
-
try:
|
103
|
-
content = img_path.read_bytes()
|
104
|
-
item = epub.EpubItem(
|
105
|
-
uid=f"img_{img_path.stem}",
|
106
|
-
file_name=f"{EPUB_IMAGE_FOLDER}/{img_path.name}",
|
107
|
-
media_type=media_type,
|
108
|
-
content=content,
|
109
|
-
)
|
110
|
-
book.add_item(item)
|
111
|
-
logger.debug("Embedded image: %s", img_path.name)
|
112
|
-
except Exception:
|
113
|
-
logger.exception("Failed to embed image %s", img_path)
|
114
|
-
|
115
|
-
return book
|
116
|
-
|
117
|
-
|
118
|
-
def add_images_from_dirs(
|
119
|
-
book: epub.EpubBook,
|
120
|
-
image_dirs: Iterable[str | Path],
|
121
|
-
) -> epub.EpubBook:
|
122
|
-
"""
|
123
|
-
Add all images from multiple directories into the given EpubBook.
|
124
|
-
|
125
|
-
:param book: The EpubBook object to modify.
|
126
|
-
:param image_dirs: An iterable of directory paths to scan for images.
|
127
|
-
:return: The same EpubBook instance, with all images added.
|
128
|
-
"""
|
129
|
-
for img_dir in image_dirs:
|
130
|
-
book = add_images_from_dir(book, img_dir)
|
131
|
-
return book
|
@@ -1,100 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.exporters.epub_utils.initializer
|
4
|
-
------------------------------------------------------
|
5
|
-
|
6
|
-
Initializes an epub.EpubBook object, sets metadata
|
7
|
-
(identifier, title, author, language, description),
|
8
|
-
adds a cover, and prepares the initial spine and TOC entries.
|
9
|
-
"""
|
10
|
-
|
11
|
-
import logging
|
12
|
-
from pathlib import Path
|
13
|
-
from typing import Any
|
14
|
-
|
15
|
-
from ebooklib import epub
|
16
|
-
|
17
|
-
from novel_downloader.utils.constants import (
|
18
|
-
EPUB_IMAGE_FOLDER,
|
19
|
-
EPUB_TEXT_FOLDER,
|
20
|
-
VOLUME_BORDER_IMAGE_PATH,
|
21
|
-
)
|
22
|
-
|
23
|
-
logger = logging.getLogger(__name__)
|
24
|
-
|
25
|
-
|
26
|
-
def init_epub(
|
27
|
-
book_info: dict[str, Any],
|
28
|
-
book_id: str,
|
29
|
-
intro_html: str,
|
30
|
-
book_cover_path: Path | None = None,
|
31
|
-
include_toc: bool = False,
|
32
|
-
) -> tuple[epub.EpubBook, list[Any], list[Any]]:
|
33
|
-
"""
|
34
|
-
Initialize an EPUB book with metadata, optional cover, and intro page.
|
35
|
-
|
36
|
-
:param book_info: Dict with keys 'book_name', 'author', 'summary'.
|
37
|
-
:param book_id: Book identifier (numeric or string).
|
38
|
-
:param intro_html: Intro content in XHTML format.
|
39
|
-
:param book_cover_path: Optional Path to the cover image file.
|
40
|
-
:param include_toc: Whether to include the <nav> item in the spine.
|
41
|
-
:return: (book, spine, toc_list)
|
42
|
-
"""
|
43
|
-
book = epub.EpubBook()
|
44
|
-
book.set_identifier(str(book_id))
|
45
|
-
book_name = book_info.get("book_name") or book_info.get("volume_name", "未找到书名")
|
46
|
-
book.set_title(book_name)
|
47
|
-
book.set_language("zh-CN")
|
48
|
-
book.add_author(book_info.get("author", "未找到作者"))
|
49
|
-
desc = book_info.get("summary") or book_info.get("volume_intro", "未找到作品简介")
|
50
|
-
book.add_metadata("DC", "description", desc)
|
51
|
-
|
52
|
-
spine = []
|
53
|
-
|
54
|
-
# cover
|
55
|
-
if book_cover_path:
|
56
|
-
try:
|
57
|
-
cover_bytes = book_cover_path.read_bytes()
|
58
|
-
ext = book_cover_path.suffix.lower()
|
59
|
-
ext = ext if ext in [".jpg", ".jpeg", ".png"] else ".jpeg"
|
60
|
-
filename = f"{EPUB_IMAGE_FOLDER}/cover{ext}"
|
61
|
-
book.set_cover(filename, cover_bytes)
|
62
|
-
spine.append("cover")
|
63
|
-
except FileNotFoundError:
|
64
|
-
logger.info(f"[epub] 封面图片不存在: {book_cover_path}")
|
65
|
-
except Exception as e:
|
66
|
-
logger.info(f"[epub] 读取封面失败: {book_cover_path},错误:{e}")
|
67
|
-
|
68
|
-
# 导航菜单
|
69
|
-
if include_toc:
|
70
|
-
spine.append("nav")
|
71
|
-
|
72
|
-
# 简介页面
|
73
|
-
intro = epub.EpubHtml(
|
74
|
-
title="书籍简介",
|
75
|
-
file_name=f"{EPUB_TEXT_FOLDER}/intro.xhtml",
|
76
|
-
lang="zh-CN",
|
77
|
-
uid="intro",
|
78
|
-
)
|
79
|
-
intro.content = intro_html
|
80
|
-
intro.add_link(href="../Styles/main.css", rel="stylesheet", type="text/css")
|
81
|
-
book.add_item(intro)
|
82
|
-
spine.append(intro)
|
83
|
-
|
84
|
-
# 添加卷边框图像 (volume_border.png)
|
85
|
-
try:
|
86
|
-
border_bytes = VOLUME_BORDER_IMAGE_PATH.read_bytes()
|
87
|
-
border_item = epub.EpubItem(
|
88
|
-
uid="volume-border",
|
89
|
-
file_name=f"{EPUB_IMAGE_FOLDER}/volume_border.png",
|
90
|
-
media_type="image/png",
|
91
|
-
content=border_bytes,
|
92
|
-
)
|
93
|
-
book.add_item(border_item)
|
94
|
-
except FileNotFoundError:
|
95
|
-
logger.info(f"[epub] 卷边框图片不存在: {VOLUME_BORDER_IMAGE_PATH}")
|
96
|
-
except Exception as e:
|
97
|
-
logger.info(f"[epub] 读取卷边框失败: {VOLUME_BORDER_IMAGE_PATH}: {e}")
|
98
|
-
|
99
|
-
toc_list = [epub.Link(intro.file_name, "书籍简介", intro.id)]
|
100
|
-
return book, spine, toc_list
|