novel-downloader 1.4.4__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.
Files changed (165) hide show
  1. novel_downloader/__init__.py +1 -1
  2. novel_downloader/cli/__init__.py +2 -2
  3. novel_downloader/cli/config.py +1 -83
  4. novel_downloader/cli/download.py +4 -5
  5. novel_downloader/cli/export.py +4 -1
  6. novel_downloader/cli/main.py +2 -0
  7. novel_downloader/cli/search.py +123 -0
  8. novel_downloader/config/__init__.py +3 -10
  9. novel_downloader/config/adapter.py +190 -54
  10. novel_downloader/config/loader.py +2 -3
  11. novel_downloader/core/__init__.py +13 -13
  12. novel_downloader/core/downloaders/__init__.py +10 -11
  13. novel_downloader/core/downloaders/base.py +152 -26
  14. novel_downloader/core/downloaders/biquge.py +5 -1
  15. novel_downloader/core/downloaders/common.py +157 -378
  16. novel_downloader/core/downloaders/esjzone.py +5 -1
  17. novel_downloader/core/downloaders/linovelib.py +5 -1
  18. novel_downloader/core/downloaders/qianbi.py +291 -4
  19. novel_downloader/core/downloaders/qidian.py +199 -285
  20. novel_downloader/core/downloaders/registry.py +67 -0
  21. novel_downloader/core/downloaders/sfacg.py +5 -1
  22. novel_downloader/core/downloaders/yamibo.py +5 -1
  23. novel_downloader/core/exporters/__init__.py +10 -11
  24. novel_downloader/core/exporters/base.py +87 -7
  25. novel_downloader/core/exporters/biquge.py +5 -8
  26. novel_downloader/core/exporters/common/__init__.py +2 -2
  27. novel_downloader/core/exporters/common/epub.py +82 -166
  28. novel_downloader/core/exporters/common/main_exporter.py +0 -60
  29. novel_downloader/core/exporters/common/txt.py +82 -83
  30. novel_downloader/core/exporters/epub_util.py +157 -1330
  31. novel_downloader/core/exporters/esjzone.py +5 -8
  32. novel_downloader/core/exporters/linovelib/__init__.py +2 -2
  33. novel_downloader/core/exporters/linovelib/epub.py +157 -212
  34. novel_downloader/core/exporters/linovelib/main_exporter.py +2 -59
  35. novel_downloader/core/exporters/linovelib/txt.py +67 -63
  36. novel_downloader/core/exporters/qianbi.py +5 -8
  37. novel_downloader/core/exporters/qidian.py +14 -4
  38. novel_downloader/core/exporters/registry.py +53 -0
  39. novel_downloader/core/exporters/sfacg.py +5 -8
  40. novel_downloader/core/exporters/txt_util.py +67 -0
  41. novel_downloader/core/exporters/yamibo.py +5 -8
  42. novel_downloader/core/fetchers/__init__.py +19 -24
  43. novel_downloader/core/fetchers/base/__init__.py +3 -3
  44. novel_downloader/core/fetchers/base/browser.py +23 -4
  45. novel_downloader/core/fetchers/base/session.py +30 -5
  46. novel_downloader/core/fetchers/biquge/__init__.py +3 -3
  47. novel_downloader/core/fetchers/biquge/browser.py +5 -0
  48. novel_downloader/core/fetchers/biquge/session.py +6 -1
  49. novel_downloader/core/fetchers/esjzone/__init__.py +3 -3
  50. novel_downloader/core/fetchers/esjzone/browser.py +5 -0
  51. novel_downloader/core/fetchers/esjzone/session.py +6 -1
  52. novel_downloader/core/fetchers/linovelib/__init__.py +3 -3
  53. novel_downloader/core/fetchers/linovelib/browser.py +6 -1
  54. novel_downloader/core/fetchers/linovelib/session.py +6 -1
  55. novel_downloader/core/fetchers/qianbi/__init__.py +3 -3
  56. novel_downloader/core/fetchers/qianbi/browser.py +5 -0
  57. novel_downloader/core/fetchers/qianbi/session.py +5 -0
  58. novel_downloader/core/fetchers/qidian/__init__.py +3 -3
  59. novel_downloader/core/fetchers/qidian/browser.py +12 -4
  60. novel_downloader/core/fetchers/qidian/session.py +11 -3
  61. novel_downloader/core/fetchers/registry.py +71 -0
  62. novel_downloader/core/fetchers/sfacg/__init__.py +3 -3
  63. novel_downloader/core/fetchers/sfacg/browser.py +5 -0
  64. novel_downloader/core/fetchers/sfacg/session.py +5 -0
  65. novel_downloader/core/fetchers/yamibo/__init__.py +3 -3
  66. novel_downloader/core/fetchers/yamibo/browser.py +5 -0
  67. novel_downloader/core/fetchers/yamibo/session.py +6 -1
  68. novel_downloader/core/interfaces/__init__.py +7 -5
  69. novel_downloader/core/interfaces/searcher.py +18 -0
  70. novel_downloader/core/parsers/__init__.py +10 -11
  71. novel_downloader/core/parsers/{biquge/main_parser.py → biquge.py} +7 -2
  72. novel_downloader/core/parsers/{esjzone/main_parser.py → esjzone.py} +7 -2
  73. novel_downloader/core/parsers/{linovelib/main_parser.py → linovelib.py} +7 -2
  74. novel_downloader/core/parsers/{qianbi/main_parser.py → qianbi.py} +7 -2
  75. novel_downloader/core/parsers/qidian/__init__.py +2 -2
  76. novel_downloader/core/parsers/qidian/chapter_encrypted.py +23 -21
  77. novel_downloader/core/parsers/qidian/chapter_normal.py +1 -1
  78. novel_downloader/core/parsers/qidian/main_parser.py +10 -21
  79. novel_downloader/core/parsers/qidian/utils/__init__.py +11 -11
  80. novel_downloader/core/parsers/qidian/utils/decryptor_fetcher.py +5 -6
  81. novel_downloader/core/parsers/qidian/utils/node_decryptor.py +2 -2
  82. novel_downloader/core/parsers/registry.py +68 -0
  83. novel_downloader/core/parsers/{sfacg/main_parser.py → sfacg.py} +7 -2
  84. novel_downloader/core/parsers/{yamibo/main_parser.py → yamibo.py} +7 -2
  85. novel_downloader/core/searchers/__init__.py +20 -0
  86. novel_downloader/core/searchers/base.py +92 -0
  87. novel_downloader/core/searchers/biquge.py +83 -0
  88. novel_downloader/core/searchers/esjzone.py +84 -0
  89. novel_downloader/core/searchers/qianbi.py +131 -0
  90. novel_downloader/core/searchers/qidian.py +87 -0
  91. novel_downloader/core/searchers/registry.py +63 -0
  92. novel_downloader/locales/en.json +12 -4
  93. novel_downloader/locales/zh.json +12 -4
  94. novel_downloader/models/__init__.py +4 -30
  95. novel_downloader/models/config.py +12 -6
  96. novel_downloader/models/search.py +16 -0
  97. novel_downloader/models/types.py +0 -2
  98. novel_downloader/resources/config/settings.toml +31 -4
  99. novel_downloader/resources/css_styles/intro.css +83 -0
  100. novel_downloader/resources/css_styles/main.css +30 -89
  101. novel_downloader/utils/__init__.py +52 -0
  102. novel_downloader/utils/chapter_storage.py +244 -224
  103. novel_downloader/utils/constants.py +1 -21
  104. novel_downloader/utils/epub/__init__.py +34 -0
  105. novel_downloader/utils/epub/builder.py +377 -0
  106. novel_downloader/utils/epub/constants.py +77 -0
  107. novel_downloader/utils/epub/documents.py +403 -0
  108. novel_downloader/utils/epub/models.py +134 -0
  109. novel_downloader/utils/epub/utils.py +212 -0
  110. novel_downloader/utils/file_utils/__init__.py +10 -14
  111. novel_downloader/utils/file_utils/io.py +20 -51
  112. novel_downloader/utils/file_utils/normalize.py +2 -2
  113. novel_downloader/utils/file_utils/sanitize.py +2 -3
  114. novel_downloader/utils/fontocr/__init__.py +5 -5
  115. novel_downloader/utils/{hash_store.py → fontocr/hash_store.py} +4 -3
  116. novel_downloader/utils/{hash_utils.py → fontocr/hash_utils.py} +2 -2
  117. novel_downloader/utils/fontocr/ocr_v1.py +13 -1
  118. novel_downloader/utils/fontocr/ocr_v2.py +13 -1
  119. novel_downloader/utils/fontocr/ocr_v3.py +744 -0
  120. novel_downloader/utils/i18n.py +2 -0
  121. novel_downloader/utils/logger.py +2 -0
  122. novel_downloader/utils/network.py +110 -251
  123. novel_downloader/utils/state.py +1 -0
  124. novel_downloader/utils/text_utils/__init__.py +18 -17
  125. novel_downloader/utils/text_utils/diff_display.py +4 -5
  126. novel_downloader/utils/text_utils/numeric_conversion.py +253 -0
  127. novel_downloader/utils/text_utils/text_cleaner.py +179 -0
  128. novel_downloader/utils/text_utils/truncate_utils.py +62 -0
  129. novel_downloader/utils/time_utils/__init__.py +3 -3
  130. novel_downloader/utils/time_utils/datetime_utils.py +4 -5
  131. novel_downloader/utils/time_utils/sleep_utils.py +2 -3
  132. {novel_downloader-1.4.4.dist-info → novel_downloader-1.5.0.dist-info}/METADATA +2 -2
  133. novel_downloader-1.5.0.dist-info/RECORD +164 -0
  134. novel_downloader/config/site_rules.py +0 -94
  135. novel_downloader/core/factory/__init__.py +0 -20
  136. novel_downloader/core/factory/downloader.py +0 -73
  137. novel_downloader/core/factory/exporter.py +0 -58
  138. novel_downloader/core/factory/fetcher.py +0 -96
  139. novel_downloader/core/factory/parser.py +0 -86
  140. novel_downloader/core/fetchers/common/__init__.py +0 -14
  141. novel_downloader/core/fetchers/common/browser.py +0 -79
  142. novel_downloader/core/fetchers/common/session.py +0 -79
  143. novel_downloader/core/parsers/biquge/__init__.py +0 -10
  144. novel_downloader/core/parsers/common/__init__.py +0 -13
  145. novel_downloader/core/parsers/common/helper.py +0 -323
  146. novel_downloader/core/parsers/common/main_parser.py +0 -106
  147. novel_downloader/core/parsers/esjzone/__init__.py +0 -10
  148. novel_downloader/core/parsers/linovelib/__init__.py +0 -10
  149. novel_downloader/core/parsers/qianbi/__init__.py +0 -10
  150. novel_downloader/core/parsers/sfacg/__init__.py +0 -10
  151. novel_downloader/core/parsers/yamibo/__init__.py +0 -10
  152. novel_downloader/models/browser.py +0 -21
  153. novel_downloader/models/site_rules.py +0 -99
  154. novel_downloader/models/tasks.py +0 -33
  155. novel_downloader/resources/css_styles/volume-intro.css +0 -56
  156. novel_downloader/resources/json/replace_word_map.json +0 -4
  157. novel_downloader/resources/text/blacklist.txt +0 -22
  158. novel_downloader/utils/text_utils/chapter_formatting.py +0 -46
  159. novel_downloader/utils/text_utils/font_mapping.py +0 -28
  160. novel_downloader/utils/text_utils/text_cleaning.py +0 -107
  161. novel_downloader-1.4.4.dist-info/RECORD +0 -165
  162. {novel_downloader-1.4.4.dist-info → novel_downloader-1.5.0.dist-info}/WHEEL +0 -0
  163. {novel_downloader-1.4.4.dist-info → novel_downloader-1.5.0.dist-info}/entry_points.txt +0 -0
  164. {novel_downloader-1.4.4.dist-info → novel_downloader-1.5.0.dist-info}/licenses/LICENSE +0 -0
  165. {novel_downloader-1.4.4.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
- ]