crawlo 1.4.6__py3-none-any.whl → 1.4.7__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.

Potentially problematic release.


This version of crawlo might be problematic. Click here for more details.

Files changed (374) hide show
  1. crawlo/__init__.py +90 -89
  2. crawlo/__version__.py +1 -1
  3. crawlo/cli.py +75 -75
  4. crawlo/commands/__init__.py +14 -14
  5. crawlo/commands/check.py +594 -594
  6. crawlo/commands/genspider.py +186 -186
  7. crawlo/commands/help.py +140 -138
  8. crawlo/commands/list.py +155 -155
  9. crawlo/commands/run.py +379 -341
  10. crawlo/commands/startproject.py +460 -460
  11. crawlo/commands/stats.py +187 -187
  12. crawlo/commands/utils.py +196 -196
  13. crawlo/config.py +320 -312
  14. crawlo/config_validator.py +277 -277
  15. crawlo/core/__init__.py +52 -52
  16. crawlo/core/engine.py +451 -438
  17. crawlo/core/processor.py +47 -47
  18. crawlo/core/scheduler.py +290 -291
  19. crawlo/crawler.py +698 -657
  20. crawlo/data/__init__.py +5 -5
  21. crawlo/data/user_agents.py +194 -194
  22. crawlo/downloader/__init__.py +280 -276
  23. crawlo/downloader/aiohttp_downloader.py +233 -233
  24. crawlo/downloader/cffi_downloader.py +250 -247
  25. crawlo/downloader/httpx_downloader.py +265 -259
  26. crawlo/downloader/hybrid_downloader.py +212 -212
  27. crawlo/downloader/playwright_downloader.py +425 -402
  28. crawlo/downloader/selenium_downloader.py +486 -472
  29. crawlo/event.py +45 -11
  30. crawlo/exceptions.py +215 -82
  31. crawlo/extension/__init__.py +65 -64
  32. crawlo/extension/health_check.py +141 -141
  33. crawlo/extension/log_interval.py +94 -94
  34. crawlo/extension/log_stats.py +70 -70
  35. crawlo/extension/logging_extension.py +53 -61
  36. crawlo/extension/memory_monitor.py +104 -104
  37. crawlo/extension/performance_profiler.py +133 -133
  38. crawlo/extension/request_recorder.py +107 -107
  39. crawlo/factories/__init__.py +27 -27
  40. crawlo/factories/base.py +68 -68
  41. crawlo/factories/crawler.py +104 -103
  42. crawlo/factories/registry.py +84 -84
  43. crawlo/factories/utils.py +135 -0
  44. crawlo/filters/__init__.py +170 -153
  45. crawlo/filters/aioredis_filter.py +348 -264
  46. crawlo/filters/memory_filter.py +261 -276
  47. crawlo/framework.py +306 -292
  48. crawlo/initialization/__init__.py +44 -44
  49. crawlo/initialization/built_in.py +391 -434
  50. crawlo/initialization/context.py +141 -141
  51. crawlo/initialization/core.py +240 -194
  52. crawlo/initialization/phases.py +230 -149
  53. crawlo/initialization/registry.py +143 -145
  54. crawlo/initialization/utils.py +49 -0
  55. crawlo/interfaces.py +23 -23
  56. crawlo/items/__init__.py +23 -23
  57. crawlo/items/base.py +23 -23
  58. crawlo/items/fields.py +52 -52
  59. crawlo/items/items.py +104 -104
  60. crawlo/logging/__init__.py +42 -46
  61. crawlo/logging/config.py +277 -197
  62. crawlo/logging/factory.py +175 -171
  63. crawlo/logging/manager.py +104 -112
  64. crawlo/middleware/__init__.py +87 -24
  65. crawlo/middleware/default_header.py +132 -132
  66. crawlo/middleware/download_delay.py +104 -104
  67. crawlo/middleware/middleware_manager.py +142 -142
  68. crawlo/middleware/offsite.py +123 -123
  69. crawlo/middleware/proxy.py +209 -209
  70. crawlo/middleware/request_ignore.py +86 -86
  71. crawlo/middleware/response_code.py +150 -150
  72. crawlo/middleware/response_filter.py +136 -136
  73. crawlo/middleware/retry.py +124 -124
  74. crawlo/mode_manager.py +287 -253
  75. crawlo/network/__init__.py +21 -21
  76. crawlo/network/request.py +375 -379
  77. crawlo/network/response.py +569 -664
  78. crawlo/pipelines/__init__.py +53 -22
  79. crawlo/pipelines/base_pipeline.py +452 -0
  80. crawlo/pipelines/bloom_dedup_pipeline.py +146 -146
  81. crawlo/pipelines/console_pipeline.py +39 -39
  82. crawlo/pipelines/csv_pipeline.py +316 -316
  83. crawlo/pipelines/database_dedup_pipeline.py +197 -197
  84. crawlo/pipelines/json_pipeline.py +218 -218
  85. crawlo/pipelines/memory_dedup_pipeline.py +105 -105
  86. crawlo/pipelines/mongo_pipeline.py +140 -132
  87. crawlo/pipelines/mysql_pipeline.py +469 -476
  88. crawlo/pipelines/pipeline_manager.py +100 -100
  89. crawlo/pipelines/redis_dedup_pipeline.py +155 -156
  90. crawlo/project.py +347 -347
  91. crawlo/queue/__init__.py +10 -0
  92. crawlo/queue/pqueue.py +38 -38
  93. crawlo/queue/queue_manager.py +591 -525
  94. crawlo/queue/redis_priority_queue.py +519 -370
  95. crawlo/settings/__init__.py +7 -7
  96. crawlo/settings/default_settings.py +284 -277
  97. crawlo/settings/setting_manager.py +219 -219
  98. crawlo/spider/__init__.py +657 -657
  99. crawlo/stats_collector.py +81 -81
  100. crawlo/subscriber.py +129 -129
  101. crawlo/task_manager.py +138 -138
  102. crawlo/templates/crawlo.cfg.tmpl +10 -10
  103. crawlo/templates/project/__init__.py.tmpl +2 -4
  104. crawlo/templates/project/items.py.tmpl +13 -17
  105. crawlo/templates/project/middlewares.py.tmpl +38 -38
  106. crawlo/templates/project/pipelines.py.tmpl +35 -36
  107. crawlo/templates/project/settings.py.tmpl +109 -111
  108. crawlo/templates/project/settings_distributed.py.tmpl +156 -159
  109. crawlo/templates/project/settings_gentle.py.tmpl +170 -176
  110. crawlo/templates/project/settings_high_performance.py.tmpl +171 -177
  111. crawlo/templates/project/settings_minimal.py.tmpl +98 -100
  112. crawlo/templates/project/settings_simple.py.tmpl +168 -174
  113. crawlo/templates/project/spiders/__init__.py.tmpl +9 -9
  114. crawlo/templates/run.py.tmpl +23 -23
  115. crawlo/templates/spider/spider.py.tmpl +32 -40
  116. crawlo/templates/spiders_init.py.tmpl +5 -10
  117. crawlo/tools/__init__.py +86 -189
  118. crawlo/tools/date_tools.py +289 -289
  119. crawlo/tools/distributed_coordinator.py +384 -384
  120. crawlo/tools/scenario_adapter.py +262 -262
  121. crawlo/tools/text_cleaner.py +232 -232
  122. crawlo/utils/__init__.py +50 -50
  123. crawlo/utils/batch_processor.py +276 -259
  124. crawlo/utils/config_manager.py +442 -0
  125. crawlo/utils/controlled_spider_mixin.py +439 -439
  126. crawlo/utils/db_helper.py +250 -250
  127. crawlo/utils/error_handler.py +410 -410
  128. crawlo/utils/fingerprint.py +121 -121
  129. crawlo/utils/func_tools.py +82 -82
  130. crawlo/utils/large_scale_helper.py +344 -344
  131. crawlo/utils/leak_detector.py +335 -0
  132. crawlo/utils/log.py +79 -79
  133. crawlo/utils/misc.py +81 -81
  134. crawlo/utils/mongo_connection_pool.py +157 -0
  135. crawlo/utils/mysql_connection_pool.py +197 -0
  136. crawlo/utils/performance_monitor.py +285 -285
  137. crawlo/utils/queue_helper.py +175 -175
  138. crawlo/utils/redis_checker.py +91 -0
  139. crawlo/utils/redis_connection_pool.py +578 -388
  140. crawlo/utils/redis_key_validator.py +198 -198
  141. crawlo/utils/request.py +278 -256
  142. crawlo/utils/request_serializer.py +225 -225
  143. crawlo/utils/resource_manager.py +337 -0
  144. crawlo/utils/selector_helper.py +137 -137
  145. crawlo/utils/singleton.py +70 -0
  146. crawlo/utils/spider_loader.py +201 -201
  147. crawlo/utils/text_helper.py +94 -94
  148. crawlo/utils/{url.py → url_utils.py} +39 -39
  149. crawlo-1.4.7.dist-info/METADATA +689 -0
  150. crawlo-1.4.7.dist-info/RECORD +347 -0
  151. examples/__init__.py +7 -7
  152. tests/__init__.py +7 -7
  153. tests/advanced_tools_example.py +217 -275
  154. tests/authenticated_proxy_example.py +110 -110
  155. tests/baidu_performance_test.py +108 -108
  156. tests/baidu_test.py +59 -59
  157. tests/bug_check_test.py +250 -250
  158. tests/cleaners_example.py +160 -160
  159. tests/comprehensive_framework_test.py +212 -212
  160. tests/comprehensive_test.py +81 -81
  161. tests/comprehensive_testing_summary.md +186 -186
  162. tests/config_validation_demo.py +142 -142
  163. tests/controlled_spider_example.py +205 -205
  164. tests/date_tools_example.py +180 -180
  165. tests/debug_configure.py +69 -69
  166. tests/debug_framework_logger.py +84 -84
  167. tests/debug_log_config.py +126 -126
  168. tests/debug_log_levels.py +63 -63
  169. tests/debug_pipelines.py +66 -66
  170. tests/detailed_log_test.py +233 -233
  171. tests/direct_selector_helper_test.py +96 -96
  172. tests/distributed_dedup_test.py +467 -0
  173. tests/distributed_test.py +66 -66
  174. tests/distributed_test_debug.py +76 -76
  175. tests/dynamic_loading_example.py +523 -523
  176. tests/dynamic_loading_test.py +104 -104
  177. tests/error_handling_example.py +171 -171
  178. tests/explain_mysql_update_behavior.py +76 -76
  179. tests/final_comprehensive_test.py +151 -151
  180. tests/final_log_test.py +260 -260
  181. tests/final_validation_test.py +182 -182
  182. tests/fix_log_test.py +142 -142
  183. tests/framework_performance_test.py +202 -202
  184. tests/log_buffering_test.py +111 -111
  185. tests/log_generation_timing_test.py +153 -153
  186. tests/monitor_redis_dedup.sh +72 -0
  187. tests/ofweek_scrapy/ofweek_scrapy/items.py +12 -12
  188. tests/ofweek_scrapy/ofweek_scrapy/middlewares.py +100 -100
  189. tests/ofweek_scrapy/ofweek_scrapy/pipelines.py +13 -13
  190. tests/ofweek_scrapy/ofweek_scrapy/settings.py +84 -84
  191. tests/ofweek_scrapy/scrapy.cfg +11 -11
  192. tests/optimized_performance_test.py +211 -211
  193. tests/performance_comparison.py +244 -244
  194. tests/queue_blocking_test.py +113 -113
  195. tests/queue_test.py +89 -89
  196. tests/redis_key_validation_demo.py +130 -130
  197. tests/request_params_example.py +150 -150
  198. tests/response_improvements_example.py +144 -144
  199. tests/scrapy_comparison/ofweek_scrapy.py +138 -138
  200. tests/scrapy_comparison/scrapy_test.py +133 -133
  201. tests/simple_cli_test.py +55 -0
  202. tests/simple_command_test.py +119 -119
  203. tests/simple_crawlo_test.py +126 -126
  204. tests/simple_follow_test.py +38 -38
  205. tests/simple_log_test2.py +137 -137
  206. tests/simple_optimization_test.py +128 -128
  207. tests/simple_queue_type_test.py +41 -41
  208. tests/simple_response_selector_test.py +94 -94
  209. tests/simple_selector_helper_test.py +154 -154
  210. tests/simple_selector_test.py +207 -207
  211. tests/simple_spider_test.py +49 -49
  212. tests/simple_url_test.py +73 -73
  213. tests/simulate_mysql_update_test.py +139 -139
  214. tests/spider_log_timing_test.py +177 -177
  215. tests/test_advanced_tools.py +148 -148
  216. tests/test_all_commands.py +230 -230
  217. tests/test_all_pipeline_fingerprints.py +133 -133
  218. tests/test_all_redis_key_configs.py +145 -145
  219. tests/test_asyncmy_usage.py +56 -56
  220. tests/test_batch_processor.py +178 -178
  221. tests/test_cleaners.py +54 -54
  222. tests/test_cli_arguments.py +119 -0
  223. tests/test_component_factory.py +174 -174
  224. tests/test_config_consistency.py +80 -80
  225. tests/test_config_merge.py +152 -152
  226. tests/test_config_validator.py +182 -182
  227. tests/test_controlled_spider_mixin.py +79 -79
  228. tests/test_crawler_process_import.py +38 -38
  229. tests/test_crawler_process_spider_modules.py +47 -47
  230. tests/test_crawlo_proxy_integration.py +114 -114
  231. tests/test_date_tools.py +123 -123
  232. tests/test_dedup_fix.py +220 -220
  233. tests/test_dedup_pipeline_consistency.py +124 -124
  234. tests/test_default_header_middleware.py +313 -313
  235. tests/test_distributed.py +65 -65
  236. tests/test_double_crawlo_fix.py +204 -204
  237. tests/test_double_crawlo_fix_simple.py +124 -124
  238. tests/test_download_delay_middleware.py +221 -221
  239. tests/test_downloader_proxy_compatibility.py +272 -272
  240. tests/test_edge_cases.py +305 -305
  241. tests/test_encoding_core.py +56 -56
  242. tests/test_encoding_detection.py +126 -126
  243. tests/test_enhanced_error_handler.py +270 -270
  244. tests/test_enhanced_error_handler_comprehensive.py +245 -245
  245. tests/test_error_handler_compatibility.py +112 -112
  246. tests/test_factories.py +252 -252
  247. tests/test_factory_compatibility.py +196 -196
  248. tests/test_final_validation.py +153 -153
  249. tests/test_fingerprint_consistency.py +135 -135
  250. tests/test_fingerprint_simple.py +51 -51
  251. tests/test_get_component_logger.py +83 -83
  252. tests/test_hash_performance.py +99 -99
  253. tests/test_integration.py +169 -169
  254. tests/test_item_dedup_redis_key.py +122 -122
  255. tests/test_large_scale_helper.py +235 -235
  256. tests/test_logging_enhancements.py +374 -374
  257. tests/test_logging_final.py +184 -184
  258. tests/test_logging_integration.py +312 -312
  259. tests/test_logging_system.py +282 -282
  260. tests/test_middleware_debug.py +141 -141
  261. tests/test_mode_consistency.py +51 -51
  262. tests/test_multi_directory.py +67 -67
  263. tests/test_multiple_spider_modules.py +80 -80
  264. tests/test_mysql_pipeline_config.py +164 -164
  265. tests/test_mysql_pipeline_error.py +98 -98
  266. tests/test_mysql_pipeline_init_log.py +82 -82
  267. tests/test_mysql_pipeline_integration.py +132 -132
  268. tests/test_mysql_pipeline_refactor.py +143 -143
  269. tests/test_mysql_pipeline_refactor_simple.py +85 -85
  270. tests/test_mysql_pipeline_robustness.py +195 -195
  271. tests/test_mysql_pipeline_types.py +88 -88
  272. tests/test_mysql_update_columns.py +93 -93
  273. tests/test_offsite_middleware.py +244 -244
  274. tests/test_offsite_middleware_simple.py +203 -203
  275. tests/test_optimized_selector_naming.py +100 -100
  276. tests/test_parsel.py +29 -29
  277. tests/test_performance.py +327 -327
  278. tests/test_performance_monitor.py +115 -115
  279. tests/test_pipeline_fingerprint_consistency.py +86 -86
  280. tests/test_priority_behavior.py +211 -211
  281. tests/test_priority_consistency.py +151 -151
  282. tests/test_priority_consistency_fixed.py +249 -249
  283. tests/test_proxy_health_check.py +32 -32
  284. tests/test_proxy_middleware.py +217 -217
  285. tests/test_proxy_middleware_enhanced.py +212 -212
  286. tests/test_proxy_middleware_integration.py +142 -142
  287. tests/test_proxy_middleware_refactored.py +207 -207
  288. tests/test_proxy_only.py +83 -83
  289. tests/test_proxy_providers.py +56 -56
  290. tests/test_proxy_stats.py +19 -19
  291. tests/test_proxy_strategies.py +59 -59
  292. tests/test_proxy_with_downloader.py +152 -152
  293. tests/test_queue_empty_check.py +41 -41
  294. tests/test_queue_manager_double_crawlo.py +173 -173
  295. tests/test_queue_manager_redis_key.py +179 -179
  296. tests/test_queue_naming.py +154 -154
  297. tests/test_queue_type.py +106 -106
  298. tests/test_queue_type_redis_config_consistency.py +130 -130
  299. tests/test_random_headers_default.py +322 -322
  300. tests/test_random_headers_necessity.py +308 -308
  301. tests/test_random_user_agent.py +72 -72
  302. tests/test_redis_config.py +28 -28
  303. tests/test_redis_connection_pool.py +294 -294
  304. tests/test_redis_key_naming.py +181 -181
  305. tests/test_redis_key_validator.py +123 -123
  306. tests/test_redis_queue.py +224 -224
  307. tests/test_redis_queue_name_fix.py +175 -175
  308. tests/test_redis_queue_type_fallback.py +129 -129
  309. tests/test_request_ignore_middleware.py +182 -182
  310. tests/test_request_params.py +111 -111
  311. tests/test_request_serialization.py +70 -70
  312. tests/test_response_code_middleware.py +349 -349
  313. tests/test_response_filter_middleware.py +427 -427
  314. tests/test_response_follow.py +104 -104
  315. tests/test_response_improvements.py +152 -152
  316. tests/test_response_selector_methods.py +92 -92
  317. tests/test_response_url_methods.py +70 -70
  318. tests/test_response_urljoin.py +86 -86
  319. tests/test_retry_middleware.py +333 -333
  320. tests/test_retry_middleware_realistic.py +273 -273
  321. tests/test_scheduler.py +252 -252
  322. tests/test_scheduler_config_update.py +133 -133
  323. tests/test_scrapy_style_encoding.py +112 -112
  324. tests/test_selector_helper.py +100 -100
  325. tests/test_selector_optimizations.py +146 -146
  326. tests/test_simple_response.py +61 -61
  327. tests/test_spider_loader.py +49 -49
  328. tests/test_spider_loader_comprehensive.py +69 -69
  329. tests/test_spider_modules.py +84 -84
  330. tests/test_spiders/test_spider.py +9 -9
  331. tests/test_telecom_spider_redis_key.py +205 -205
  332. tests/test_template_content.py +87 -87
  333. tests/test_template_redis_key.py +134 -134
  334. tests/test_tools.py +159 -159
  335. tests/test_user_agent_randomness.py +176 -176
  336. tests/test_user_agents.py +96 -96
  337. tests/untested_features_report.md +138 -138
  338. tests/verify_debug.py +51 -51
  339. tests/verify_distributed.py +117 -117
  340. tests/verify_log_fix.py +111 -111
  341. tests/verify_mysql_warnings.py +109 -109
  342. crawlo/logging/async_handler.py +0 -181
  343. crawlo/logging/monitor.py +0 -153
  344. crawlo/logging/sampler.py +0 -167
  345. crawlo/tools/authenticated_proxy.py +0 -241
  346. crawlo/tools/data_formatter.py +0 -226
  347. crawlo/tools/data_validator.py +0 -181
  348. crawlo/tools/encoding_converter.py +0 -127
  349. crawlo/tools/network_diagnostic.py +0 -365
  350. crawlo/tools/request_tools.py +0 -83
  351. crawlo/tools/retry_mechanism.py +0 -224
  352. crawlo/utils/env_config.py +0 -143
  353. crawlo/utils/large_scale_config.py +0 -287
  354. crawlo/utils/system.py +0 -11
  355. crawlo/utils/tools.py +0 -5
  356. crawlo-1.4.6.dist-info/METADATA +0 -329
  357. crawlo-1.4.6.dist-info/RECORD +0 -361
  358. tests/env_config_example.py +0 -134
  359. tests/ofweek_scrapy/ofweek_scrapy/spiders/ofweek_spider.py +0 -162
  360. tests/test_authenticated_proxy.py +0 -142
  361. tests/test_comprehensive.py +0 -147
  362. tests/test_dynamic_downloaders_proxy.py +0 -125
  363. tests/test_dynamic_proxy.py +0 -93
  364. tests/test_dynamic_proxy_config.py +0 -147
  365. tests/test_dynamic_proxy_real.py +0 -110
  366. tests/test_env_config.py +0 -122
  367. tests/test_framework_env_usage.py +0 -104
  368. tests/test_large_scale_config.py +0 -113
  369. tests/test_proxy_api.py +0 -265
  370. tests/test_real_scenario_proxy.py +0 -196
  371. tests/tools_example.py +0 -261
  372. {crawlo-1.4.6.dist-info → crawlo-1.4.7.dist-info}/WHEEL +0 -0
  373. {crawlo-1.4.6.dist-info → crawlo-1.4.7.dist-info}/entry_points.txt +0 -0
  374. {crawlo-1.4.6.dist-info → crawlo-1.4.7.dist-info}/top_level.txt +0 -0
@@ -1,147 +0,0 @@
1
- #!/usr/bin/python
2
- # -*- coding: UTF-8 -*-
3
- """
4
- 测试动态下载器(Selenium和Playwright)的代理配置逻辑
5
- """
6
-
7
- from crawlo.tools import AuthenticatedProxy
8
-
9
-
10
- def test_selenium_proxy_logic():
11
- """测试Selenium下载器的代理配置逻辑"""
12
- print("=== 测试Selenium下载器的代理配置逻辑 ===")
13
-
14
- # 代理配置
15
- proxy_config = {
16
- "http": "http://dwe20241014:Dwe0101014@182.201.243.186:58111",
17
- "https": "http://dwe20241014:Dwe0101014@182.201.243.186:58111"
18
- }
19
-
20
- # 创建代理对象
21
- proxy_url = proxy_config["http"]
22
- proxy = AuthenticatedProxy(proxy_url)
23
-
24
- print(f"原始代理URL: {proxy_url}")
25
- print(f"清洁URL: {proxy.clean_url}")
26
- print(f"认证信息: {proxy.get_auth_credentials()}")
27
-
28
- # 模拟Selenium的代理配置逻辑
29
- print(f"\nSelenium代理配置逻辑:")
30
- print(f" 1. 在爬虫设置中配置:")
31
- print(f" settings = {{")
32
- print(f" 'SELENIUM_PROXY': '{proxy.clean_url}',")
33
- print(f" }}")
34
-
35
- # 对于带认证的代理,需要特殊处理
36
- if proxy.username and proxy.password:
37
- print(f"\n 2. 带认证代理的处理逻辑:")
38
- print(f" - 用户名: {proxy.username}")
39
- print(f" - 密码: {proxy.password}")
40
- print(f" - 认证头: {proxy.get_auth_header()}")
41
- print(f" - 处理方式: 通过浏览器扩展或手动输入认证信息")
42
-
43
- print("\nSelenium配置逻辑测试完成!")
44
-
45
-
46
- def test_playwright_proxy_logic():
47
- """测试Playwright下载器的代理配置逻辑"""
48
- print("\n=== 测试Playwright下载器的代理配置逻辑 ===")
49
-
50
- # 代理配置
51
- proxy_config = {
52
- "http": "http://dwe20241014:Dwe0101014@182.201.243.186:58111",
53
- "https": "http://dwe20241014:Dwe0101014@182.201.243.186:58111"
54
- }
55
-
56
- # 创建代理对象
57
- proxy_url = proxy_config["http"]
58
- proxy = AuthenticatedProxy(proxy_url)
59
-
60
- print(f"原始代理URL: {proxy_url}")
61
- print(f"清洁URL: {proxy.clean_url}")
62
- print(f"认证信息: {proxy.get_auth_credentials()}")
63
-
64
- # 模拟Playwright的代理配置逻辑
65
- print(f"\nPlaywright代理配置逻辑:")
66
- print(f" 1. 简单代理配置:")
67
- print(f" settings = {{")
68
- print(f" 'PLAYWRIGHT_PROXY': '{proxy.clean_url}',")
69
- print(f" }}")
70
-
71
- # 对于带认证的代理,Playwright可以直接在代理配置中包含认证信息
72
- if proxy.username and proxy.password:
73
- print(f"\n 2. 带认证的代理配置逻辑:")
74
- print(f" settings = {{")
75
- print(f" 'PLAYWRIGHT_PROXY': {{")
76
- print(f" 'server': '{proxy.clean_url}',")
77
- print(f" 'username': '{proxy.username}',")
78
- print(f" 'password': '{proxy.password}'")
79
- print(f" }}")
80
- print(f" }}")
81
- print(f" 实现方式: 在启动浏览器时传递proxy参数")
82
-
83
- print("\nPlaywright配置逻辑测试完成!")
84
-
85
-
86
- def show_proxy_configuration_examples():
87
- """显示代理配置示例"""
88
- print("\n=== 代理配置示例 ===")
89
-
90
- # 不同类型的代理配置示例
91
- examples = [
92
- {
93
- "name": "带认证HTTP代理",
94
- "url": "http://username:password@proxy.example.com:8080",
95
- "selenium_config": "SELENIUM_PROXY = 'http://proxy.example.com:8080'",
96
- "playwright_config": "PLAYWRIGHT_PROXY = {'server': 'http://proxy.example.com:8080', 'username': 'username', 'password': 'password'}"
97
- },
98
- {
99
- "name": "带认证HTTPS代理",
100
- "url": "https://user:pass@secure-proxy.example.com:443",
101
- "selenium_config": "SELENIUM_PROXY = 'https://secure-proxy.example.com:443'",
102
- "playwright_config": "PLAYWRIGHT_PROXY = {'server': 'https://secure-proxy.example.com:443', 'username': 'user', 'password': 'pass'}"
103
- },
104
- {
105
- "name": "SOCKS5代理",
106
- "url": "socks5://username:password@socks-proxy.example.com:1080",
107
- "selenium_config": "SELENIUM_PROXY = 'socks5://socks-proxy.example.com:1080'",
108
- "playwright_config": "PLAYWRIGHT_PROXY = {'server': 'socks5://socks-proxy.example.com:1080', 'username': 'username', 'password': 'password'}"
109
- },
110
- {
111
- "name": "不带认证代理",
112
- "url": "http://proxy.example.com:8080",
113
- "selenium_config": "SELENIUM_PROXY = 'http://proxy.example.com:8080'",
114
- "playwright_config": "PLAYWRIGHT_PROXY = 'http://proxy.example.com:8080'"
115
- }
116
- ]
117
-
118
- for i, example in enumerate(examples, 1):
119
- print(f"\n示例 {i}: {example['name']}")
120
- print(f" 代理URL: {example['url']}")
121
- proxy = AuthenticatedProxy(example['url'])
122
- print(f" 清洁URL: {proxy.clean_url}")
123
- print(f" 用户名: {proxy.username or '无'}")
124
- print(f" 密码: {proxy.password or '无'}")
125
- print(f" Selenium配置: {example['selenium_config']}")
126
- print(f" Playwright配置: {example['playwright_config']}")
127
-
128
-
129
- def main():
130
- """主函数"""
131
- print("开始测试动态下载器的代理配置逻辑...\n")
132
-
133
- # 测试各个下载器的配置逻辑
134
- test_selenium_proxy_logic()
135
- test_playwright_proxy_logic()
136
- show_proxy_configuration_examples()
137
-
138
- print("\n所有配置逻辑测试完成!")
139
- print("\n总结:")
140
- print("1. Selenium和Playwright都支持代理配置")
141
- print("2. 带认证的代理需要特殊处理")
142
- print("3. Playwright对带认证代理的支持更直接")
143
- print("4. Selenium需要通过扩展或其他方式处理认证")
144
-
145
-
146
- if __name__ == "__main__":
147
- main()
@@ -1,110 +0,0 @@
1
- #!/usr/bin/python
2
- # -*- coding: UTF-8 -*-
3
- """
4
- 实际测试动态下载器(Playwright)通过代理访问网站
5
- """
6
-
7
- import asyncio
8
- from crawlo.spider import Spider
9
- from crawlo.network.request import Request
10
- from crawlo.tools import AuthenticatedProxy
11
-
12
-
13
- class ProxyTestSpider(Spider):
14
- """代理测试爬虫"""
15
- name = "proxy_test_spider" # 添加name属性
16
-
17
- # 自定义配置
18
- custom_settings = {
19
- "DOWNLOADER_TYPE": "playwright",
20
- "PLAYWRIGHT_BROWSER_TYPE": "chromium",
21
- "PLAYWRIGHT_HEADLESS": True,
22
- # 配置带认证的代理
23
- "PLAYWRIGHT_PROXY": {
24
- "server": "http://182.201.243.186:58111",
25
- "username": "dwe20241014",
26
- "password": "Dwe0101014"
27
- }
28
- }
29
-
30
- def __init__(self, **kwargs):
31
- super().__init__(**kwargs)
32
- print("代理测试爬虫初始化完成")
33
- print(f"代理配置: {self.custom_settings.get('PLAYWRIGHT_PROXY')}")
34
-
35
- def start_requests(self):
36
- """开始请求"""
37
- urls = [
38
- "https://httpbin.org/ip", # 查看IP地址
39
- "https://httpbin.org/headers", # 查看请求头
40
- ]
41
-
42
- for url in urls:
43
- request = Request(url, callback=self.parse)
44
- yield request
45
-
46
- def parse(self, response):
47
- """解析响应"""
48
- print(f"\n=== 响应信息 ===")
49
- print(f"URL: {response.url}")
50
- print(f"状态码: {response.status_code}")
51
- print(f"响应内容: {response.text[:500]}")
52
-
53
- # 保存响应内容
54
- filename = response.url.split("/")[-1].replace("?", "_").replace("&", "_")
55
- with open(f"proxy_test_{filename}.html", "w", encoding="utf-8") as f:
56
- f.write(response.text)
57
- print(f"响应已保存到 proxy_test_{filename}.html")
58
-
59
- # 返回一个简单的item
60
- yield {"url": response.url, "status": response.status_code}
61
-
62
-
63
- # 异步运行函数
64
- async def run_spider():
65
- """运行爬虫"""
66
- print("开始测试动态下载器通过代理访问网站...")
67
-
68
- # 创建爬虫实例
69
- spider = ProxyTestSpider()
70
-
71
- # 创建一个简单的crawler模拟器
72
- class MockCrawler:
73
- def __init__(self):
74
- from crawlo.settings.setting_manager import SettingManager
75
- self.settings = SettingManager()
76
- # 应用爬虫的自定义设置
77
- if hasattr(spider, 'custom_settings'):
78
- for key, value in spider.custom_settings.items():
79
- self.settings.set(key, value)
80
-
81
- crawler = MockCrawler()
82
-
83
- # 创建爬虫实例并绑定crawler
84
- spider_instance = spider.create_instance(crawler)
85
-
86
- # 执行初始请求
87
- requests = list(spider_instance.start_requests())
88
- print(f"生成了 {len(requests)} 个请求")
89
-
90
- # 使用Playwright下载器处理请求
91
- try:
92
- from crawlo.downloader import PlaywrightDownloader
93
- downloader = PlaywrightDownloader(crawler)
94
- await downloader.download(requests[0]) # 测试第一个请求
95
- print("Playwright下载器测试成功!")
96
- except Exception as e:
97
- print(f"Playwright下载器测试失败: {e}")
98
- import traceback
99
- traceback.print_exc()
100
-
101
- print("\n测试完成!")
102
-
103
-
104
- async def main():
105
- """主函数"""
106
- await run_spider()
107
-
108
-
109
- if __name__ == "__main__":
110
- asyncio.run(main())
tests/test_env_config.py DELETED
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- 环境变量配置工具测试
5
- """
6
- import os
7
- import sys
8
- import unittest
9
- from unittest.mock import patch
10
-
11
- # 添加项目根目录到Python路径
12
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
13
-
14
- from crawlo.utils.env_config import EnvConfigManager, get_env_var, get_redis_config, get_runtime_config
15
-
16
-
17
- class TestEnvConfigManager(unittest.TestCase):
18
- """环境变量配置管理器测试"""
19
-
20
- def test_get_env_var_str(self):
21
- """测试字符串环境变量获取"""
22
- with patch.dict(os.environ, {'TEST_VAR': 'test_value'}):
23
- result = EnvConfigManager.get_env_var('TEST_VAR', 'default', str)
24
- self.assertEqual(result, 'test_value')
25
-
26
- # 测试默认值
27
- result = EnvConfigManager.get_env_var('NON_EXISTENT_VAR', 'default', str)
28
- self.assertEqual(result, 'default')
29
-
30
- def test_get_env_var_int(self):
31
- """测试整数环境变量获取"""
32
- with patch.dict(os.environ, {'TEST_INT': '42'}):
33
- result = EnvConfigManager.get_env_var('TEST_INT', 0, int)
34
- self.assertEqual(result, 42)
35
-
36
- # 测试默认值
37
- result = EnvConfigManager.get_env_var('NON_EXISTENT_VAR', 10, int)
38
- self.assertEqual(result, 10)
39
-
40
- # 测试无效值
41
- with patch.dict(os.environ, {'INVALID_INT': 'not_a_number'}):
42
- result = EnvConfigManager.get_env_var('INVALID_INT', 5, int)
43
- self.assertEqual(result, 5)
44
-
45
- def test_get_env_var_float(self):
46
- """测试浮点数环境变量获取"""
47
- with patch.dict(os.environ, {'TEST_FLOAT': '3.14'}):
48
- result = EnvConfigManager.get_env_var('TEST_FLOAT', 0.0, float)
49
- self.assertEqual(result, 3.14)
50
-
51
- # 测试默认值
52
- result = EnvConfigManager.get_env_var('NON_EXISTENT_VAR', 2.5, float)
53
- self.assertEqual(result, 2.5)
54
-
55
- def test_get_env_var_bool(self):
56
- """测试布尔环境变量获取"""
57
- # 测试 True 值
58
- for true_val in ['1', 'true', 'True', 'TRUE', 'yes', 'on']:
59
- with patch.dict(os.environ, {'TEST_BOOL': true_val}):
60
- result = EnvConfigManager.get_env_var('TEST_BOOL', False, bool)
61
- self.assertTrue(result)
62
-
63
- # 测试 False 值
64
- for false_val in ['0', 'false', 'False', 'FALSE', 'no', 'off', '']:
65
- with patch.dict(os.environ, {'TEST_BOOL': false_val}):
66
- result = EnvConfigManager.get_env_var('TEST_BOOL', True, bool)
67
- self.assertFalse(result)
68
-
69
- # 测试默认值
70
- result = EnvConfigManager.get_env_var('NON_EXISTENT_VAR', True, bool)
71
- self.assertTrue(result)
72
-
73
- def test_get_redis_config(self):
74
- """测试 Redis 配置获取"""
75
- with patch.dict(os.environ, {
76
- 'REDIS_HOST': 'localhost',
77
- 'REDIS_PORT': '6380',
78
- 'REDIS_PASSWORD': 'secret',
79
- 'REDIS_DB': '1'
80
- }):
81
- config = get_redis_config()
82
- self.assertEqual(config['REDIS_HOST'], 'localhost')
83
- self.assertEqual(config['REDIS_PORT'], 6380)
84
- self.assertEqual(config['REDIS_PASSWORD'], 'secret')
85
- self.assertEqual(config['REDIS_DB'], 1)
86
-
87
- # 测试默认值
88
- with patch.dict(os.environ, {}):
89
- config = get_redis_config()
90
- self.assertEqual(config['REDIS_HOST'], '127.0.0.1')
91
- self.assertEqual(config['REDIS_PORT'], 6379)
92
- self.assertEqual(config['REDIS_PASSWORD'], '')
93
- self.assertEqual(config['REDIS_DB'], 0)
94
-
95
- def test_get_runtime_config(self):
96
- """测试运行时配置获取"""
97
- with patch.dict(os.environ, {
98
- 'CRAWLO_MODE': 'distributed',
99
- 'PROJECT_NAME': 'test_project',
100
- 'CONCURRENCY': '20'
101
- }):
102
- config = get_runtime_config()
103
- self.assertEqual(config['CRAWLO_MODE'], 'distributed')
104
- self.assertEqual(config['PROJECT_NAME'], 'test_project')
105
- self.assertEqual(config['CONCURRENCY'], 20)
106
-
107
- # 测试默认值
108
- with patch.dict(os.environ, {}):
109
- config = get_runtime_config()
110
- self.assertEqual(config['CRAWLO_MODE'], 'standalone')
111
- self.assertEqual(config['PROJECT_NAME'], 'crawlo')
112
- self.assertEqual(config['CONCURRENCY'], 8)
113
-
114
- def test_convenience_functions(self):
115
- """测试便捷函数"""
116
- with patch.dict(os.environ, {'TEST_CONVENIENCE': 'convenience_value'}):
117
- result = get_env_var('TEST_CONVENIENCE', 'default')
118
- self.assertEqual(result, 'convenience_value')
119
-
120
-
121
- if __name__ == '__main__':
122
- unittest.main()
@@ -1,104 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- 框架环境变量使用测试
5
- 验证整个框架中环境变量的正确使用
6
- """
7
- import sys
8
- import os
9
- import unittest
10
- from unittest.mock import patch, MagicMock
11
-
12
- # 添加项目根目录到Python路径
13
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
14
-
15
- from crawlo.utils.env_config import get_env_var, get_redis_config, get_runtime_config
16
- from crawlo.settings.setting_manager import SettingManager
17
- from crawlo.settings import default_settings
18
- from crawlo.mode_manager import from_env
19
-
20
-
21
- class TestFrameworkEnvUsage(unittest.TestCase):
22
- """框架环境变量使用测试"""
23
-
24
- def test_default_settings_env_usage(self):
25
- """测试 default_settings.py 中的环境变量使用"""
26
- # 验证 default_settings.py 不直接使用 os.getenv
27
- import inspect
28
- import crawlo.settings.default_settings as default_settings_module
29
-
30
- source_code = inspect.getsource(default_settings_module)
31
- # 检查是否还有直接使用 os.getenv 的地方
32
- self.assertNotIn('os.getenv', source_code,
33
- "default_settings.py 不应该直接使用 os.getenv")
34
-
35
- # 但应该使用 env_config 工具
36
- self.assertIn('get_redis_config', source_code,
37
- "default_settings.py 应该使用 get_redis_config")
38
- self.assertIn('get_runtime_config', source_code,
39
- "default_settings.py 应该使用 get_runtime_config")
40
-
41
- def test_env_config_tool(self):
42
- """测试环境变量配置工具"""
43
- # 测试获取Redis配置
44
- with patch.dict(os.environ, {
45
- 'REDIS_HOST': 'test.redis.com',
46
- 'REDIS_PORT': '6380',
47
- 'REDIS_PASSWORD': 'test_pass',
48
- 'REDIS_DB': '2'
49
- }):
50
- redis_config = get_redis_config()
51
- self.assertEqual(redis_config['REDIS_HOST'], 'test.redis.com')
52
- self.assertEqual(redis_config['REDIS_PORT'], 6380)
53
- self.assertEqual(redis_config['REDIS_PASSWORD'], 'test_pass')
54
- self.assertEqual(redis_config['REDIS_DB'], 2)
55
-
56
- # 测试获取运行时配置
57
- with patch.dict(os.environ, {
58
- 'PROJECT_NAME': 'test_project',
59
- 'CRAWLO_MODE': 'distributed',
60
- 'CONCURRENCY': '16'
61
- }):
62
- runtime_config = get_runtime_config()
63
- self.assertEqual(runtime_config['PROJECT_NAME'], 'test_project')
64
- self.assertEqual(runtime_config['CRAWLO_MODE'], 'distributed')
65
- self.assertEqual(runtime_config['CONCURRENCY'], 16)
66
-
67
- def test_settings_manager_with_env(self):
68
- """测试设置管理器与环境变量的集成"""
69
- # 设置环境变量
70
- env_vars = {
71
- 'PROJECT_NAME': 'env_test_project',
72
- 'CONCURRENCY': '12',
73
- 'REDIS_HOST': 'env.redis.test',
74
- 'REDIS_PORT': '6381'
75
- }
76
-
77
- with patch.dict(os.environ, env_vars):
78
- # 重新导入 default_settings 模块以获取最新的环境变量
79
- import importlib
80
- import crawlo.settings.default_settings
81
- importlib.reload(crawlo.settings.default_settings)
82
-
83
- # 创建设置管理器
84
- settings = SettingManager()
85
- settings.set_settings(crawlo.settings.default_settings)
86
-
87
- # 验证环境变量被正确使用
88
- redis_config = get_redis_config()
89
- self.assertEqual(settings.get('REDIS_HOST'), redis_config['REDIS_HOST'])
90
-
91
- runtime_config = get_runtime_config()
92
- self.assertEqual(settings.get('PROJECT_NAME'), runtime_config['PROJECT_NAME'])
93
-
94
- def test_mode_manager_env_usage(self):
95
- """测试 mode_manager.py 中的环境变量使用"""
96
- # 验证 from_env 函数现在会抛出异常
97
- with self.assertRaises(RuntimeError) as context:
98
- from_env()
99
-
100
- self.assertIn("环境变量配置已移除", str(context.exception))
101
-
102
-
103
- if __name__ == '__main__':
104
- unittest.main()
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- 大规模配置工具测试
5
- 测试 LargeScaleConfig, apply_large_scale_config
6
- """
7
- import sys
8
- import os
9
- import unittest
10
- from unittest.mock import Mock, patch, MagicMock
11
-
12
- # 添加项目根目录到 Python 路径
13
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
14
-
15
- from crawlo.utils.large_scale_config import LargeScaleConfig, apply_large_scale_config
16
-
17
-
18
- class TestLargeScaleConfig(unittest.TestCase):
19
- """大规模配置工具测试"""
20
-
21
- def test_conservative_config(self):
22
- """测试保守配置"""
23
- config = LargeScaleConfig.conservative_config(concurrency=8)
24
-
25
- # 验证基本配置
26
- self.assertEqual(config['CONCURRENCY'], 8)
27
- self.assertEqual(config['SCHEDULER_MAX_QUEUE_SIZE'], 80) # 8 * 10
28
- self.assertEqual(config['DOWNLOAD_DELAY'], 0.2)
29
- self.assertEqual(config['MAX_RUNNING_SPIDERS'], 1)
30
-
31
- # 验证连接池配置
32
- self.assertEqual(config['CONNECTION_POOL_LIMIT'], 16) # 8 * 2
33
-
34
- # 验证重试配置
35
- self.assertEqual(config['MAX_RETRY_TIMES'], 2)
36
-
37
- def test_balanced_config(self):
38
- """测试平衡配置"""
39
- config = LargeScaleConfig.balanced_config(concurrency=16)
40
-
41
- # 验证基本配置
42
- self.assertEqual(config['CONCURRENCY'], 16)
43
- self.assertEqual(config['SCHEDULER_MAX_QUEUE_SIZE'], 240) # 16 * 15
44
- self.assertEqual(config['DOWNLOAD_DELAY'], 0.1)
45
- self.assertEqual(config['MAX_RUNNING_SPIDERS'], 2)
46
-
47
- # 验证连接池配置
48
- self.assertEqual(config['CONNECTION_POOL_LIMIT'], 48) # 16 * 3
49
-
50
- # 验证重试配置
51
- self.assertEqual(config['MAX_RETRY_TIMES'], 3)
52
-
53
- def test_aggressive_config(self):
54
- """测试激进配置"""
55
- config = LargeScaleConfig.aggressive_config(concurrency=32)
56
-
57
- # 验证基本配置
58
- self.assertEqual(config['CONCURRENCY'], 32)
59
- self.assertEqual(config['SCHEDULER_MAX_QUEUE_SIZE'], 640) # 32 * 20
60
- self.assertEqual(config['DOWNLOAD_DELAY'], 0.05)
61
- self.assertEqual(config['MAX_RUNNING_SPIDERS'], 3)
62
-
63
- # 验证连接池配置
64
- self.assertEqual(config['CONNECTION_POOL_LIMIT'], 128) # 32 * 4
65
-
66
- # 验证重试配置
67
- self.assertEqual(config['MAX_RETRY_TIMES'], 5)
68
-
69
- def test_memory_optimized_config(self):
70
- """测试内存优化配置"""
71
- config = LargeScaleConfig.memory_optimized_config(concurrency=12)
72
-
73
- # 验证基本配置
74
- self.assertEqual(config['CONCURRENCY'], 12)
75
- self.assertEqual(config['SCHEDULER_MAX_QUEUE_SIZE'], 60) # 12 * 5
76
- self.assertEqual(config['DOWNLOAD_DELAY'], 0.1)
77
- self.assertEqual(config['MAX_RUNNING_SPIDERS'], 1)
78
-
79
- # 验证连接池配置
80
- self.assertEqual(config['CONNECTION_POOL_LIMIT'], 12) # 12 * 1
81
-
82
- # 验证内存限制配置
83
- self.assertEqual(config['DOWNLOAD_MAXSIZE'], 2 * 1024 * 1024) # 2MB
84
- self.assertEqual(config['DOWNLOAD_WARN_SIZE'], 512 * 1024) # 512KB
85
-
86
- # 验证重试配置
87
- self.assertEqual(config['MAX_RETRY_TIMES'], 2)
88
-
89
- def test_apply_large_scale_config(self):
90
- """测试应用大规模配置"""
91
- settings_dict = {}
92
-
93
- # 应用平衡配置
94
- apply_large_scale_config(settings_dict, "balanced", 16)
95
-
96
- # 验证配置已应用
97
- self.assertEqual(settings_dict['CONCURRENCY'], 16)
98
- self.assertEqual(settings_dict['SCHEDULER_MAX_QUEUE_SIZE'], 240)
99
- self.assertEqual(settings_dict['DOWNLOAD_DELAY'], 0.1)
100
-
101
- def test_apply_large_scale_config_invalid_type(self):
102
- """测试应用无效的大规模配置类型"""
103
- settings_dict = {}
104
-
105
- # 应用无效配置类型应该抛出异常
106
- with self.assertRaises(ValueError) as context:
107
- apply_large_scale_config(settings_dict, "invalid_type", 16)
108
-
109
- self.assertIn("不支持的配置类型", str(context.exception))
110
-
111
-
112
- if __name__ == '__main__':
113
- unittest.main()