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
@@ -0,0 +1,164 @@
|
|
1
|
+
novel_downloader/__init__.py,sha256=SIm_swXHzLDHFQcQUzFPB-cv_f_HLvvthF5sfTlkNG4,218
|
2
|
+
novel_downloader/cli/__init__.py,sha256=QMtpA-QIdW1VAaEYIVGkuLFp0yRpacbttiLz02QsBAM,174
|
3
|
+
novel_downloader/cli/clean.py,sha256=hOk8SJQwBCw2oOObTdEI79wpnmZ25uB1s9LQK1-4LNU,4487
|
4
|
+
novel_downloader/cli/config.py,sha256=S1c-76mqIc9UEtASuSqsChmvvv-btnphmhOf43TVIZ4,3262
|
5
|
+
novel_downloader/cli/download.py,sha256=0fX3dZE-163i0q8lBLkz0QUBLRkl9AfWnuGOmCFrXfs,6791
|
6
|
+
novel_downloader/cli/export.py,sha256=Mm3CPva_gE4KSUfuetFBbCB6E8prE4kHHj9UqPCBFas,2410
|
7
|
+
novel_downloader/cli/main.py,sha256=fipNkrT1Vj8owroOcadwarA81eMRSnCs1rhB6Ypt_9c,1009
|
8
|
+
novel_downloader/cli/search.py,sha256=Iw59yZwGugKq9lZgxEkKoEnOA1IPgCOCqmdaqoxhtVE,3405
|
9
|
+
novel_downloader/config/__init__.py,sha256=qgOTCPNGmmnMRU0kn9w-ZPFf_dmyfKRZabxb49GUaag,475
|
10
|
+
novel_downloader/config/adapter.py,sha256=HwLKxFd-dle2uN0HPyzNmqiGyBGQ0uZs2-jwU1PTwvk,13456
|
11
|
+
novel_downloader/config/loader.py,sha256=bzZVwwDKwHMjtsQKKXhlOiiI0PG5t1UKKr4Ddkm-fjk,5742
|
12
|
+
novel_downloader/core/__init__.py,sha256=bx_UGagwvQxGOuXr1ewBDmoPfOZFTV5G9zi0HkYAuwg,1079
|
13
|
+
novel_downloader/core/downloaders/__init__.py,sha256=FG-HqP0067APoOk5eqwCgAyFyA_nKAfkqQDcd_IMdmE,1038
|
14
|
+
novel_downloader/core/downloaders/base.py,sha256=xAQTaaPR8jcGrD8bwo_Ezkwr5-UTVNLKpS3XCNiNXXU,10839
|
15
|
+
novel_downloader/core/downloaders/biquge.py,sha256=-1TR0MS8VvX4UcJ9U4_oSmxtVN-XBtWbV_gAaS_EBfM,759
|
16
|
+
novel_downloader/core/downloaders/common.py,sha256=jm93XTSRFL89kOMWkzDGFJpHklNQcVhw_7Q3n5BuFg0,7468
|
17
|
+
novel_downloader/core/downloaders/esjzone.py,sha256=5DFwXEQUHHSR1fTF8gY9zvuWLXIQqKPvPopuSQa_jQg,747
|
18
|
+
novel_downloader/core/downloaders/linovelib.py,sha256=xQFy1WZ4f1lSVMD5jFvTV5MexVksS5TUPsEH5rSdXbY,776
|
19
|
+
novel_downloader/core/downloaders/qianbi.py,sha256=IeetEHnSj5XVPWC5oFYJCfzx8a6QHXD36ko-JzZTGyQ,10338
|
20
|
+
novel_downloader/core/downloaders/qidian.py,sha256=UOzO_RQhMVlROTd_P8q5g6IZ-COqcxwWHdu5a7rwTyY,9784
|
21
|
+
novel_downloader/core/downloaders/registry.py,sha256=CUc7SVdk9dfT34B4ggtNH39Pmk2CknWXPHxlnwnT2cQ,1742
|
22
|
+
novel_downloader/core/downloaders/sfacg.py,sha256=QX6eGhBoLSG1-Xlp-Tk6V4cC8jO-eX0CuDLXdKN6gKM,749
|
23
|
+
novel_downloader/core/downloaders/yamibo.py,sha256=s69T5sE8Un2NsZ0mhRJhVs7nWFTrVm85MbqQBsmSHEI,752
|
24
|
+
novel_downloader/core/exporters/__init__.py,sha256=lpoRD5nnMLWBfy--0MaU2AFgJR4znC3NFb_YtkJ7qv0,841
|
25
|
+
novel_downloader/core/exporters/base.py,sha256=HEpSkOo9Uxz5rzicQ3UIk697TRrgj3ZBpO9_E3V2mgM,8742
|
26
|
+
novel_downloader/core/exporters/biquge.py,sha256=nEurX2XcwlnMj1GudDea-1Aqk1PTXSX1AzRycVBUqbY,506
|
27
|
+
novel_downloader/core/exporters/epub_util.py,sha256=hN4BixHcAB9SnLkLN-6nnqr3r5CKvwMhI1Ensblfltg,5167
|
28
|
+
novel_downloader/core/exporters/esjzone.py,sha256=WSUkDfsLZ2EaBMI-TtFBuC0bFxvpvZJO6ZokclGcoQU,505
|
29
|
+
novel_downloader/core/exporters/qianbi.py,sha256=ceq4S87UrvZDaFcOl6glO6IJuVcCR3hsbQCtyfa55Zc,499
|
30
|
+
novel_downloader/core/exporters/qidian.py,sha256=GvpY5JlGQbC9r1DJlBwFD3hrTjIjQcaO9BmF88g5ATQ,983
|
31
|
+
novel_downloader/core/exporters/registry.py,sha256=9McaEeGZa7Adjk9qafNQA6_QaPFRQGEFrgvYqtDGMoY,1431
|
32
|
+
novel_downloader/core/exporters/sfacg.py,sha256=hJq3yy0zHn08q8NbCc1fLZOWuzjongth-wBp0nqcx2Q,493
|
33
|
+
novel_downloader/core/exporters/txt_util.py,sha256=LrffCEB8Qnbe6Db6IIUfs3erfwzMgCNCsWFFboWTxBA,1985
|
34
|
+
novel_downloader/core/exporters/yamibo.py,sha256=V9U7cHbWykM45Py0lU2MMKDwWqwO-BdHZE_yrLt9Rlw,499
|
35
|
+
novel_downloader/core/exporters/common/__init__.py,sha256=qublXdulyhYQOZFE-rjDicS-3-dDWBgl4iYy8pj_NPg,274
|
36
|
+
novel_downloader/core/exporters/common/epub.py,sha256=1hANj0h004eTb1dpH0ZPCpVmEzwmsAJAXVINjoNa6_M,5781
|
37
|
+
novel_downloader/core/exporters/common/main_exporter.py,sha256=skkl-ClFXVzIGqdtQxuH78O0KZvXL4YKRP5Z_KCMJEg,2105
|
38
|
+
novel_downloader/core/exporters/common/txt.py,sha256=aGB1xL9zWfqV2mlaSgAMcxB3JRdAq2Y4Dxf-ElxX4xQ,4709
|
39
|
+
novel_downloader/core/exporters/linovelib/__init__.py,sha256=PgmtYx6t8YpPl5Dhqq7lgkqz5btyj_XUrOjnJOfSQLU,195
|
40
|
+
novel_downloader/core/exporters/linovelib/epub.py,sha256=xCKwSEgZciIVgXzZgdP1YzRM4QYzVEkkIAvAF3CWydE,10615
|
41
|
+
novel_downloader/core/exporters/linovelib/main_exporter.py,sha256=2IlnxgH64v9CrU6GsBTPHJ1oYXBTxCOZKSLzBm1VD-w,2050
|
42
|
+
novel_downloader/core/exporters/linovelib/txt.py,sha256=TWAQ5ZCDgBqrKktivEgDmuEZEgmi5ogG4i-a0zDXfHQ,4343
|
43
|
+
novel_downloader/core/fetchers/__init__.py,sha256=iHWGP1IHWIe7RutcSVl_cQM7bxmC6skeEvOJU5ck_yM,1365
|
44
|
+
novel_downloader/core/fetchers/registry.py,sha256=3tCP1Ubcbm6BBYbi3PPO0A1l75DXpk64z7OZ159Loo4,1915
|
45
|
+
novel_downloader/core/fetchers/base/__init__.py,sha256=URfwFQG16FkRkYSgoyf9t-enoM2j_aEZgAHkOIKPgRY,224
|
46
|
+
novel_downloader/core/fetchers/base/browser.py,sha256=mUbpoAiss5XLX4k9YK9YAMAWtxy2_ZCCnnJpm9LrW0Q,12398
|
47
|
+
novel_downloader/core/fetchers/base/rate_limiter.py,sha256=zUYH_PjnKfUzJpcbUPtMkwXxIlF0SH-ZTFlbCUrq060,2724
|
48
|
+
novel_downloader/core/fetchers/base/session.py,sha256=igtIzGYgxRwcQC4SJD5y6Xt1xV_VUF2YqsYc4AV9Mo4,13957
|
49
|
+
novel_downloader/core/fetchers/biquge/__init__.py,sha256=HtTYA5ftmdG8ss23C0aVd9XpMXPUw9jYyHVWcitqdWA,236
|
50
|
+
novel_downloader/core/fetchers/biquge/browser.py,sha256=zt1_ZjSdzcTpPVQKCxym-zN5G6nkQiBxsgG9ILxEd3M,2539
|
51
|
+
novel_downloader/core/fetchers/biquge/session.py,sha256=5JpxTbVRKENtKk5tbmq8uWqudriNGKxePjzAefXNvgk,2565
|
52
|
+
novel_downloader/core/fetchers/esjzone/__init__.py,sha256=p9oILNGkK_4OlPKeN64aRHh9yuNJO3JUzQ2H9qGfhXg,242
|
53
|
+
novel_downloader/core/fetchers/esjzone/browser.py,sha256=2RSHnG90eWATo0Y_PQj0bchD8zmYLvtIIqXzaTz1qW8,6421
|
54
|
+
novel_downloader/core/fetchers/esjzone/session.py,sha256=P-z-sonyvubO8SZqCl9ImruxjE_yRdZg4BJ9azm9dPU,7350
|
55
|
+
novel_downloader/core/fetchers/linovelib/__init__.py,sha256=DdnfWgy_6XW1iaI1d5BBNwX8bizrmF-Vj3LrGy6q41c,254
|
56
|
+
novel_downloader/core/fetchers/linovelib/browser.py,sha256=JsUbfpMHiFEeF5Cl268l6nL9jUpqJH78t0kQ2INJJ8E,6220
|
57
|
+
novel_downloader/core/fetchers/linovelib/session.py,sha256=y3ISDrFPJy7O9tZYP09ctw0JlfzsJEe6NMPRgbnTsoc,6230
|
58
|
+
novel_downloader/core/fetchers/qianbi/__init__.py,sha256=bu2lH43Lclku6Fm60q8p9j3f5eijyyXmTKUxcO-82U0,236
|
59
|
+
novel_downloader/core/fetchers/qianbi/browser.py,sha256=HsW6DY2fAJDG1V6h6owlLP-GmGR--iu_UTHWSo6OIi4,3304
|
60
|
+
novel_downloader/core/fetchers/qianbi/session.py,sha256=B85N21hrtn1DWErumLAN3IJNzRKFT-8dgVCNE3Mr2f8,3283
|
61
|
+
novel_downloader/core/fetchers/qidian/__init__.py,sha256=C4mfhryEleBO8D9eMJW_WVS9-7wg_9-eME0SQCezoBk,236
|
62
|
+
novel_downloader/core/fetchers/qidian/browser.py,sha256=qu3JBSBWS9VLWbz-LXHHksrZ7idIv2Gik9DeHPLlaus,10726
|
63
|
+
novel_downloader/core/fetchers/qidian/session.py,sha256=rSMwS8Ds2RiKySoyR8CUXMrlZrzFOLUSmTyMcNIK8Rg,9966
|
64
|
+
novel_downloader/core/fetchers/sfacg/__init__.py,sha256=aRvY8SFPhr3Kg5EX2MeXoMZh9oNomD4fqzIo1PK-mwc,230
|
65
|
+
novel_downloader/core/fetchers/sfacg/browser.py,sha256=U-ASxhiwNuDygNwBvwFcfA9hQweeReOmc8hjouUcLjE,5822
|
66
|
+
novel_downloader/core/fetchers/sfacg/session.py,sha256=rmFocT_g6Co0jrM2TDXIMIkuF6gSADTfXNdmu7Lb1eg,5226
|
67
|
+
novel_downloader/core/fetchers/yamibo/__init__.py,sha256=0_9xSGNEEYVgVM6A9ZQpSIrcjmuSGQI_XMg4EmP9dvI,236
|
68
|
+
novel_downloader/core/fetchers/yamibo/browser.py,sha256=0nirnzAZZxt77gW4fQ5oUoCziALigbZaCwuMbEPQ_RI,7407
|
69
|
+
novel_downloader/core/fetchers/yamibo/session.py,sha256=qmrHZ4h8IeeqobfJPIpNDNkIw3tzSmjlklcparoQ6ys,7343
|
70
|
+
novel_downloader/core/interfaces/__init__.py,sha256=BS-0upPeUmJofNnhP-eiYiYT2IGnfBQDUILqXqbomfc,665
|
71
|
+
novel_downloader/core/interfaces/downloader.py,sha256=H0S4o5MW22JcvNVECv1bCdwAN0drBwHY31IbvVHn-X0,1557
|
72
|
+
novel_downloader/core/interfaces/exporter.py,sha256=zwIaJ5FXo_JmKYg2UZV9FTWX7xZ2e0QuL4RTNGRtI04,1610
|
73
|
+
novel_downloader/core/interfaces/fetcher.py,sha256=XlP3d-Q_xvuVextZCdLOxDf8BwBbx799L_WLJx0WTB8,4096
|
74
|
+
novel_downloader/core/interfaces/parser.py,sha256=iZeUgNl-zE-wsf1eW4GVCPjEaLSvQrNJi_mVEOU9ulY,1353
|
75
|
+
novel_downloader/core/interfaces/searcher.py,sha256=KUgkyDndFDVd65aSA2S8Y_FLmtla5DRX3eSQ5Ebxi5E,363
|
76
|
+
novel_downloader/core/parsers/__init__.py,sha256=XrIsgXFKaHdiggC6Pn5tWsh8Wo5syQJDWfJLkW-qcjY,806
|
77
|
+
novel_downloader/core/parsers/base.py,sha256=GifJANFm0auYyzYuqYox9LFgDskW8G2vR0DaMrRcG1w,2962
|
78
|
+
novel_downloader/core/parsers/biquge.py,sha256=HfZfLhvGmY7WATXuwN5MjMKadpLh7d5FvBUwc5D5slc,4705
|
79
|
+
novel_downloader/core/parsers/esjzone.py,sha256=UbhbH_ZdMriBjw97esdUgUI2Mj5kaJl85euSWU4GE5U,8647
|
80
|
+
novel_downloader/core/parsers/linovelib.py,sha256=tDKS097ybcGS9BgjOmKoVNv2bfHsGzVRpJvkevOYZNo,7694
|
81
|
+
novel_downloader/core/parsers/qianbi.py,sha256=kSnDgC-jCJmg4pWTXcFHbaucLxrgw0ZXI04pohU7J3Q,5195
|
82
|
+
novel_downloader/core/parsers/registry.py,sha256=wpdEp2I881BlO2V6KcpoO8TdFDqoe8o1ppY7tiu2nDY,1869
|
83
|
+
novel_downloader/core/parsers/sfacg.py,sha256=kHsfMgl78IUX70KQGSQrpIVdU6LdlZeHICRupb6QFc4,6024
|
84
|
+
novel_downloader/core/parsers/yamibo.py,sha256=JcSJcZyiCfXq1blGTCuoIoWhOpTYOUH9T34Z-1ZCA9s,6680
|
85
|
+
novel_downloader/core/parsers/qidian/__init__.py,sha256=ScY9penE8b1m5HZGu6C1XwbzuqKbeGVCvli0J-xzzKs,173
|
86
|
+
novel_downloader/core/parsers/qidian/book_info_parser.py,sha256=TbP8nghoxzBi435cSJKAzWttBRUq49MHw6kn0klfZrU,3056
|
87
|
+
novel_downloader/core/parsers/qidian/chapter_encrypted.py,sha256=zdZArGNGADXiwhikSyp3UZ7RLNOAaobldZuTzMWTjL4,18494
|
88
|
+
novel_downloader/core/parsers/qidian/chapter_normal.py,sha256=Hq8PuUsa8d-GB5VYvsi3Rpymut9dOJ_MQKzWkENBXwE,4727
|
89
|
+
novel_downloader/core/parsers/qidian/chapter_router.py,sha256=foVMlWtE-qUOvJD_4EDiuAVaNkFdeV_ZTCvS5IL7Orc,1957
|
90
|
+
novel_downloader/core/parsers/qidian/main_parser.py,sha256=lwzcrhiQCd9SRBQnKHilce1BSmkvfzP3HHZNgPX1swY,3928
|
91
|
+
novel_downloader/core/parsers/qidian/utils/__init__.py,sha256=aYjFuY2ovAMdrHVZ-6o7GQNJq6SmwFEppx0n801B02A,588
|
92
|
+
novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py,sha256=LJecMdwWlO9Z2Z8nk4f2QF3-rEWVv6sJoX2YRq_O11c,4686
|
93
|
+
novel_downloader/core/parsers/qidian/utils/helpers.py,sha256=v64zTDQ6qbKnGXM7MPzCsS7yQ-w730vPVrDD19Bgx4Q,3514
|
94
|
+
novel_downloader/core/parsers/qidian/utils/node_decryptor.py,sha256=MQQUI9nNpM23K0sA9bRVhs7pbQX6OvMc1NgvM28gHsU,5949
|
95
|
+
novel_downloader/core/searchers/__init__.py,sha256=6CgH2VRUUCRnnhVSXKuih8bwL5inytRFuihTJQhtWok,386
|
96
|
+
novel_downloader/core/searchers/base.py,sha256=05RsKGvTCdMr-D1xzD17VAcNxYrA2LI2EmAxOo7u7Dg,2544
|
97
|
+
novel_downloader/core/searchers/biquge.py,sha256=ToudWrm9E07k5jnGZMzlzAAi9wgyiE02BxcUTExUgOM,2624
|
98
|
+
novel_downloader/core/searchers/esjzone.py,sha256=d4EJNbYYEYR1bl6uH3G2r6M185Dwbohhnkeg1T_BwMc,2740
|
99
|
+
novel_downloader/core/searchers/qianbi.py,sha256=LGX0DHdsCBj_zp79eSmxGBE0ONKb763GZ2PMQv_XKzo,4243
|
100
|
+
novel_downloader/core/searchers/qidian.py,sha256=9gEwq4ildh4fTiyqMeqxQdoLaTj4d4gmYfVzRX95eLg,2712
|
101
|
+
novel_downloader/core/searchers/registry.py,sha256=ud9vW4mV3H1-k9iK3LHT-aYAMSAClCY5SsDcq-kZkH0,1874
|
102
|
+
novel_downloader/locales/en.json,sha256=eHSK2hHXRJY8d2voMoBhYqmBmjU94wKRwm4j3CTEOEI,7458
|
103
|
+
novel_downloader/locales/zh.json,sha256=OB-VeUIdOBMfL4kZQWNl_XN_91vmimGIzYC-OLMoWgE,7252
|
104
|
+
novel_downloader/models/__init__.py,sha256=iwKxN4kAh442wPgZxKXQRig1PQthD3Az263Y60ICaik,672
|
105
|
+
novel_downloader/models/chapter.py,sha256=bdAQUDZIuuTVxoYjoOJrbS2u81b1B2mkuZkTSf0m2HQ,492
|
106
|
+
novel_downloader/models/config.py,sha256=3BFEnxlOWQztJb5tEvPEkpf6P0L5H7ib4XiWXNBAQGQ,3299
|
107
|
+
novel_downloader/models/login.py,sha256=sY2Jom6PLpA9Z3Uy7plZKhda3Gq7awKOOIIaQ79PpWs,371
|
108
|
+
novel_downloader/models/search.py,sha256=jC-ACdF4YvWw3v9E-oFyb_rgOg1T67CuubdEHXjw1_k,249
|
109
|
+
novel_downloader/models/types.py,sha256=hQI1o_xnFcO75Uh6xC9D6SsNHUapaJoEGOeEOqb8LvA,311
|
110
|
+
novel_downloader/resources/config/settings.toml,sha256=MyiZ4uGMEzb1KuAOoJV1hnwOQxGpjfzBUs17j0to_p8,5012
|
111
|
+
novel_downloader/resources/css_styles/intro.css,sha256=Nqzp-A5we92d90CCiGL8h2FeuMnCz-G0TLevMF_Pl2U,1271
|
112
|
+
novel_downloader/resources/css_styles/main.css,sha256=1nsDTr698eY3furWDHuQMDKP1Vqd2h5x40eJMZpktNE,559
|
113
|
+
novel_downloader/resources/images/volume_border.png,sha256=2dEVimnTHKOfLMhi7bhkh_5joWNnrqg8duomLSNOZx4,28613
|
114
|
+
novel_downloader/resources/js_scripts/qidian_decrypt_node.js,sha256=spNrk_gXI7pPW9abr4XGc2LASMe1UuN4BUe4cH24L8s,2195
|
115
|
+
novel_downloader/resources/json/linovelib_font_map.json,sha256=F1IlEcvXGcagnZCu4Gw2vQ2NLnhy6cJOLhabukqnftw,67854
|
116
|
+
novel_downloader/tui/__init__.py,sha256=8RB8tBrPcoBzm1tpQlgZqnOZXrdHmlzMRxuk9wsN4m0,115
|
117
|
+
novel_downloader/tui/app.py,sha256=ytV1u15nGCRj_ff_GeAL3W1XlU6r5Lh_k3HBcAjPRx0,731
|
118
|
+
novel_downloader/tui/main.py,sha256=MBP8SrwEYTpGQm-V9W_4rKnTeslneORfkzFsU3Xj2yA,256
|
119
|
+
novel_downloader/tui/screens/__init__.py,sha256=QsUM5cUEKm7nluQh9acEt37xRWbkZU3vqIpBduepDCU,203
|
120
|
+
novel_downloader/tui/screens/home.py,sha256=nH3pRuCOFcSvNV4AYC6RRkWpphmRgY1bNK36OkSVfCg,6994
|
121
|
+
novel_downloader/tui/screens/login.py,sha256=GK8dXCtH5lGu3ilT1Cv2VmFCwHMspDNpzw0logj2lz0,2225
|
122
|
+
novel_downloader/tui/styles/home_layout.tcss,sha256=VNJs339qiwNUuqwwdK6VkYThCdsqlw-2mEoZVCspdrw,974
|
123
|
+
novel_downloader/tui/widgets/richlog_handler.py,sha256=bhFb0E7Z7-dRS07y_vMjxjPeCic9AD59MFPLhef_R5g,572
|
124
|
+
novel_downloader/utils/__init__.py,sha256=cr74_8UmCYV7GOLGq-25WE1om9kWCDkWVFvklUEw4HM,1180
|
125
|
+
novel_downloader/utils/cache.py,sha256=_jVEWAaMGY86kWVnAuuIvJA_hA8dH2ClI7o3p99mEvE,618
|
126
|
+
novel_downloader/utils/chapter_storage.py,sha256=gRjNvGD9vnd86rmjvNRlZllvJv0PY3CojLeAafHNqPI,10360
|
127
|
+
novel_downloader/utils/constants.py,sha256=MVNwKBy0iw0ipA_kn8Zjih9gbvB3szDvoiKxg_u-t5w,3990
|
128
|
+
novel_downloader/utils/cookies.py,sha256=WuPBt_z7cF4n7QPIw1julATWt6dbDRCbNdgXHSikmjo,2042
|
129
|
+
novel_downloader/utils/crypto_utils.py,sha256=BRlVR9Nvbu8TQXocJb3po1-kD5HkbCV0yyT84nq_XtI,2052
|
130
|
+
novel_downloader/utils/i18n.py,sha256=86Wz4zT0_YTnmOSS6cliqO_uMgJJdfC-hNLyqZnXgvU,1050
|
131
|
+
novel_downloader/utils/logger.py,sha256=k5m7XV0Ht1nnAnUTNTHL3DQXz5iyZ02tRnmDa83r_GE,3368
|
132
|
+
novel_downloader/utils/network.py,sha256=6hK1leSOfTvw4teeSZ98eV09A5Rf2CG75UaAuEJY6RY,4677
|
133
|
+
novel_downloader/utils/state.py,sha256=jDgpZJQFgbnJiStmqGRjLzg6y9f49e5fmg4CJD2r_es,5133
|
134
|
+
novel_downloader/utils/epub/__init__.py,sha256=RRZGcGrefgQXbbLkPCtn3FklbkXxyhnh60R5a--XlcY,718
|
135
|
+
novel_downloader/utils/epub/builder.py,sha256=apuzG7UzYcEEreMpf9Dez06-laQQg6EGGvl3PQGpBFA,11664
|
136
|
+
novel_downloader/utils/epub/constants.py,sha256=0ERCwUwUH5lE51-D0egP3WEjHK4AQZsQv17s8lHg-kI,2124
|
137
|
+
novel_downloader/utils/epub/documents.py,sha256=SCvs1Z1F1kXRTpgrO6nl-izKJCihWC5tOXhU05KMsU4,12169
|
138
|
+
novel_downloader/utils/epub/models.py,sha256=oSgup2yenYMHhp0jpS4u5XixaiQ5h3sjg1q6Y2uGLOo,2915
|
139
|
+
novel_downloader/utils/epub/utils.py,sha256=hP8fMTioUDnEcqtQ7eF4Ofw62VDaMCix3h_TYIi57Yw,5874
|
140
|
+
novel_downloader/utils/file_utils/__init__.py,sha256=qrASldzqPs64CHaxPFTvxYn75abb4sdyTavksPhGmo4,1051
|
141
|
+
novel_downloader/utils/file_utils/io.py,sha256=mKfS9dDV5OVBK-2163GO2mk_2Lqw0mXX5iKmF1F1kEM,6483
|
142
|
+
novel_downloader/utils/file_utils/normalize.py,sha256=v0ZRGcuZ9KMj0GTgAMPCwSBnYkEz8LCnW5dJYjf_jQk,2023
|
143
|
+
novel_downloader/utils/file_utils/sanitize.py,sha256=sYMu7II8ebQVCwd5GzeLjBKKZNOxHXbyL6il8UGwlqo,2111
|
144
|
+
novel_downloader/utils/fontocr/__init__.py,sha256=L_q0BkI1OnKoxp5NA0H191V5KwOwzRG6sAg60RKANRs,586
|
145
|
+
novel_downloader/utils/fontocr/hash_store.py,sha256=a2j5icguKNKWKAsZNsjm_wEBz-RMe6ZY86cSjEyD88E,9447
|
146
|
+
novel_downloader/utils/fontocr/hash_utils.py,sha256=UqEMvkbzVvv5NwBJBRMO_X6nMDgE7xF28vfGjVr0X-0,3039
|
147
|
+
novel_downloader/utils/fontocr/model_loader.py,sha256=aBPZlwZ-rx2tDsWtN3BnB15vceqNkqTEBX1h2pMZf3E,2012
|
148
|
+
novel_downloader/utils/fontocr/ocr_v1.py,sha256=4VApGfOuShCs_YqPozLQMXNHvJor2J5CJ3mwudK1Ixg,11689
|
149
|
+
novel_downloader/utils/fontocr/ocr_v2.py,sha256=eIdtFwmoaK-bDdMnbIqF0qECyECDIHYTkWJcJZ5yBVc,27751
|
150
|
+
novel_downloader/utils/fontocr/ocr_v3.py,sha256=4g22Sjja5ER-3pKxA4y49FLItTcIdhMSWepjKOJnsgw,27101
|
151
|
+
novel_downloader/utils/text_utils/__init__.py,sha256=5-0aaY4M151vXMI1UyGXpOyuZ6cqtJLwvw0KgdTNRTk,885
|
152
|
+
novel_downloader/utils/text_utils/diff_display.py,sha256=pbAPiYdvI_1nls5SNRWxJo0iDLS_A-sApA6uQnoV9es,2527
|
153
|
+
novel_downloader/utils/text_utils/numeric_conversion.py,sha256=RJ3L5GBxgNEQYJ7xFoihLVsjGcObBfpUAk_Gz5MxlkA,6627
|
154
|
+
novel_downloader/utils/text_utils/text_cleaner.py,sha256=9-Ymi6H9BDBv1Sjk2gE9fCG4G3A8Lut-n2sfAyeyH2I,6124
|
155
|
+
novel_downloader/utils/text_utils/truncate_utils.py,sha256=GeQCczW0jAHSeDMxx0qCRtnvT-CH1-KjqJq2JBpIv7U,1483
|
156
|
+
novel_downloader/utils/time_utils/__init__.py,sha256=VP0RYksrkswEAkFmBQmeshe5eTiQeJpkT2ZKK5UEErU,624
|
157
|
+
novel_downloader/utils/time_utils/datetime_utils.py,sha256=8qXAMVU8txsFG3QF35JmCbvswE4JqEdqD5fiAS6psU0,4931
|
158
|
+
novel_downloader/utils/time_utils/sleep_utils.py,sha256=vsx-p0X9xqjtXH6YSzA6aF81yEM_fz1JrOYLJOIrqaI,3232
|
159
|
+
novel_downloader-1.5.0.dist-info/licenses/LICENSE,sha256=XgmnH0mBf-qEiizoVAfJQAKzPB9y3rBa-ni7M0Aqv4A,1066
|
160
|
+
novel_downloader-1.5.0.dist-info/METADATA,sha256=LWu5kIhamrwC9I10s7v1HfOf_OGYPJyjstcBvVfUJy0,7253
|
161
|
+
novel_downloader-1.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
162
|
+
novel_downloader-1.5.0.dist-info/entry_points.txt,sha256=u1Ns5xI_QJyL4HAFCgJvJdib9ugu7M9I2tnQwZjJxrk,112
|
163
|
+
novel_downloader-1.5.0.dist-info/top_level.txt,sha256=hP4jYWM2LTm1jxsW4hqEB8N0dsRvldO2QdhggJT917I,17
|
164
|
+
novel_downloader-1.5.0.dist-info/RECORD,,
|
@@ -1,94 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.config.site_rules
|
4
|
-
----------------------------------
|
5
|
-
|
6
|
-
Handles loading, saving, and caching of site-specific scraping rules.
|
7
|
-
|
8
|
-
This module provides functionality to:
|
9
|
-
- Load site rules from JSON, YAML, or TOML formats.
|
10
|
-
- Save rules into a standard JSON format.
|
11
|
-
"""
|
12
|
-
|
13
|
-
import json
|
14
|
-
import logging
|
15
|
-
from pathlib import Path
|
16
|
-
|
17
|
-
from novel_downloader.models import SiteRulesDict
|
18
|
-
from novel_downloader.utils.cache import cached_load_config
|
19
|
-
from novel_downloader.utils.constants import SITE_RULES_FILE
|
20
|
-
from novel_downloader.utils.file_utils import save_as_json
|
21
|
-
|
22
|
-
logger = logging.getLogger(__name__)
|
23
|
-
|
24
|
-
|
25
|
-
def save_rules_as_json(
|
26
|
-
source_path: str | Path, output_path: str | Path = SITE_RULES_FILE
|
27
|
-
) -> None:
|
28
|
-
"""
|
29
|
-
Load rules from source_path (toml, yaml, or json) and save as JSON.
|
30
|
-
|
31
|
-
:param source_path: Path to the source rules file
|
32
|
-
(supports .toml, .yaml, .yml, .json).
|
33
|
-
:param output_path: Path where the JSON output will be saved.
|
34
|
-
Defaults to SITE_RULES_FILE.
|
35
|
-
:raises FileNotFoundError: If the source_path does not exist.
|
36
|
-
:raises ValueError: If the source file format is not supported.
|
37
|
-
:raises Exception: If file loading or saving fails.
|
38
|
-
"""
|
39
|
-
TAG = "[Config]"
|
40
|
-
source_path = Path(source_path)
|
41
|
-
output_path = Path(output_path)
|
42
|
-
|
43
|
-
if not source_path.exists():
|
44
|
-
raise FileNotFoundError(f"Source file {source_path} not found.")
|
45
|
-
|
46
|
-
suffix = source_path.suffix.lower()
|
47
|
-
|
48
|
-
logger.debug("%s Loading rules from %s (format: %s)", TAG, source_path, suffix)
|
49
|
-
|
50
|
-
try:
|
51
|
-
if suffix == ".toml":
|
52
|
-
import tomllib
|
53
|
-
|
54
|
-
with source_path.open("rb") as f:
|
55
|
-
rules_data = tomllib.load(f)
|
56
|
-
elif suffix in {".yaml", ".yml"}:
|
57
|
-
import yaml
|
58
|
-
|
59
|
-
with source_path.open("r", encoding="utf-8") as f:
|
60
|
-
rules_data = yaml.safe_load(f)
|
61
|
-
elif suffix == ".json":
|
62
|
-
with source_path.open("r", encoding="utf-8") as f:
|
63
|
-
rules_data = json.load(f)
|
64
|
-
else:
|
65
|
-
raise ValueError(f"Unsupported input format: {suffix}")
|
66
|
-
|
67
|
-
except Exception as e:
|
68
|
-
logger.error("%s Failed to load rules from %s: %s", TAG, source_path, str(e))
|
69
|
-
raise
|
70
|
-
|
71
|
-
logger.info("%s Saving rules to %s as JSON", TAG, output_path)
|
72
|
-
|
73
|
-
save_as_json(rules_data, output_path)
|
74
|
-
return
|
75
|
-
|
76
|
-
|
77
|
-
@cached_load_config
|
78
|
-
def load_site_rules(json_path: str | Path = SITE_RULES_FILE) -> SiteRulesDict:
|
79
|
-
"""
|
80
|
-
Loads site scraping rules from a JSON file and caches the result for future access.
|
81
|
-
|
82
|
-
:param json_path: Path to the site rules JSON file. Defaults to SITE_RULES_FILE.
|
83
|
-
:return: A dictionary containing all site-specific scraping rules.
|
84
|
-
"""
|
85
|
-
json_path = Path(json_path)
|
86
|
-
site_rules: SiteRulesDict = {}
|
87
|
-
|
88
|
-
if not json_path.exists():
|
89
|
-
return site_rules
|
90
|
-
|
91
|
-
with json_path.open("r", encoding="utf-8") as f:
|
92
|
-
site_rules = json.load(f)
|
93
|
-
|
94
|
-
return site_rules
|
@@ -1,20 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.factory
|
4
|
-
-----------------------------
|
5
|
-
|
6
|
-
This package provides factory methods for dynamically retrieving components
|
7
|
-
based on runtime parameters such as site name or content type.
|
8
|
-
"""
|
9
|
-
|
10
|
-
from .downloader import get_downloader
|
11
|
-
from .exporter import get_exporter
|
12
|
-
from .fetcher import get_fetcher
|
13
|
-
from .parser import get_parser
|
14
|
-
|
15
|
-
__all__ = [
|
16
|
-
"get_downloader",
|
17
|
-
"get_exporter",
|
18
|
-
"get_fetcher",
|
19
|
-
"get_parser",
|
20
|
-
]
|
@@ -1,73 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.factory.downloader
|
4
|
-
----------------------------------------
|
5
|
-
|
6
|
-
This module implements a factory function for creating downloader instances
|
7
|
-
based on the site name and parser mode specified in the configuration.
|
8
|
-
"""
|
9
|
-
|
10
|
-
from collections.abc import Callable
|
11
|
-
|
12
|
-
from novel_downloader.config import load_site_rules
|
13
|
-
from novel_downloader.core.downloaders import (
|
14
|
-
BiqugeDownloader,
|
15
|
-
CommonDownloader,
|
16
|
-
EsjzoneDownloader,
|
17
|
-
LinovelibDownloader,
|
18
|
-
QianbiDownloader,
|
19
|
-
QidianDownloader,
|
20
|
-
SfacgDownloader,
|
21
|
-
YamiboDownloader,
|
22
|
-
)
|
23
|
-
from novel_downloader.core.interfaces import (
|
24
|
-
DownloaderProtocol,
|
25
|
-
FetcherProtocol,
|
26
|
-
ParserProtocol,
|
27
|
-
)
|
28
|
-
from novel_downloader.models import DownloaderConfig
|
29
|
-
|
30
|
-
DownloaderBuilder = Callable[
|
31
|
-
[FetcherProtocol, ParserProtocol, DownloaderConfig],
|
32
|
-
DownloaderProtocol,
|
33
|
-
]
|
34
|
-
|
35
|
-
_site_map: dict[str, DownloaderBuilder] = {
|
36
|
-
"biquge": BiqugeDownloader,
|
37
|
-
"esjzone": EsjzoneDownloader,
|
38
|
-
"linovelib": LinovelibDownloader,
|
39
|
-
"qianbi": QianbiDownloader,
|
40
|
-
"qidian": QidianDownloader,
|
41
|
-
"sfacg": SfacgDownloader,
|
42
|
-
"yamibo": YamiboDownloader,
|
43
|
-
}
|
44
|
-
|
45
|
-
|
46
|
-
def get_downloader(
|
47
|
-
fetcher: FetcherProtocol,
|
48
|
-
parser: ParserProtocol,
|
49
|
-
site: str,
|
50
|
-
config: DownloaderConfig,
|
51
|
-
) -> DownloaderProtocol:
|
52
|
-
"""
|
53
|
-
Returns an DownloaderProtocol for the given site.
|
54
|
-
|
55
|
-
:param fetcher: Fetcher implementation
|
56
|
-
:param parser: Parser implementation
|
57
|
-
:param site: Site name (e.g., 'qidian')
|
58
|
-
:param config: Downloader configuration
|
59
|
-
|
60
|
-
:return: An instance of a downloader class
|
61
|
-
"""
|
62
|
-
site_key = site.lower()
|
63
|
-
|
64
|
-
# site-specific
|
65
|
-
if site_key in _site_map:
|
66
|
-
return _site_map[site_key](fetcher, parser, config)
|
67
|
-
|
68
|
-
# fallback
|
69
|
-
site_rules = load_site_rules()
|
70
|
-
if site_key not in site_rules:
|
71
|
-
raise ValueError(f"Unsupported site: {site}")
|
72
|
-
|
73
|
-
return CommonDownloader(fetcher, parser, config, site_key)
|
@@ -1,58 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.factory.exporter
|
4
|
-
--------------------------------------
|
5
|
-
|
6
|
-
This module implements a factory function for creating exporter instances
|
7
|
-
based on the site name.
|
8
|
-
"""
|
9
|
-
|
10
|
-
from collections.abc import Callable
|
11
|
-
|
12
|
-
from novel_downloader.config import load_site_rules
|
13
|
-
from novel_downloader.core.exporters import (
|
14
|
-
BiqugeExporter,
|
15
|
-
CommonExporter,
|
16
|
-
EsjzoneExporter,
|
17
|
-
LinovelibExporter,
|
18
|
-
QianbiExporter,
|
19
|
-
QidianExporter,
|
20
|
-
SfacgExporter,
|
21
|
-
YamiboExporter,
|
22
|
-
)
|
23
|
-
from novel_downloader.core.interfaces import ExporterProtocol
|
24
|
-
from novel_downloader.models import ExporterConfig
|
25
|
-
|
26
|
-
ExporterBuilder = Callable[[ExporterConfig], ExporterProtocol]
|
27
|
-
|
28
|
-
_site_map: dict[str, ExporterBuilder] = {
|
29
|
-
"biquge": BiqugeExporter,
|
30
|
-
"esjzone": EsjzoneExporter,
|
31
|
-
"linovelib": LinovelibExporter,
|
32
|
-
"qianbi": QianbiExporter,
|
33
|
-
"qidian": QidianExporter,
|
34
|
-
"sfacg": SfacgExporter,
|
35
|
-
"yamibo": YamiboExporter,
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
def get_exporter(site: str, config: ExporterConfig) -> ExporterProtocol:
|
40
|
-
"""
|
41
|
-
Returns a site-specific exporter instance.
|
42
|
-
|
43
|
-
:param site: Site name (e.g., 'qidian')
|
44
|
-
:param config: Configuration for the exporter
|
45
|
-
:return: An instance of a exporter class
|
46
|
-
"""
|
47
|
-
site_key = site.lower()
|
48
|
-
|
49
|
-
# site-specific
|
50
|
-
if site_key in _site_map:
|
51
|
-
return _site_map[site_key](config)
|
52
|
-
|
53
|
-
# Fallback
|
54
|
-
site_rules = load_site_rules()
|
55
|
-
if site_key not in site_rules:
|
56
|
-
raise ValueError(f"Unsupported site: {site}")
|
57
|
-
|
58
|
-
return CommonExporter(config, site_key)
|
@@ -1,96 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.factory.fetcher
|
4
|
-
-------------------------------------
|
5
|
-
|
6
|
-
This module implements a factory function for retrieving fetcher instances
|
7
|
-
based on the target novel platform (site).
|
8
|
-
"""
|
9
|
-
|
10
|
-
from collections.abc import Callable
|
11
|
-
|
12
|
-
from novel_downloader.config import load_site_rules
|
13
|
-
from novel_downloader.core.fetchers import (
|
14
|
-
BiqugeBrowser,
|
15
|
-
BiqugeSession,
|
16
|
-
CommonBrowser,
|
17
|
-
CommonSession,
|
18
|
-
EsjzoneBrowser,
|
19
|
-
EsjzoneSession,
|
20
|
-
LinovelibBrowser,
|
21
|
-
LinovelibSession,
|
22
|
-
QianbiBrowser,
|
23
|
-
QianbiSession,
|
24
|
-
QidianBrowser,
|
25
|
-
QidianSession,
|
26
|
-
SfacgBrowser,
|
27
|
-
SfacgSession,
|
28
|
-
YamiboBrowser,
|
29
|
-
YamiboSession,
|
30
|
-
)
|
31
|
-
from novel_downloader.core.interfaces import FetcherProtocol
|
32
|
-
from novel_downloader.models import FetcherConfig
|
33
|
-
|
34
|
-
FetcherBuilder = Callable[[FetcherConfig], FetcherProtocol]
|
35
|
-
|
36
|
-
_site_map: dict[str, dict[str, FetcherBuilder]] = {
|
37
|
-
"biquge": {
|
38
|
-
"browser": BiqugeBrowser,
|
39
|
-
"session": BiqugeSession,
|
40
|
-
},
|
41
|
-
"esjzone": {
|
42
|
-
"browser": EsjzoneBrowser,
|
43
|
-
"session": EsjzoneSession,
|
44
|
-
},
|
45
|
-
"linovelib": {
|
46
|
-
"browser": LinovelibBrowser,
|
47
|
-
"session": LinovelibSession,
|
48
|
-
},
|
49
|
-
"qianbi": {
|
50
|
-
"browser": QianbiBrowser,
|
51
|
-
"session": QianbiSession,
|
52
|
-
},
|
53
|
-
"qidian": {
|
54
|
-
"browser": QidianBrowser,
|
55
|
-
"session": QidianSession,
|
56
|
-
},
|
57
|
-
"sfacg": {
|
58
|
-
"browser": SfacgBrowser,
|
59
|
-
"session": SfacgSession,
|
60
|
-
},
|
61
|
-
"yamibo": {
|
62
|
-
"browser": YamiboBrowser,
|
63
|
-
"session": YamiboSession,
|
64
|
-
},
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
def get_fetcher(
|
69
|
-
site: str,
|
70
|
-
config: FetcherConfig,
|
71
|
-
) -> FetcherProtocol:
|
72
|
-
"""
|
73
|
-
Returns an FetcherProtocol for the given site.
|
74
|
-
|
75
|
-
:param site: Site name (e.g., 'qidian')
|
76
|
-
:param config: Configuration for the requester
|
77
|
-
:return: An instance of a requester class
|
78
|
-
"""
|
79
|
-
site_key = site.lower()
|
80
|
-
mode = config.mode
|
81
|
-
|
82
|
-
# site-specific
|
83
|
-
fetcher_cls = _site_map.get(site_key, {}).get(mode)
|
84
|
-
if fetcher_cls is not None:
|
85
|
-
return fetcher_cls(config)
|
86
|
-
|
87
|
-
# fallback: use Common based on mode
|
88
|
-
site_rules = load_site_rules()
|
89
|
-
site_rule = site_rules.get(site_key)
|
90
|
-
if site_rule is None:
|
91
|
-
raise ValueError(f"Unsupported site: {site}")
|
92
|
-
profile = site_rule["profile"]
|
93
|
-
|
94
|
-
if mode == "browser":
|
95
|
-
return CommonBrowser(site_key, profile, config)
|
96
|
-
return CommonSession(site_key, profile, config)
|
@@ -1,86 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.factory.parser
|
4
|
-
------------------------------------
|
5
|
-
|
6
|
-
This module implements a factory function for creating parser instances
|
7
|
-
based on the site name and parser mode specified in the configuration.
|
8
|
-
"""
|
9
|
-
|
10
|
-
from collections.abc import Callable
|
11
|
-
|
12
|
-
from novel_downloader.config import load_site_rules
|
13
|
-
from novel_downloader.core.interfaces import ParserProtocol
|
14
|
-
from novel_downloader.core.parsers import (
|
15
|
-
BiqugeParser,
|
16
|
-
CommonParser,
|
17
|
-
EsjzoneParser,
|
18
|
-
LinovelibParser,
|
19
|
-
QianbiParser,
|
20
|
-
QidianParser,
|
21
|
-
SfacgParser,
|
22
|
-
YamiboParser,
|
23
|
-
)
|
24
|
-
from novel_downloader.models import ParserConfig
|
25
|
-
|
26
|
-
ParserBuilder = Callable[[ParserConfig], ParserProtocol]
|
27
|
-
|
28
|
-
_site_map: dict[str, dict[str, ParserBuilder]] = {
|
29
|
-
"biquge": {
|
30
|
-
"browser": BiqugeParser,
|
31
|
-
"session": BiqugeParser,
|
32
|
-
},
|
33
|
-
"esjzone": {
|
34
|
-
"browser": EsjzoneParser,
|
35
|
-
"session": EsjzoneParser,
|
36
|
-
},
|
37
|
-
"linovelib": {
|
38
|
-
"browser": LinovelibParser,
|
39
|
-
"session": LinovelibParser,
|
40
|
-
},
|
41
|
-
"qianbi": {
|
42
|
-
"browser": QianbiParser,
|
43
|
-
"session": QianbiParser,
|
44
|
-
},
|
45
|
-
"qidian": {
|
46
|
-
"browser": QidianParser,
|
47
|
-
"session": QidianParser,
|
48
|
-
},
|
49
|
-
"sfacg": {
|
50
|
-
"browser": SfacgParser,
|
51
|
-
"session": SfacgParser,
|
52
|
-
},
|
53
|
-
"yamibo": {
|
54
|
-
"browser": YamiboParser,
|
55
|
-
"session": YamiboParser,
|
56
|
-
},
|
57
|
-
}
|
58
|
-
|
59
|
-
|
60
|
-
def get_parser(site: str, config: ParserConfig) -> ParserProtocol:
|
61
|
-
"""
|
62
|
-
Returns a site-specific parser instance.
|
63
|
-
|
64
|
-
:param site: Site name (e.g., 'qidian')
|
65
|
-
:param config: Configuration for the parser
|
66
|
-
:return: An instance of a parser class
|
67
|
-
"""
|
68
|
-
site_key = site.lower()
|
69
|
-
|
70
|
-
if site_key in _site_map:
|
71
|
-
site_entry = _site_map[site_key]
|
72
|
-
if isinstance(site_entry, dict):
|
73
|
-
parser_class = site_entry.get(config.mode)
|
74
|
-
else:
|
75
|
-
parser_class = site_entry
|
76
|
-
|
77
|
-
if parser_class:
|
78
|
-
return parser_class(config)
|
79
|
-
|
80
|
-
# Fallback: site not mapped specially, try to load rule
|
81
|
-
site_rules = load_site_rules()
|
82
|
-
site_rule = site_rules.get(site_key)
|
83
|
-
if site_rule is None:
|
84
|
-
raise ValueError(f"Unsupported site: {site}")
|
85
|
-
|
86
|
-
return CommonParser(config, site_key, site_rule)
|
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
novel_downloader.core.fetchers.common
|
4
|
-
-------------------------------------
|
5
|
-
|
6
|
-
"""
|
7
|
-
|
8
|
-
from .browser import CommonBrowser
|
9
|
-
from .session import CommonSession
|
10
|
-
|
11
|
-
__all__ = [
|
12
|
-
"CommonBrowser",
|
13
|
-
"CommonSession",
|
14
|
-
]
|