graph-crawler 5.2.1__tar.gz → 5.3.2__tar.gz

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 (956) hide show
  1. graph_crawler-5.3.2/CHANGELOG.md +353 -0
  2. graph_crawler-5.3.2/CODE_STYLE.md +1473 -0
  3. graph_crawler-5.3.2/LICENSE +21 -0
  4. graph_crawler-5.3.2/MANIFEST.in +16 -0
  5. graph_crawler-5.3.2/PKG-INFO +531 -0
  6. graph_crawler-5.3.2/README.md +410 -0
  7. graph_crawler-5.3.2/graph_crawler/__init__.py +492 -0
  8. graph_crawler-5.3.2/graph_crawler/__version__.py +8 -0
  9. graph_crawler-5.3.2/graph_crawler/ai/__init__.py +50 -0
  10. graph_crawler-5.3.2/graph_crawler/api/__init__.py +28 -0
  11. graph_crawler-5.3.2/graph_crawler/api/_core.py +283 -0
  12. graph_crawler-5.3.2/graph_crawler/api/_distributed.py +172 -0
  13. graph_crawler-5.3.2/graph_crawler/api/_shared.py +110 -0
  14. graph_crawler-5.3.2/graph_crawler/api/_sitemap_distributed.py +238 -0
  15. graph_crawler-5.3.2/graph_crawler/api/async_.py +323 -0
  16. graph_crawler-5.3.2/graph_crawler/api/cli.py +440 -0
  17. graph_crawler-5.3.2/graph_crawler/api/client/__init__.py +8 -0
  18. graph_crawler-5.3.2/graph_crawler/api/client/client.py +470 -0
  19. graph_crawler-5.3.2/graph_crawler/api/history_manager.py +55 -0
  20. graph_crawler-5.3.2/graph_crawler/api/project_init.py +196 -0
  21. graph_crawler-5.3.2/graph_crawler/api/server/__init__.py +18 -0
  22. graph_crawler-5.3.2/graph_crawler/api/server/crawl_monitor.py +145 -0
  23. graph_crawler-5.3.2/graph_crawler/api/server/dashboard.py +221 -0
  24. graph_crawler-5.3.2/graph_crawler/api/server/rest_api.py +704 -0
  25. graph_crawler-5.3.2/graph_crawler/api/server/webhooks.py +421 -0
  26. graph_crawler-5.3.2/graph_crawler/api/server/websocket_manager.py +89 -0
  27. graph_crawler-5.3.2/graph_crawler/api/stats_collector.py +88 -0
  28. graph_crawler-5.3.2/graph_crawler/api/sync.py +536 -0
  29. graph_crawler-5.3.2/graph_crawler/application/__init__.py +38 -0
  30. graph_crawler-5.3.2/graph_crawler/application/bootstrap.py +211 -0
  31. graph_crawler-5.3.2/graph_crawler/application/context/__init__.py +31 -0
  32. graph_crawler-5.3.2/graph_crawler/application/context/dependency_registry.py +354 -0
  33. graph_crawler-5.3.2/graph_crawler/application/context/graph_context.py +217 -0
  34. graph_crawler-5.3.2/graph_crawler/application/context/merge_context.py +221 -0
  35. graph_crawler-5.3.2/graph_crawler/application/dto/__init__.py +67 -0
  36. graph_crawler-5.3.2/graph_crawler/application/dto/edge_dto.py +25 -0
  37. graph_crawler-5.3.2/graph_crawler/application/dto/graph_dto.py +27 -0
  38. graph_crawler-5.3.2/graph_crawler/application/dto/mappers/__init__.py +14 -0
  39. graph_crawler-5.3.2/graph_crawler/application/dto/mappers/edge_mapper.py +149 -0
  40. graph_crawler-5.3.2/graph_crawler/application/dto/mappers/graph_mapper.py +622 -0
  41. graph_crawler-5.3.2/graph_crawler/application/dto/mappers/node_data_codec.py +190 -0
  42. graph_crawler-5.3.2/graph_crawler/application/dto/mappers/node_mapper.py +417 -0
  43. graph_crawler-5.3.2/graph_crawler/application/dto/node_dto.py +27 -0
  44. graph_crawler-5.3.2/graph_crawler/application/dto/utils.py +272 -0
  45. graph_crawler-5.3.2/graph_crawler/application/services/__init__.py +60 -0
  46. graph_crawler-5.3.2/graph_crawler/application/services/application_container.py +208 -0
  47. graph_crawler-5.3.2/graph_crawler/application/services/driver_factory.py +147 -0
  48. graph_crawler-5.3.2/graph_crawler/application/services/exporters/__init__.py +26 -0
  49. graph_crawler-5.3.2/graph_crawler/application/services/exporters/base_exporter.py +150 -0
  50. graph_crawler-5.3.2/graph_crawler/application/services/exporters/csv_exporter.py +318 -0
  51. graph_crawler-5.3.2/graph_crawler/application/services/exporters/edge_exporter.py +432 -0
  52. graph_crawler-5.3.2/graph_crawler/application/services/exporters/excel_exporter.py +301 -0
  53. graph_crawler-5.3.2/graph_crawler/application/services/exporters/jsonl_exporter.py +290 -0
  54. graph_crawler-5.3.2/graph_crawler/application/services/exporters/node_exporter.py +284 -0
  55. graph_crawler-5.3.2/graph_crawler/application/services/exporters/parquet_exporter.py +248 -0
  56. graph_crawler-5.3.2/graph_crawler/application/services/exporters/sql_exporter.py +267 -0
  57. graph_crawler-5.3.2/graph_crawler/application/services/finalize.py +115 -0
  58. graph_crawler-5.3.2/graph_crawler/application/services/low_memory_graph_saver.py +337 -0
  59. graph_crawler-5.3.2/graph_crawler/application/services/resource_budget.py +179 -0
  60. graph_crawler-5.3.2/graph_crawler/application/services/scheduling/__init__.py +12 -0
  61. graph_crawler-5.3.2/graph_crawler/application/services/scheduling/rule_based_scheduler.py +113 -0
  62. graph_crawler-5.3.2/graph_crawler/application/services/storage_factory.py +195 -0
  63. graph_crawler-5.3.2/graph_crawler/application/use_cases/__init__.py +11 -0
  64. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/__init__.py +81 -0
  65. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/adaptive_throttler.py +373 -0
  66. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/async_bridge.py +45 -0
  67. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/base_spider.py +155 -0
  68. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/celery_batch_spider.py +656 -0
  69. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/celery_spider.py +445 -0
  70. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/checkpoint.py +421 -0
  71. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/crawl_coordinator.py +1049 -0
  72. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/dead_letter_queue.py +413 -0
  73. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/domain_rate_limiter.py +262 -0
  74. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/filters/__init__.py +10 -0
  75. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/filters/base.py +74 -0
  76. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/filters/domain_filter.py +195 -0
  77. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/filters/domain_patterns.py +30 -0
  78. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/filters/path_filter.py +95 -0
  79. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/incremental_strategy.py +239 -0
  80. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/link_processor.py +932 -0
  81. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/multiprocess_spider.py +511 -0
  82. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/node_scanner.py +866 -0
  83. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/parsers/__init__.py +6 -0
  84. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/parsers/base.py +73 -0
  85. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/parsers/html_parser.py +154 -0
  86. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/progress_tracker.py +235 -0
  87. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/scheduler.py +747 -0
  88. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/serialization_mixin.py +218 -0
  89. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/sitemap_parser.py +657 -0
  90. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/sitemap_processor.py +401 -0
  91. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/sitemap_spider.py +608 -0
  92. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/spider.py +813 -0
  93. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/spider_lifecycle.py +108 -0
  94. graph_crawler-5.3.2/graph_crawler/application/use_cases/crawling/worker_pool.py +154 -0
  95. graph_crawler-5.3.2/graph_crawler/application/use_cases/graph_export.py +504 -0
  96. graph_crawler-5.3.2/graph_crawler/application/use_cases/graph_merge/__init__.py +33 -0
  97. graph_crawler-5.3.2/graph_crawler/application/use_cases/graph_merge/graph_operations.py +632 -0
  98. graph_crawler-5.3.2/graph_crawler/application/use_cases/graph_merge/merge_strategies.py +348 -0
  99. graph_crawler-5.3.2/graph_crawler/data/__init__.py +28 -0
  100. graph_crawler-5.3.2/graph_crawler/data/backends/__init__.py +21 -0
  101. graph_crawler-5.3.2/graph_crawler/data/backends/memory.py +486 -0
  102. graph_crawler-5.3.2/graph_crawler/data/backends/sqlite.py +1866 -0
  103. graph_crawler-5.3.2/graph_crawler/data/interfaces.py +563 -0
  104. graph_crawler-5.3.2/graph_crawler/domain/__init__.py +62 -0
  105. graph_crawler-5.3.2/graph_crawler/domain/context/__init__.py +14 -0
  106. graph_crawler-5.3.2/graph_crawler/domain/context/crawl_context.py +531 -0
  107. graph_crawler-5.3.2/graph_crawler/domain/entities/__init__.py +32 -0
  108. graph_crawler-5.3.2/graph_crawler/domain/entities/edge.py +345 -0
  109. graph_crawler-5.3.2/graph_crawler/domain/entities/edge_analysis.py +223 -0
  110. graph_crawler-5.3.2/graph_crawler/domain/entities/graph.py +4169 -0
  111. graph_crawler-5.3.2/graph_crawler/domain/entities/graph_operations.py +30 -0
  112. graph_crawler-5.3.2/graph_crawler/domain/entities/graph_statistics.py +10 -0
  113. graph_crawler-5.3.2/graph_crawler/domain/entities/merge_strategies.py +33 -0
  114. graph_crawler-5.3.2/graph_crawler/domain/entities/node.py +780 -0
  115. graph_crawler-5.3.2/graph_crawler/domain/entities/redirect_mode.py +23 -0
  116. graph_crawler-5.3.2/graph_crawler/domain/entities/registries.py +223 -0
  117. graph_crawler-5.3.2/graph_crawler/domain/entities/sitemap_node.py +74 -0
  118. graph_crawler-5.3.2/graph_crawler/domain/entities/strategies.py +202 -0
  119. graph_crawler-5.3.2/graph_crawler/domain/events/__init__.py +162 -0
  120. graph_crawler-5.3.2/graph_crawler/domain/events/base.py +60 -0
  121. graph_crawler-5.3.2/graph_crawler/domain/events/crawl.py +112 -0
  122. graph_crawler-5.3.2/graph_crawler/domain/events/edge.py +43 -0
  123. graph_crawler-5.3.2/graph_crawler/domain/events/event_bus.py +250 -0
  124. graph_crawler-5.3.2/graph_crawler/domain/events/events.py +313 -0
  125. graph_crawler-5.3.2/graph_crawler/domain/events/fetch.py +120 -0
  126. graph_crawler-5.3.2/graph_crawler/domain/events/idempotent_subscriber.py +120 -0
  127. graph_crawler-5.3.2/graph_crawler/domain/events/legacy_type_map.py +45 -0
  128. graph_crawler-5.3.2/graph_crawler/domain/events/llm.py +148 -0
  129. graph_crawler-5.3.2/graph_crawler/domain/events/node.py +111 -0
  130. graph_crawler-5.3.2/graph_crawler/domain/events/plugin.py +92 -0
  131. graph_crawler-5.3.2/graph_crawler/domain/events/scheduler.py +98 -0
  132. graph_crawler-5.3.2/graph_crawler/domain/events/storage.py +161 -0
  133. graph_crawler-5.3.2/graph_crawler/domain/interfaces/__init__.py +111 -0
  134. graph_crawler-5.3.2/graph_crawler/domain/interfaces/adapter.py +29 -0
  135. graph_crawler-5.3.2/graph_crawler/domain/interfaces/control_channel.py +371 -0
  136. graph_crawler-5.3.2/graph_crawler/domain/interfaces/crawl_context.py +49 -0
  137. graph_crawler-5.3.2/graph_crawler/domain/interfaces/distributed_spider.py +62 -0
  138. graph_crawler-5.3.2/graph_crawler/domain/interfaces/driver.py +87 -0
  139. graph_crawler-5.3.2/graph_crawler/domain/interfaces/event_bus.py +61 -0
  140. graph_crawler-5.3.2/graph_crawler/domain/interfaces/exporters.py +69 -0
  141. graph_crawler-5.3.2/graph_crawler/domain/interfaces/filter.py +19 -0
  142. graph_crawler-5.3.2/graph_crawler/domain/interfaces/merge_context.py +52 -0
  143. graph_crawler-5.3.2/graph_crawler/domain/interfaces/node_interfaces.py +389 -0
  144. graph_crawler-5.3.2/graph_crawler/domain/interfaces/parser.py +88 -0
  145. graph_crawler-5.3.2/graph_crawler/domain/interfaces/plugin_manager.py +53 -0
  146. graph_crawler-5.3.2/graph_crawler/domain/interfaces/processor.py +11 -0
  147. graph_crawler-5.3.2/graph_crawler/domain/interfaces/scanner.py +57 -0
  148. graph_crawler-5.3.2/graph_crawler/domain/interfaces/scheduler.py +43 -0
  149. graph_crawler-5.3.2/graph_crawler/domain/interfaces/scheduling/__init__.py +40 -0
  150. graph_crawler-5.3.2/graph_crawler/domain/interfaces/scheduling/frontier.py +97 -0
  151. graph_crawler-5.3.2/graph_crawler/domain/interfaces/scheduling/scheduler.py +107 -0
  152. graph_crawler-5.3.2/graph_crawler/domain/interfaces/spider.py +63 -0
  153. graph_crawler-5.3.2/graph_crawler/domain/interfaces/stop_condition.py +211 -0
  154. graph_crawler-5.3.2/graph_crawler/domain/interfaces/storage/__init__.py +43 -0
  155. graph_crawler-5.3.2/graph_crawler/domain/interfaces/storage/base.py +68 -0
  156. graph_crawler-5.3.2/graph_crawler/domain/interfaces/storage/eviction.py +98 -0
  157. graph_crawler-5.3.2/graph_crawler/domain/interfaces/storage/queue.py +234 -0
  158. graph_crawler-5.3.2/graph_crawler/domain/services/__init__.py +216 -0
  159. graph_crawler-5.3.2/graph_crawler/domain/services/adjacency_maintenance.py +95 -0
  160. graph_crawler-5.3.2/graph_crawler/domain/services/cycle_detection.py +92 -0
  161. graph_crawler-5.3.2/graph_crawler/domain/services/degree_ranking.py +47 -0
  162. graph_crawler-5.3.2/graph_crawler/domain/services/depth_context.py +123 -0
  163. graph_crawler-5.3.2/graph_crawler/domain/services/display_title.py +47 -0
  164. graph_crawler-5.3.2/graph_crawler/domain/services/duplicate_detection.py +141 -0
  165. graph_crawler-5.3.2/graph_crawler/domain/services/duplicate_selector.py +127 -0
  166. graph_crawler-5.3.2/graph_crawler/domain/services/duplicate_stats.py +63 -0
  167. graph_crawler-5.3.2/graph_crawler/domain/services/edge_filter.py +82 -0
  168. graph_crawler-5.3.2/graph_crawler/domain/services/edge_statistics.py +110 -0
  169. graph_crawler-5.3.2/graph_crawler/domain/services/eviction_policy.py +83 -0
  170. graph_crawler-5.3.2/graph_crawler/domain/services/graph_query_cascade.py +178 -0
  171. graph_crawler-5.3.2/graph_crawler/domain/services/graph_statistics.py +186 -0
  172. graph_crawler-5.3.2/graph_crawler/domain/services/graph_traversal.py +150 -0
  173. graph_crawler-5.3.2/graph_crawler/domain/services/language_versions.py +73 -0
  174. graph_crawler-5.3.2/graph_crawler/domain/services/lsh_index.py +99 -0
  175. graph_crawler-5.3.2/graph_crawler/domain/services/minimap_builder.py +147 -0
  176. graph_crawler-5.3.2/graph_crawler/domain/services/node_content_resolver.py +128 -0
  177. graph_crawler-5.3.2/graph_crawler/domain/services/node_view_builder.py +163 -0
  178. graph_crawler-5.3.2/graph_crawler/domain/services/pagination_guards.py +136 -0
  179. graph_crawler-5.3.2/graph_crawler/domain/services/predicate_ops.py +77 -0
  180. graph_crawler-5.3.2/graph_crawler/domain/services/schema_filter.py +138 -0
  181. graph_crawler-5.3.2/graph_crawler/domain/services/search_haystack.py +102 -0
  182. graph_crawler-5.3.2/graph_crawler/domain/services/simhash_clustering.py +96 -0
  183. graph_crawler-5.3.2/graph_crawler/domain/services/simhash_fallback.py +59 -0
  184. graph_crawler-5.3.2/graph_crawler/domain/services/similarity_ranking.py +62 -0
  185. graph_crawler-5.3.2/graph_crawler/domain/services/text_search.py +157 -0
  186. graph_crawler-5.3.2/graph_crawler/domain/services/url_clustering.py +88 -0
  187. graph_crawler-5.3.2/graph_crawler/domain/services/url_deduplication.py +101 -0
  188. graph_crawler-5.3.2/graph_crawler/domain/services/url_normalizer.py +117 -0
  189. graph_crawler-5.3.2/graph_crawler/domain/services/url_rule_matcher.py +103 -0
  190. graph_crawler-5.3.2/graph_crawler/domain/services/url_tree_builder.py +197 -0
  191. graph_crawler-5.3.2/graph_crawler/domain/value_objects/__init__.py +88 -0
  192. graph_crawler-5.3.2/graph_crawler/domain/value_objects/configs.py +884 -0
  193. graph_crawler-5.3.2/graph_crawler/domain/value_objects/domain_patterns.py +71 -0
  194. graph_crawler-5.3.2/graph_crawler/domain/value_objects/fetch_options.py +57 -0
  195. graph_crawler-5.3.2/graph_crawler/domain/value_objects/html_document.py +59 -0
  196. graph_crawler-5.3.2/graph_crawler/domain/value_objects/lifecycle.py +30 -0
  197. graph_crawler-5.3.2/graph_crawler/domain/value_objects/models.py +1315 -0
  198. graph_crawler-5.3.2/graph_crawler/domain/value_objects/page_actions.py +72 -0
  199. graph_crawler-5.3.2/graph_crawler/domain/value_objects/redirect_hop.py +49 -0
  200. graph_crawler-5.3.2/graph_crawler/domain/value_objects/scheduling/__init__.py +23 -0
  201. graph_crawler-5.3.2/graph_crawler/domain/value_objects/scheduling/crawl_request.py +153 -0
  202. graph_crawler-5.3.2/graph_crawler/domain/value_objects/scheduling/retry_policy.py +109 -0
  203. graph_crawler-5.3.2/graph_crawler/domain/value_objects/settings.py +350 -0
  204. graph_crawler-5.3.2/graph_crawler/domain/value_objects/url_normalization.py +497 -0
  205. graph_crawler-5.3.2/graph_crawler/domain/value_objects/views.py +293 -0
  206. graph_crawler-5.3.2/graph_crawler/extensions/__init__.py +1 -0
  207. graph_crawler-5.3.2/graph_crawler/extensions/middleware/__init__.py +65 -0
  208. graph_crawler-5.3.2/graph_crawler/extensions/middleware/base.py +136 -0
  209. graph_crawler-5.3.2/graph_crawler/extensions/middleware/cache_middleware.py +277 -0
  210. graph_crawler-5.3.2/graph_crawler/extensions/middleware/chain.py +155 -0
  211. graph_crawler-5.3.2/graph_crawler/extensions/middleware/error_recovery_middleware.py +442 -0
  212. graph_crawler-5.3.2/graph_crawler/extensions/middleware/logging_middleware.py +108 -0
  213. graph_crawler-5.3.2/graph_crawler/extensions/middleware/proxy_health.py +141 -0
  214. graph_crawler-5.3.2/graph_crawler/extensions/middleware/proxy_middleware.py +209 -0
  215. graph_crawler-5.3.2/graph_crawler/extensions/middleware/proxy_models.py +80 -0
  216. graph_crawler-5.3.2/graph_crawler/extensions/middleware/proxy_selection.py +87 -0
  217. graph_crawler-5.3.2/graph_crawler/extensions/middleware/rate_limit_middleware.py +262 -0
  218. graph_crawler-5.3.2/graph_crawler/extensions/middleware/request_response_middleware.py +476 -0
  219. graph_crawler-5.3.2/graph_crawler/extensions/middleware/retry_middleware.py +279 -0
  220. graph_crawler-5.3.2/graph_crawler/extensions/middleware/robots_cache.py +85 -0
  221. graph_crawler-5.3.2/graph_crawler/extensions/middleware/robots_middleware.py +110 -0
  222. graph_crawler-5.3.2/graph_crawler/extensions/middleware/robots_validator.py +60 -0
  223. graph_crawler-5.3.2/graph_crawler/extensions/middleware/user_agent_middleware.py +251 -0
  224. graph_crawler-5.3.2/graph_crawler/extensions/plugins/__init__.py +57 -0
  225. graph_crawler-5.3.2/graph_crawler/extensions/plugins/builtin/__init__.py +7 -0
  226. graph_crawler-5.3.2/graph_crawler/extensions/plugins/builtin/stats_export_plugin.py +99 -0
  227. graph_crawler-5.3.2/graph_crawler/extensions/plugins/crawl_engine/__init__.py +24 -0
  228. graph_crawler-5.3.2/graph_crawler/extensions/plugins/crawl_engine/base.py +155 -0
  229. graph_crawler-5.3.2/graph_crawler/extensions/plugins/crawl_engine/priority_provider.py +247 -0
  230. graph_crawler-5.3.2/graph_crawler/extensions/plugins/crawl_engine/smart_crawl.py +296 -0
  231. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/__init__.py +128 -0
  232. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/anti_bot_detection.py +55 -0
  233. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/anti_bot_playwright.py +88 -0
  234. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/anti_bot_scripts.py +136 -0
  235. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/anti_bot_stealth.py +177 -0
  236. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/base.py +121 -0
  237. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/captcha/__init__.py +22 -0
  238. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/captcha/detector.py +94 -0
  239. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/captcha/models.py +74 -0
  240. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/captcha/plugin.py +228 -0
  241. graph_crawler-5.3.2/graph_crawler/extensions/plugins/engine/captcha/services.py +389 -0
  242. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/__init__.py +86 -0
  243. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/base.py +520 -0
  244. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/__init__.py +15 -0
  245. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/base.py +82 -0
  246. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/goose3_extractor.py +80 -0
  247. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/newspaper_extractor.py +93 -0
  248. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/plugin.py +132 -0
  249. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/content_extractors/readability_extractor.py +91 -0
  250. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/defaults.py +32 -0
  251. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/extractors/__init__.py +30 -0
  252. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/extractors/email_extractor.py +146 -0
  253. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/extractors/phone_extractor.py +136 -0
  254. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/extractors/price_extractor.py +137 -0
  255. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/links.py +184 -0
  256. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/markdown_plugin.py +249 -0
  257. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/metadata.py +384 -0
  258. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/smart_page_finder.py +749 -0
  259. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/__init__.py +51 -0
  260. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/constants.py +27 -0
  261. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/exceptions.py +18 -0
  262. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/extractor.py +361 -0
  263. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/options.py +62 -0
  264. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/__init__.py +25 -0
  265. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/base.py +43 -0
  266. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/jsonld.py +331 -0
  267. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/microdata.py +117 -0
  268. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/opengraph.py +66 -0
  269. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/rdfa.py +122 -0
  270. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/parsers/twitter.py +66 -0
  271. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/plugin.py +132 -0
  272. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/structured_data/result.py +233 -0
  273. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/text.py +76 -0
  274. graph_crawler-5.3.2/graph_crawler/extensions/plugins/node/url_normalizer.py +363 -0
  275. graph_crawler-5.3.2/graph_crawler/extensions/plugins/registry.py +97 -0
  276. graph_crawler-5.3.2/graph_crawler/infrastructure/__init__.py +1 -0
  277. graph_crawler-5.3.2/graph_crawler/infrastructure/adapters/__init__.py +60 -0
  278. graph_crawler-5.3.2/graph_crawler/infrastructure/adapters/base.py +498 -0
  279. graph_crawler-5.3.2/graph_crawler/infrastructure/adapters/selectolax_adapter.py +233 -0
  280. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/__init__.py +37 -0
  281. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/celery_app.py +202 -0
  282. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/celery_batch.py +284 -0
  283. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/celery_job_task.py +415 -0
  284. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/celery_unified.py +419 -0
  285. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/config.py +201 -0
  286. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/easy_crawler.py +279 -0
  287. graph_crawler-5.3.2/graph_crawler/infrastructure/messaging/worker_api.py +607 -0
  288. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/__init__.py +135 -0
  289. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/auto_storage.py +336 -0
  290. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/base.py +111 -0
  291. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/eviction.py +100 -0
  292. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/graph_repository.py +401 -0
  293. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/json/__init__.py +10 -0
  294. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/json_storage.py +375 -0
  295. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/lmdb_eviction_storage.py +401 -0
  296. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/memory/__init__.py +1 -0
  297. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/memory_dedup_store.py +90 -0
  298. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/memory_frontier.py +180 -0
  299. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/memory_politeness_store.py +88 -0
  300. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/memory_storage.py +166 -0
  301. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/mongodb_storage.py +383 -0
  302. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/naming_strategy.py +174 -0
  303. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/postgresql_storage.py +449 -0
  304. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/protocols/__init__.py +1 -0
  305. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/redis_dedup_store.py +119 -0
  306. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/redis_politeness_store.py +122 -0
  307. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/repository.py +130 -0
  308. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/sqlite/__init__.py +10 -0
  309. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/sqlite_eviction_storage.py +918 -0
  310. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/sqlite_storage.py +775 -0
  311. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/__init__.py +47 -0
  312. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/file_job_storage.py +245 -0
  313. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/file_queue_storage.py +248 -0
  314. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/memory_job_storage.py +94 -0
  315. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/memory_queue_storage.py +117 -0
  316. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/postgresql_job_storage.py +317 -0
  317. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/postgresql_queue_storage.py +364 -0
  318. graph_crawler-5.3.2/graph_crawler/infrastructure/persistence/unified/unified_storage.py +244 -0
  319. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/__init__.py +135 -0
  320. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/__init__.py +38 -0
  321. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/config.py +47 -0
  322. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/context.py +55 -0
  323. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/driver.py +724 -0
  324. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/driver_curl_cffi.py +407 -0
  325. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/__init__.py +48 -0
  326. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle.py +484 -0
  327. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle_adaptive.py +1435 -0
  328. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/headers.py +69 -0
  329. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/http_cache.py +321 -0
  330. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/rate_limiter.py +96 -0
  331. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/plugins/retry.py +316 -0
  332. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/async_http/stages.py +33 -0
  333. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/base.py +324 -0
  334. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/base_plugin.py +151 -0
  335. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/compression/__init__.py +23 -0
  336. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/compression/strategy.py +219 -0
  337. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/connection_pool.py +349 -0
  338. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/context.py +114 -0
  339. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/core/__init__.py +15 -0
  340. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/core/base_async.py +378 -0
  341. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/core/body_decoder.py +26 -0
  342. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/core/mixins.py +258 -0
  343. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/core/redirect_utils.py +168 -0
  344. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/escalation.py +950 -0
  345. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/factory.py +210 -0
  346. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/__init__.py +19 -0
  347. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/adaptive_semaphore.py +65 -0
  348. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/batch_scheduler.py +764 -0
  349. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/browser_factory.py +580 -0
  350. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/browser_profile.py +718 -0
  351. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/config.py +84 -0
  352. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/context.py +46 -0
  353. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/driver.py +80 -0
  354. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/engine.py +480 -0
  355. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/fetch_metrics.py +115 -0
  356. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/net/__init__.py +41 -0
  357. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/net/geoip.py +136 -0
  358. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/net/proxy_pool.py +225 -0
  359. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/net/rate_limiter.py +139 -0
  360. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/page_actions.py +186 -0
  361. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/page_fetch.py +968 -0
  362. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/__init__.py +71 -0
  363. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/_network_record.py +66 -0
  364. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/captcha_detector.py +315 -0
  365. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/captcha_solver.py +108 -0
  366. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/cookie_consent.py +565 -0
  367. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/form_filler.py +177 -0
  368. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/human_bezier.py +297 -0
  369. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/network_log.py +406 -0
  370. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/ram_adaptive.py +208 -0
  371. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/screenshot.py +169 -0
  372. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/plugins/user_profile.py +556 -0
  373. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/pool_lifecycle.py +658 -0
  374. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/pooled_driver.py +704 -0
  375. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/stages.py +35 -0
  376. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/playwright/stealth_hints.py +153 -0
  377. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/plugin_manager.py +316 -0
  378. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/protocols.py +118 -0
  379. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/undetected/__init__.py +8 -0
  380. graph_crawler-5.3.2/graph_crawler/infrastructure/transport/undetected/async_driver.py +465 -0
  381. graph_crawler-5.3.2/graph_crawler/native/__init__.py +199 -0
  382. graph_crawler-5.3.2/graph_crawler/native/bloom_filter.pyx +255 -0
  383. graph_crawler-5.3.2/graph_crawler/native/html_parser.pyx +262 -0
  384. graph_crawler-5.3.2/graph_crawler/native/setup.py +103 -0
  385. graph_crawler-5.3.2/graph_crawler/native/url_utils.pyx +209 -0
  386. graph_crawler-5.3.2/graph_crawler/observability/__init__.py +62 -0
  387. graph_crawler-5.3.2/graph_crawler/observability/decorators/__init__.py +11 -0
  388. graph_crawler-5.3.2/graph_crawler/observability/decorators/cache.py +126 -0
  389. graph_crawler-5.3.2/graph_crawler/observability/decorators/log.py +56 -0
  390. graph_crawler-5.3.2/graph_crawler/observability/decorators/retry.py +121 -0
  391. graph_crawler-5.3.2/graph_crawler/observability/decorators/timing.py +43 -0
  392. graph_crawler-5.3.2/graph_crawler/observability/error_tracing.py +361 -0
  393. graph_crawler-5.3.2/graph_crawler/observability/extensions/__init__.py +18 -0
  394. graph_crawler-5.3.2/graph_crawler/observability/extensions/memory_guard.py +237 -0
  395. graph_crawler-5.3.2/graph_crawler/observability/extensions/state_manager.py +319 -0
  396. graph_crawler-5.3.2/graph_crawler/observability/listeners/__init__.py +33 -0
  397. graph_crawler-5.3.2/graph_crawler/observability/listeners/base.py +82 -0
  398. graph_crawler-5.3.2/graph_crawler/observability/listeners/base_metrics_listener.py +18 -0
  399. graph_crawler-5.3.2/graph_crawler/observability/listeners/crawl_listener.py +28 -0
  400. graph_crawler-5.3.2/graph_crawler/observability/listeners/dlq_listener.py +215 -0
  401. graph_crawler-5.3.2/graph_crawler/observability/listeners/error_listener.py +18 -0
  402. graph_crawler-5.3.2/graph_crawler/observability/listeners/logging_listener.py +88 -0
  403. graph_crawler-5.3.2/graph_crawler/observability/listeners/metrics_listener.py +109 -0
  404. graph_crawler-5.3.2/graph_crawler/observability/listeners/node_listener.py +33 -0
  405. graph_crawler-5.3.2/graph_crawler/observability/listeners/plugin_listener.py +28 -0
  406. graph_crawler-5.3.2/graph_crawler/observability/listeners/storage_listener.py +21 -0
  407. graph_crawler-5.3.2/graph_crawler/observability/listeners/url_listener.py +29 -0
  408. graph_crawler-5.3.2/graph_crawler/observability/metrics/__init__.py +23 -0
  409. graph_crawler-5.3.2/graph_crawler/observability/metrics/memory_profiler.py +508 -0
  410. graph_crawler-5.3.2/graph_crawler/observability/metrics/metrics_collector.py +408 -0
  411. graph_crawler-5.3.2/graph_crawler/observability/metrics/prometheus_metrics.py +293 -0
  412. graph_crawler-5.3.2/graph_crawler/observability/metrics_core.py +389 -0
  413. graph_crawler-5.3.2/graph_crawler/observability/structured_logging.py +216 -0
  414. graph_crawler-5.3.2/graph_crawler/observability/tracing.py +291 -0
  415. graph_crawler-5.3.2/graph_crawler/optimizations/__init__.py +89 -0
  416. graph_crawler-5.3.2/graph_crawler/optimizations/generators.py +477 -0
  417. graph_crawler-5.3.2/graph_crawler/optimizations/memory_slots.py +641 -0
  418. graph_crawler-5.3.2/graph_crawler/optimizations/simhash_numba.py +284 -0
  419. graph_crawler-5.3.2/graph_crawler/py.typed +0 -0
  420. graph_crawler-5.3.2/graph_crawler/shared/__init__.py +25 -0
  421. graph_crawler-5.3.2/graph_crawler/shared/constants.py +938 -0
  422. graph_crawler-5.3.2/graph_crawler/shared/dto/__init__.py +38 -0
  423. graph_crawler-5.3.2/graph_crawler/shared/dto/edge_dto.py +52 -0
  424. graph_crawler-5.3.2/graph_crawler/shared/dto/graph_dto.py +97 -0
  425. graph_crawler-5.3.2/graph_crawler/shared/dto/node_dto.py +193 -0
  426. graph_crawler-5.3.2/graph_crawler/shared/error_handling/__init__.py +15 -0
  427. graph_crawler-5.3.2/graph_crawler/shared/error_handling/error_handler.py +333 -0
  428. graph_crawler-5.3.2/graph_crawler/shared/exceptions.py +394 -0
  429. graph_crawler-5.3.2/graph_crawler/shared/platform/__init__.py +125 -0
  430. graph_crawler-5.3.2/graph_crawler/shared/platform/adaptive_resolver.py +414 -0
  431. graph_crawler-5.3.2/graph_crawler/shared/platform/config.py +635 -0
  432. graph_crawler-5.3.2/graph_crawler/shared/platform/detector.py +334 -0
  433. graph_crawler-5.3.2/graph_crawler/shared/platform/diagnostics.py +660 -0
  434. graph_crawler-5.3.2/graph_crawler/shared/platform/metrics.py +299 -0
  435. graph_crawler-5.3.2/graph_crawler/shared/security/__init__.py +22 -0
  436. graph_crawler-5.3.2/graph_crawler/shared/security/url_sanitizer.py +100 -0
  437. graph_crawler-5.3.2/graph_crawler/shared/security/url_validator.py +299 -0
  438. graph_crawler-5.3.2/graph_crawler/shared/utils/__init__.py +212 -0
  439. graph_crawler-5.3.2/graph_crawler/shared/utils/async_compat.py +140 -0
  440. graph_crawler-5.3.2/graph_crawler/shared/utils/bloom_filter.py +373 -0
  441. graph_crawler-5.3.2/graph_crawler/shared/utils/captcha/__init__.py +36 -0
  442. graph_crawler-5.3.2/graph_crawler/shared/utils/captcha/base.py +92 -0
  443. graph_crawler-5.3.2/graph_crawler/shared/utils/captcha/manager.py +474 -0
  444. graph_crawler-5.3.2/graph_crawler/shared/utils/celery_config.py +332 -0
  445. graph_crawler-5.3.2/graph_crawler/shared/utils/celery_helpers.py +153 -0
  446. graph_crawler-5.3.2/graph_crawler/shared/utils/cgroup_limits.py +227 -0
  447. graph_crawler-5.3.2/graph_crawler/shared/utils/content_decoder.py +150 -0
  448. graph_crawler-5.3.2/graph_crawler/shared/utils/distributed_rate_limiter.py +265 -0
  449. graph_crawler-5.3.2/graph_crawler/shared/utils/distributed_rate_limiter_backends.py +284 -0
  450. graph_crawler-5.3.2/graph_crawler/shared/utils/dns_cache.py +370 -0
  451. graph_crawler-5.3.2/graph_crawler/shared/utils/enterprise_ua_generator.py +294 -0
  452. graph_crawler-5.3.2/graph_crawler/shared/utils/event_publisher_mixin.py +187 -0
  453. graph_crawler-5.3.2/graph_crawler/shared/utils/fast_json.py +240 -0
  454. graph_crawler-5.3.2/graph_crawler/shared/utils/fingerprint.py +36 -0
  455. graph_crawler-5.3.2/graph_crawler/shared/utils/fingerprint_data.py +99 -0
  456. graph_crawler-5.3.2/graph_crawler/shared/utils/fingerprint_generators.py +128 -0
  457. graph_crawler-5.3.2/graph_crawler/shared/utils/fingerprint_profile.py +121 -0
  458. graph_crawler-5.3.2/graph_crawler/shared/utils/fingerprint_stealth.py +105 -0
  459. graph_crawler-5.3.2/graph_crawler/shared/utils/html_utils.py +118 -0
  460. graph_crawler-5.3.2/graph_crawler/shared/utils/id_generator.py +195 -0
  461. graph_crawler-5.3.2/graph_crawler/shared/utils/memory_optimizer.py +536 -0
  462. graph_crawler-5.3.2/graph_crawler/shared/utils/rate_limiter.py +185 -0
  463. graph_crawler-5.3.2/graph_crawler/shared/utils/regex_validator.py +966 -0
  464. graph_crawler-5.3.2/graph_crawler/shared/utils/shadow_dom.py +36 -0
  465. graph_crawler-5.3.2/graph_crawler/shared/utils/text_utils.py +387 -0
  466. graph_crawler-5.3.2/graph_crawler/shared/utils/url_patterns.py +135 -0
  467. graph_crawler-5.3.2/graph_crawler/shared/utils/url_utils.py +595 -0
  468. graph_crawler-5.3.2/graph_crawler/shared/utils/user_agent_rotator.py +333 -0
  469. graph_crawler-5.3.2/graph_crawler/shared/utils/validation_helpers.py +225 -0
  470. graph_crawler-5.3.2/graph_crawler/shared/utils/visualization.py +134 -0
  471. graph_crawler-5.3.2/graph_crawler/shared/utils/visualization_core.py +566 -0
  472. graph_crawler-5.3.2/graph_crawler/tools/__init__.py +1 -0
  473. graph_crawler-5.3.2/graph_crawler/tools/db_cleanup.py +263 -0
  474. graph_crawler-5.3.2/graph_crawler.egg-info/PKG-INFO +531 -0
  475. graph_crawler-5.3.2/graph_crawler.egg-info/SOURCES.txt +479 -0
  476. graph_crawler-5.3.2/pyproject.toml +301 -0
  477. graph_crawler-5.3.2/setup.cfg +4 -0
  478. graph_crawler-5.2.1/CHANGELOG.md +0 -244
  479. graph_crawler-5.2.1/CODE_STYLE.md +0 -1473
  480. graph_crawler-5.2.1/LICENSE +0 -21
  481. graph_crawler-5.2.1/MANIFEST.in +0 -19
  482. graph_crawler-5.2.1/PKG-INFO +0 -370
  483. graph_crawler-5.2.1/README.md +0 -249
  484. graph_crawler-5.2.1/graph_crawler/__init__.py +0 -478
  485. graph_crawler-5.2.1/graph_crawler/__version__.py +0 -7
  486. graph_crawler-5.2.1/graph_crawler/ai/__init__.py +0 -49
  487. graph_crawler-5.2.1/graph_crawler/api/__init__.py +0 -24
  488. graph_crawler-5.2.1/graph_crawler/api/_core.py +0 -281
  489. graph_crawler-5.2.1/graph_crawler/api/_distributed.py +0 -174
  490. graph_crawler-5.2.1/graph_crawler/api/_shared.py +0 -120
  491. graph_crawler-5.2.1/graph_crawler/api/_sitemap_distributed.py +0 -244
  492. graph_crawler-5.2.1/graph_crawler/api/async_.py +0 -325
  493. graph_crawler-5.2.1/graph_crawler/api/cli.py +0 -440
  494. graph_crawler-5.2.1/graph_crawler/api/client/__init__.py +0 -8
  495. graph_crawler-5.2.1/graph_crawler/api/client/client.py +0 -498
  496. graph_crawler-5.2.1/graph_crawler/api/history_manager.py +0 -82
  497. graph_crawler-5.2.1/graph_crawler/api/project_init.py +0 -194
  498. graph_crawler-5.2.1/graph_crawler/api/server/__init__.py +0 -18
  499. graph_crawler-5.2.1/graph_crawler/api/server/crawl_monitor.py +0 -145
  500. graph_crawler-5.2.1/graph_crawler/api/server/dashboard.py +0 -221
  501. graph_crawler-5.2.1/graph_crawler/api/server/rest_api.py +0 -704
  502. graph_crawler-5.2.1/graph_crawler/api/server/webhooks.py +0 -421
  503. graph_crawler-5.2.1/graph_crawler/api/server/websocket_manager.py +0 -89
  504. graph_crawler-5.2.1/graph_crawler/api/stats_collector.py +0 -115
  505. graph_crawler-5.2.1/graph_crawler/api/sync.py +0 -491
  506. graph_crawler-5.2.1/graph_crawler/application/__init__.py +0 -38
  507. graph_crawler-5.2.1/graph_crawler/application/bootstrap.py +0 -209
  508. graph_crawler-5.2.1/graph_crawler/application/context/__init__.py +0 -31
  509. graph_crawler-5.2.1/graph_crawler/application/context/dependency_registry.py +0 -354
  510. graph_crawler-5.2.1/graph_crawler/application/context/graph_context.py +0 -217
  511. graph_crawler-5.2.1/graph_crawler/application/context/merge_context.py +0 -221
  512. graph_crawler-5.2.1/graph_crawler/application/dto/__init__.py +0 -67
  513. graph_crawler-5.2.1/graph_crawler/application/dto/edge_dto.py +0 -25
  514. graph_crawler-5.2.1/graph_crawler/application/dto/graph_dto.py +0 -27
  515. graph_crawler-5.2.1/graph_crawler/application/dto/mappers/__init__.py +0 -14
  516. graph_crawler-5.2.1/graph_crawler/application/dto/mappers/edge_mapper.py +0 -149
  517. graph_crawler-5.2.1/graph_crawler/application/dto/mappers/graph_mapper.py +0 -614
  518. graph_crawler-5.2.1/graph_crawler/application/dto/mappers/node_data_codec.py +0 -190
  519. graph_crawler-5.2.1/graph_crawler/application/dto/mappers/node_mapper.py +0 -387
  520. graph_crawler-5.2.1/graph_crawler/application/dto/node_dto.py +0 -27
  521. graph_crawler-5.2.1/graph_crawler/application/dto/utils.py +0 -272
  522. graph_crawler-5.2.1/graph_crawler/application/services/__init__.py +0 -60
  523. graph_crawler-5.2.1/graph_crawler/application/services/application_container.py +0 -208
  524. graph_crawler-5.2.1/graph_crawler/application/services/driver_factory.py +0 -147
  525. graph_crawler-5.2.1/graph_crawler/application/services/exporters/__init__.py +0 -26
  526. graph_crawler-5.2.1/graph_crawler/application/services/exporters/base_exporter.py +0 -150
  527. graph_crawler-5.2.1/graph_crawler/application/services/exporters/csv_exporter.py +0 -318
  528. graph_crawler-5.2.1/graph_crawler/application/services/exporters/edge_exporter.py +0 -432
  529. graph_crawler-5.2.1/graph_crawler/application/services/exporters/excel_exporter.py +0 -301
  530. graph_crawler-5.2.1/graph_crawler/application/services/exporters/jsonl_exporter.py +0 -290
  531. graph_crawler-5.2.1/graph_crawler/application/services/exporters/node_exporter.py +0 -283
  532. graph_crawler-5.2.1/graph_crawler/application/services/exporters/parquet_exporter.py +0 -248
  533. graph_crawler-5.2.1/graph_crawler/application/services/exporters/sql_exporter.py +0 -267
  534. graph_crawler-5.2.1/graph_crawler/application/services/finalize.py +0 -115
  535. graph_crawler-5.2.1/graph_crawler/application/services/low_memory_graph_saver.py +0 -339
  536. graph_crawler-5.2.1/graph_crawler/application/services/resource_budget.py +0 -179
  537. graph_crawler-5.2.1/graph_crawler/application/services/scheduling/__init__.py +0 -12
  538. graph_crawler-5.2.1/graph_crawler/application/services/scheduling/rule_based_scheduler.py +0 -113
  539. graph_crawler-5.2.1/graph_crawler/application/services/storage_factory.py +0 -195
  540. graph_crawler-5.2.1/graph_crawler/application/use_cases/__init__.py +0 -11
  541. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/__init__.py +0 -81
  542. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/adaptive_throttler.py +0 -374
  543. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/async_bridge.py +0 -45
  544. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/base_spider.py +0 -156
  545. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/celery_batch_spider.py +0 -658
  546. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/celery_spider.py +0 -448
  547. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/checkpoint.py +0 -421
  548. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/crawl_coordinator.py +0 -1044
  549. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/dead_letter_queue.py +0 -413
  550. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/domain_rate_limiter.py +0 -262
  551. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/filters/__init__.py +0 -10
  552. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/filters/base.py +0 -74
  553. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/filters/domain_filter.py +0 -195
  554. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/filters/domain_patterns.py +0 -30
  555. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/filters/path_filter.py +0 -95
  556. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/incremental_strategy.py +0 -239
  557. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/link_processor.py +0 -908
  558. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/multiprocess_spider.py +0 -511
  559. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/node_scanner.py +0 -808
  560. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/parsers/__init__.py +0 -6
  561. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/parsers/base.py +0 -73
  562. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/parsers/html_parser.py +0 -154
  563. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/progress_tracker.py +0 -235
  564. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/scheduler.py +0 -747
  565. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/serialization_mixin.py +0 -218
  566. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/sitemap_parser.py +0 -662
  567. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/sitemap_processor.py +0 -401
  568. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/sitemap_spider.py +0 -608
  569. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/spider.py +0 -811
  570. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/spider_lifecycle.py +0 -108
  571. graph_crawler-5.2.1/graph_crawler/application/use_cases/crawling/worker_pool.py +0 -154
  572. graph_crawler-5.2.1/graph_crawler/application/use_cases/graph_export.py +0 -504
  573. graph_crawler-5.2.1/graph_crawler/application/use_cases/graph_merge/__init__.py +0 -33
  574. graph_crawler-5.2.1/graph_crawler/application/use_cases/graph_merge/graph_operations.py +0 -632
  575. graph_crawler-5.2.1/graph_crawler/application/use_cases/graph_merge/merge_strategies.py +0 -348
  576. graph_crawler-5.2.1/graph_crawler/data/__init__.py +0 -28
  577. graph_crawler-5.2.1/graph_crawler/data/backends/__init__.py +0 -21
  578. graph_crawler-5.2.1/graph_crawler/data/backends/memory.py +0 -486
  579. graph_crawler-5.2.1/graph_crawler/data/backends/sqlite.py +0 -1866
  580. graph_crawler-5.2.1/graph_crawler/data/interfaces.py +0 -575
  581. graph_crawler-5.2.1/graph_crawler/domain/__init__.py +0 -62
  582. graph_crawler-5.2.1/graph_crawler/domain/context/__init__.py +0 -14
  583. graph_crawler-5.2.1/graph_crawler/domain/context/crawl_context.py +0 -531
  584. graph_crawler-5.2.1/graph_crawler/domain/entities/__init__.py +0 -32
  585. graph_crawler-5.2.1/graph_crawler/domain/entities/edge.py +0 -345
  586. graph_crawler-5.2.1/graph_crawler/domain/entities/edge_analysis.py +0 -223
  587. graph_crawler-5.2.1/graph_crawler/domain/entities/graph.py +0 -4120
  588. graph_crawler-5.2.1/graph_crawler/domain/entities/graph_operations.py +0 -33
  589. graph_crawler-5.2.1/graph_crawler/domain/entities/graph_statistics.py +0 -13
  590. graph_crawler-5.2.1/graph_crawler/domain/entities/merge_strategies.py +0 -36
  591. graph_crawler-5.2.1/graph_crawler/domain/entities/node.py +0 -692
  592. graph_crawler-5.2.1/graph_crawler/domain/entities/redirect_mode.py +0 -23
  593. graph_crawler-5.2.1/graph_crawler/domain/entities/registries.py +0 -237
  594. graph_crawler-5.2.1/graph_crawler/domain/entities/sitemap_node.py +0 -74
  595. graph_crawler-5.2.1/graph_crawler/domain/entities/strategies.py +0 -202
  596. graph_crawler-5.2.1/graph_crawler/domain/events/__init__.py +0 -163
  597. graph_crawler-5.2.1/graph_crawler/domain/events/base.py +0 -58
  598. graph_crawler-5.2.1/graph_crawler/domain/events/crawl.py +0 -123
  599. graph_crawler-5.2.1/graph_crawler/domain/events/edge.py +0 -46
  600. graph_crawler-5.2.1/graph_crawler/domain/events/event_bus.py +0 -251
  601. graph_crawler-5.2.1/graph_crawler/domain/events/events.py +0 -313
  602. graph_crawler-5.2.1/graph_crawler/domain/events/fetch.py +0 -123
  603. graph_crawler-5.2.1/graph_crawler/domain/events/idempotent_subscriber.py +0 -120
  604. graph_crawler-5.2.1/graph_crawler/domain/events/legacy_type_map.py +0 -45
  605. graph_crawler-5.2.1/graph_crawler/domain/events/llm.py +0 -158
  606. graph_crawler-5.2.1/graph_crawler/domain/events/node.py +0 -124
  607. graph_crawler-5.2.1/graph_crawler/domain/events/plugin.py +0 -96
  608. graph_crawler-5.2.1/graph_crawler/domain/events/scheduler.py +0 -102
  609. graph_crawler-5.2.1/graph_crawler/domain/events/storage.py +0 -168
  610. graph_crawler-5.2.1/graph_crawler/domain/interfaces/__init__.py +0 -111
  611. graph_crawler-5.2.1/graph_crawler/domain/interfaces/adapter.py +0 -29
  612. graph_crawler-5.2.1/graph_crawler/domain/interfaces/control_channel.py +0 -371
  613. graph_crawler-5.2.1/graph_crawler/domain/interfaces/crawl_context.py +0 -49
  614. graph_crawler-5.2.1/graph_crawler/domain/interfaces/distributed_spider.py +0 -63
  615. graph_crawler-5.2.1/graph_crawler/domain/interfaces/driver.py +0 -88
  616. graph_crawler-5.2.1/graph_crawler/domain/interfaces/event_bus.py +0 -61
  617. graph_crawler-5.2.1/graph_crawler/domain/interfaces/exporters.py +0 -83
  618. graph_crawler-5.2.1/graph_crawler/domain/interfaces/filter.py +0 -19
  619. graph_crawler-5.2.1/graph_crawler/domain/interfaces/merge_context.py +0 -58
  620. graph_crawler-5.2.1/graph_crawler/domain/interfaces/node_interfaces.py +0 -376
  621. graph_crawler-5.2.1/graph_crawler/domain/interfaces/parser.py +0 -110
  622. graph_crawler-5.2.1/graph_crawler/domain/interfaces/plugin_manager.py +0 -53
  623. graph_crawler-5.2.1/graph_crawler/domain/interfaces/processor.py +0 -11
  624. graph_crawler-5.2.1/graph_crawler/domain/interfaces/scanner.py +0 -57
  625. graph_crawler-5.2.1/graph_crawler/domain/interfaces/scheduler.py +0 -43
  626. graph_crawler-5.2.1/graph_crawler/domain/interfaces/scheduling/__init__.py +0 -40
  627. graph_crawler-5.2.1/graph_crawler/domain/interfaces/scheduling/frontier.py +0 -97
  628. graph_crawler-5.2.1/graph_crawler/domain/interfaces/scheduling/scheduler.py +0 -107
  629. graph_crawler-5.2.1/graph_crawler/domain/interfaces/spider.py +0 -63
  630. graph_crawler-5.2.1/graph_crawler/domain/interfaces/stop_condition.py +0 -211
  631. graph_crawler-5.2.1/graph_crawler/domain/interfaces/storage/__init__.py +0 -43
  632. graph_crawler-5.2.1/graph_crawler/domain/interfaces/storage/base.py +0 -70
  633. graph_crawler-5.2.1/graph_crawler/domain/interfaces/storage/eviction.py +0 -102
  634. graph_crawler-5.2.1/graph_crawler/domain/interfaces/storage/queue.py +0 -234
  635. graph_crawler-5.2.1/graph_crawler/domain/services/__init__.py +0 -216
  636. graph_crawler-5.2.1/graph_crawler/domain/services/adjacency_maintenance.py +0 -95
  637. graph_crawler-5.2.1/graph_crawler/domain/services/cycle_detection.py +0 -92
  638. graph_crawler-5.2.1/graph_crawler/domain/services/degree_ranking.py +0 -47
  639. graph_crawler-5.2.1/graph_crawler/domain/services/depth_context.py +0 -123
  640. graph_crawler-5.2.1/graph_crawler/domain/services/display_title.py +0 -47
  641. graph_crawler-5.2.1/graph_crawler/domain/services/duplicate_detection.py +0 -141
  642. graph_crawler-5.2.1/graph_crawler/domain/services/duplicate_selector.py +0 -127
  643. graph_crawler-5.2.1/graph_crawler/domain/services/duplicate_stats.py +0 -63
  644. graph_crawler-5.2.1/graph_crawler/domain/services/edge_filter.py +0 -82
  645. graph_crawler-5.2.1/graph_crawler/domain/services/edge_statistics.py +0 -110
  646. graph_crawler-5.2.1/graph_crawler/domain/services/eviction_policy.py +0 -83
  647. graph_crawler-5.2.1/graph_crawler/domain/services/graph_query_cascade.py +0 -178
  648. graph_crawler-5.2.1/graph_crawler/domain/services/graph_statistics.py +0 -186
  649. graph_crawler-5.2.1/graph_crawler/domain/services/graph_traversal.py +0 -150
  650. graph_crawler-5.2.1/graph_crawler/domain/services/language_versions.py +0 -73
  651. graph_crawler-5.2.1/graph_crawler/domain/services/lsh_index.py +0 -99
  652. graph_crawler-5.2.1/graph_crawler/domain/services/minimap_builder.py +0 -147
  653. graph_crawler-5.2.1/graph_crawler/domain/services/node_content_resolver.py +0 -128
  654. graph_crawler-5.2.1/graph_crawler/domain/services/node_view_builder.py +0 -163
  655. graph_crawler-5.2.1/graph_crawler/domain/services/pagination_guards.py +0 -136
  656. graph_crawler-5.2.1/graph_crawler/domain/services/predicate_ops.py +0 -77
  657. graph_crawler-5.2.1/graph_crawler/domain/services/schema_filter.py +0 -138
  658. graph_crawler-5.2.1/graph_crawler/domain/services/search_haystack.py +0 -102
  659. graph_crawler-5.2.1/graph_crawler/domain/services/simhash_clustering.py +0 -96
  660. graph_crawler-5.2.1/graph_crawler/domain/services/simhash_fallback.py +0 -59
  661. graph_crawler-5.2.1/graph_crawler/domain/services/similarity_ranking.py +0 -62
  662. graph_crawler-5.2.1/graph_crawler/domain/services/text_search.py +0 -157
  663. graph_crawler-5.2.1/graph_crawler/domain/services/url_clustering.py +0 -88
  664. graph_crawler-5.2.1/graph_crawler/domain/services/url_deduplication.py +0 -101
  665. graph_crawler-5.2.1/graph_crawler/domain/services/url_normalizer.py +0 -108
  666. graph_crawler-5.2.1/graph_crawler/domain/services/url_rule_matcher.py +0 -103
  667. graph_crawler-5.2.1/graph_crawler/domain/services/url_tree_builder.py +0 -197
  668. graph_crawler-5.2.1/graph_crawler/domain/value_objects/__init__.py +0 -88
  669. graph_crawler-5.2.1/graph_crawler/domain/value_objects/configs.py +0 -884
  670. graph_crawler-5.2.1/graph_crawler/domain/value_objects/domain_patterns.py +0 -71
  671. graph_crawler-5.2.1/graph_crawler/domain/value_objects/fetch_options.py +0 -57
  672. graph_crawler-5.2.1/graph_crawler/domain/value_objects/html_document.py +0 -59
  673. graph_crawler-5.2.1/graph_crawler/domain/value_objects/lifecycle.py +0 -30
  674. graph_crawler-5.2.1/graph_crawler/domain/value_objects/models.py +0 -1316
  675. graph_crawler-5.2.1/graph_crawler/domain/value_objects/redirect_hop.py +0 -49
  676. graph_crawler-5.2.1/graph_crawler/domain/value_objects/scheduling/__init__.py +0 -23
  677. graph_crawler-5.2.1/graph_crawler/domain/value_objects/scheduling/crawl_request.py +0 -153
  678. graph_crawler-5.2.1/graph_crawler/domain/value_objects/scheduling/retry_policy.py +0 -109
  679. graph_crawler-5.2.1/graph_crawler/domain/value_objects/settings.py +0 -350
  680. graph_crawler-5.2.1/graph_crawler/domain/value_objects/url_normalization.py +0 -496
  681. graph_crawler-5.2.1/graph_crawler/domain/value_objects/views.py +0 -293
  682. graph_crawler-5.2.1/graph_crawler/extensions/__init__.py +0 -1
  683. graph_crawler-5.2.1/graph_crawler/extensions/middleware/__init__.py +0 -65
  684. graph_crawler-5.2.1/graph_crawler/extensions/middleware/base.py +0 -147
  685. graph_crawler-5.2.1/graph_crawler/extensions/middleware/cache_middleware.py +0 -277
  686. graph_crawler-5.2.1/graph_crawler/extensions/middleware/chain.py +0 -159
  687. graph_crawler-5.2.1/graph_crawler/extensions/middleware/error_recovery_middleware.py +0 -442
  688. graph_crawler-5.2.1/graph_crawler/extensions/middleware/logging_middleware.py +0 -108
  689. graph_crawler-5.2.1/graph_crawler/extensions/middleware/proxy_health.py +0 -144
  690. graph_crawler-5.2.1/graph_crawler/extensions/middleware/proxy_middleware.py +0 -208
  691. graph_crawler-5.2.1/graph_crawler/extensions/middleware/proxy_models.py +0 -84
  692. graph_crawler-5.2.1/graph_crawler/extensions/middleware/proxy_selection.py +0 -87
  693. graph_crawler-5.2.1/graph_crawler/extensions/middleware/rate_limit_middleware.py +0 -262
  694. graph_crawler-5.2.1/graph_crawler/extensions/middleware/request_response_middleware.py +0 -476
  695. graph_crawler-5.2.1/graph_crawler/extensions/middleware/retry_middleware.py +0 -279
  696. graph_crawler-5.2.1/graph_crawler/extensions/middleware/robots_cache.py +0 -85
  697. graph_crawler-5.2.1/graph_crawler/extensions/middleware/robots_middleware.py +0 -110
  698. graph_crawler-5.2.1/graph_crawler/extensions/middleware/robots_validator.py +0 -60
  699. graph_crawler-5.2.1/graph_crawler/extensions/middleware/user_agent_middleware.py +0 -251
  700. graph_crawler-5.2.1/graph_crawler/extensions/plugins/__init__.py +0 -57
  701. graph_crawler-5.2.1/graph_crawler/extensions/plugins/builtin/__init__.py +0 -7
  702. graph_crawler-5.2.1/graph_crawler/extensions/plugins/builtin/stats_export_plugin.py +0 -98
  703. graph_crawler-5.2.1/graph_crawler/extensions/plugins/crawl_engine/__init__.py +0 -24
  704. graph_crawler-5.2.1/graph_crawler/extensions/plugins/crawl_engine/base.py +0 -155
  705. graph_crawler-5.2.1/graph_crawler/extensions/plugins/crawl_engine/priority_provider.py +0 -247
  706. graph_crawler-5.2.1/graph_crawler/extensions/plugins/crawl_engine/smart_crawl.py +0 -306
  707. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/__init__.py +0 -128
  708. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/anti_bot_detection.py +0 -52
  709. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/anti_bot_playwright.py +0 -85
  710. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/anti_bot_scripts.py +0 -133
  711. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/anti_bot_stealth.py +0 -177
  712. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/base.py +0 -121
  713. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/captcha/__init__.py +0 -22
  714. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/captcha/detector.py +0 -94
  715. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/captcha/models.py +0 -74
  716. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/captcha/plugin.py +0 -228
  717. graph_crawler-5.2.1/graph_crawler/extensions/plugins/engine/captcha/services.py +0 -389
  718. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/__init__.py +0 -86
  719. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/base.py +0 -432
  720. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/__init__.py +0 -15
  721. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/base.py +0 -82
  722. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/goose3_extractor.py +0 -80
  723. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/newspaper_extractor.py +0 -93
  724. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/plugin.py +0 -132
  725. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/content_extractors/readability_extractor.py +0 -91
  726. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/defaults.py +0 -32
  727. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/extractors/__init__.py +0 -30
  728. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/extractors/email_extractor.py +0 -146
  729. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/extractors/phone_extractor.py +0 -136
  730. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/extractors/price_extractor.py +0 -137
  731. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/links.py +0 -184
  732. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/markdown_plugin.py +0 -249
  733. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/metadata.py +0 -391
  734. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/smart_page_finder.py +0 -749
  735. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/__init__.py +0 -51
  736. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/constants.py +0 -27
  737. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/exceptions.py +0 -18
  738. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/extractor.py +0 -361
  739. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/options.py +0 -62
  740. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/__init__.py +0 -25
  741. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/base.py +0 -43
  742. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/jsonld.py +0 -331
  743. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/microdata.py +0 -117
  744. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/opengraph.py +0 -66
  745. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/rdfa.py +0 -122
  746. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/parsers/twitter.py +0 -66
  747. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/plugin.py +0 -132
  748. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/structured_data/result.py +0 -233
  749. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/text.py +0 -76
  750. graph_crawler-5.2.1/graph_crawler/extensions/plugins/node/url_normalizer.py +0 -363
  751. graph_crawler-5.2.1/graph_crawler/extensions/plugins/registry.py +0 -97
  752. graph_crawler-5.2.1/graph_crawler/infrastructure/__init__.py +0 -1
  753. graph_crawler-5.2.1/graph_crawler/infrastructure/adapters/__init__.py +0 -60
  754. graph_crawler-5.2.1/graph_crawler/infrastructure/adapters/base.py +0 -498
  755. graph_crawler-5.2.1/graph_crawler/infrastructure/adapters/selectolax_adapter.py +0 -234
  756. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/__init__.py +0 -37
  757. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/celery_app.py +0 -202
  758. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/celery_batch.py +0 -284
  759. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/celery_job_task.py +0 -415
  760. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/celery_unified.py +0 -419
  761. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/config.py +0 -201
  762. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/easy_crawler.py +0 -279
  763. graph_crawler-5.2.1/graph_crawler/infrastructure/messaging/worker_api.py +0 -607
  764. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/__init__.py +0 -135
  765. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/auto_storage.py +0 -336
  766. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/base.py +0 -111
  767. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/eviction.py +0 -100
  768. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/graph_repository.py +0 -401
  769. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/json/__init__.py +0 -10
  770. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/json_storage.py +0 -375
  771. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/lmdb_eviction_storage.py +0 -403
  772. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/memory/__init__.py +0 -1
  773. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/memory_dedup_store.py +0 -91
  774. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/memory_frontier.py +0 -180
  775. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/memory_politeness_store.py +0 -88
  776. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/memory_storage.py +0 -166
  777. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/mongodb_storage.py +0 -383
  778. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/naming_strategy.py +0 -174
  779. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/postgresql_storage.py +0 -449
  780. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/protocols/__init__.py +0 -1
  781. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/redis_dedup_store.py +0 -119
  782. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/redis_politeness_store.py +0 -122
  783. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/repository.py +0 -130
  784. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/sqlite/__init__.py +0 -10
  785. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/sqlite_eviction_storage.py +0 -918
  786. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/sqlite_storage.py +0 -775
  787. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/__init__.py +0 -47
  788. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/file_job_storage.py +0 -245
  789. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/file_queue_storage.py +0 -248
  790. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/memory_job_storage.py +0 -94
  791. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/memory_queue_storage.py +0 -117
  792. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/postgresql_job_storage.py +0 -317
  793. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/postgresql_queue_storage.py +0 -364
  794. graph_crawler-5.2.1/graph_crawler/infrastructure/persistence/unified/unified_storage.py +0 -244
  795. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/__init__.py +0 -135
  796. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/__init__.py +0 -38
  797. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/config.py +0 -47
  798. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/context.py +0 -55
  799. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/driver.py +0 -724
  800. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/driver_curl_cffi.py +0 -407
  801. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/__init__.py +0 -48
  802. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle.py +0 -484
  803. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle_adaptive.py +0 -1435
  804. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/headers.py +0 -69
  805. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/http_cache.py +0 -321
  806. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/rate_limiter.py +0 -96
  807. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/plugins/retry.py +0 -316
  808. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/async_http/stages.py +0 -33
  809. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/base.py +0 -324
  810. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/base_plugin.py +0 -151
  811. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/compression/__init__.py +0 -23
  812. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/compression/strategy.py +0 -219
  813. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/connection_pool.py +0 -349
  814. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/context.py +0 -114
  815. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/core/__init__.py +0 -15
  816. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/core/base_async.py +0 -378
  817. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/core/body_decoder.py +0 -26
  818. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/core/mixins.py +0 -258
  819. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/core/redirect_utils.py +0 -168
  820. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/escalation.py +0 -937
  821. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/factory.py +0 -210
  822. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/__init__.py +0 -19
  823. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/adaptive_semaphore.py +0 -65
  824. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/batch_scheduler.py +0 -764
  825. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/browser_factory.py +0 -576
  826. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/browser_profile.py +0 -718
  827. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/config.py +0 -84
  828. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/context.py +0 -46
  829. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/driver.py +0 -80
  830. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/engine.py +0 -465
  831. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/fetch_metrics.py +0 -115
  832. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/net/__init__.py +0 -41
  833. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/net/geoip.py +0 -136
  834. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/net/proxy_pool.py +0 -225
  835. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/net/rate_limiter.py +0 -139
  836. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/page_fetch.py +0 -896
  837. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/__init__.py +0 -71
  838. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/_network_record.py +0 -66
  839. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/captcha_detector.py +0 -315
  840. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/captcha_solver.py +0 -108
  841. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/cookie_consent.py +0 -565
  842. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/form_filler.py +0 -177
  843. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/human_bezier.py +0 -297
  844. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/network_log.py +0 -366
  845. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/ram_adaptive.py +0 -208
  846. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/screenshot.py +0 -169
  847. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/plugins/user_profile.py +0 -556
  848. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/pool_lifecycle.py +0 -658
  849. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/pooled_driver.py +0 -698
  850. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/stages.py +0 -35
  851. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/playwright/stealth_hints.py +0 -153
  852. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/plugin_manager.py +0 -316
  853. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/protocols.py +0 -118
  854. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/undetected/__init__.py +0 -8
  855. graph_crawler-5.2.1/graph_crawler/infrastructure/transport/undetected/async_driver.py +0 -465
  856. graph_crawler-5.2.1/graph_crawler/native/README.md +0 -110
  857. graph_crawler-5.2.1/graph_crawler/native/__init__.py +0 -200
  858. graph_crawler-5.2.1/graph_crawler/native/bloom_filter.pyx +0 -255
  859. graph_crawler-5.2.1/graph_crawler/native/html_parser.pyx +0 -262
  860. graph_crawler-5.2.1/graph_crawler/native/setup.py +0 -101
  861. graph_crawler-5.2.1/graph_crawler/native/url_utils.pyx +0 -209
  862. graph_crawler-5.2.1/graph_crawler/observability/__init__.py +0 -62
  863. graph_crawler-5.2.1/graph_crawler/observability/decorators/__init__.py +0 -11
  864. graph_crawler-5.2.1/graph_crawler/observability/decorators/cache.py +0 -126
  865. graph_crawler-5.2.1/graph_crawler/observability/decorators/log.py +0 -56
  866. graph_crawler-5.2.1/graph_crawler/observability/decorators/retry.py +0 -121
  867. graph_crawler-5.2.1/graph_crawler/observability/decorators/timing.py +0 -43
  868. graph_crawler-5.2.1/graph_crawler/observability/error_tracing.py +0 -363
  869. graph_crawler-5.2.1/graph_crawler/observability/extensions/__init__.py +0 -18
  870. graph_crawler-5.2.1/graph_crawler/observability/extensions/memory_guard.py +0 -237
  871. graph_crawler-5.2.1/graph_crawler/observability/extensions/state_manager.py +0 -319
  872. graph_crawler-5.2.1/graph_crawler/observability/listeners/__init__.py +0 -33
  873. graph_crawler-5.2.1/graph_crawler/observability/listeners/base.py +0 -82
  874. graph_crawler-5.2.1/graph_crawler/observability/listeners/base_metrics_listener.py +0 -18
  875. graph_crawler-5.2.1/graph_crawler/observability/listeners/crawl_listener.py +0 -28
  876. graph_crawler-5.2.1/graph_crawler/observability/listeners/dlq_listener.py +0 -215
  877. graph_crawler-5.2.1/graph_crawler/observability/listeners/error_listener.py +0 -18
  878. graph_crawler-5.2.1/graph_crawler/observability/listeners/logging_listener.py +0 -88
  879. graph_crawler-5.2.1/graph_crawler/observability/listeners/metrics_listener.py +0 -109
  880. graph_crawler-5.2.1/graph_crawler/observability/listeners/node_listener.py +0 -33
  881. graph_crawler-5.2.1/graph_crawler/observability/listeners/plugin_listener.py +0 -28
  882. graph_crawler-5.2.1/graph_crawler/observability/listeners/storage_listener.py +0 -21
  883. graph_crawler-5.2.1/graph_crawler/observability/listeners/url_listener.py +0 -29
  884. graph_crawler-5.2.1/graph_crawler/observability/metrics/__init__.py +0 -23
  885. graph_crawler-5.2.1/graph_crawler/observability/metrics/memory_profiler.py +0 -508
  886. graph_crawler-5.2.1/graph_crawler/observability/metrics/metrics_collector.py +0 -408
  887. graph_crawler-5.2.1/graph_crawler/observability/metrics/prometheus_metrics.py +0 -293
  888. graph_crawler-5.2.1/graph_crawler/observability/metrics_core.py +0 -395
  889. graph_crawler-5.2.1/graph_crawler/observability/structured_logging.py +0 -240
  890. graph_crawler-5.2.1/graph_crawler/observability/tracing.py +0 -291
  891. graph_crawler-5.2.1/graph_crawler/optimizations/__init__.py +0 -89
  892. graph_crawler-5.2.1/graph_crawler/optimizations/generators.py +0 -477
  893. graph_crawler-5.2.1/graph_crawler/optimizations/memory_slots.py +0 -641
  894. graph_crawler-5.2.1/graph_crawler/optimizations/simhash_numba.py +0 -284
  895. graph_crawler-5.2.1/graph_crawler/shared/__init__.py +0 -25
  896. graph_crawler-5.2.1/graph_crawler/shared/constants.py +0 -938
  897. graph_crawler-5.2.1/graph_crawler/shared/dto/__init__.py +0 -38
  898. graph_crawler-5.2.1/graph_crawler/shared/dto/edge_dto.py +0 -52
  899. graph_crawler-5.2.1/graph_crawler/shared/dto/graph_dto.py +0 -97
  900. graph_crawler-5.2.1/graph_crawler/shared/dto/node_dto.py +0 -193
  901. graph_crawler-5.2.1/graph_crawler/shared/error_handling/__init__.py +0 -15
  902. graph_crawler-5.2.1/graph_crawler/shared/error_handling/error_handler.py +0 -333
  903. graph_crawler-5.2.1/graph_crawler/shared/exceptions.py +0 -394
  904. graph_crawler-5.2.1/graph_crawler/shared/platform/__init__.py +0 -125
  905. graph_crawler-5.2.1/graph_crawler/shared/platform/adaptive_resolver.py +0 -414
  906. graph_crawler-5.2.1/graph_crawler/shared/platform/config.py +0 -635
  907. graph_crawler-5.2.1/graph_crawler/shared/platform/detector.py +0 -334
  908. graph_crawler-5.2.1/graph_crawler/shared/platform/diagnostics.py +0 -660
  909. graph_crawler-5.2.1/graph_crawler/shared/platform/metrics.py +0 -299
  910. graph_crawler-5.2.1/graph_crawler/shared/security/__init__.py +0 -22
  911. graph_crawler-5.2.1/graph_crawler/shared/security/url_sanitizer.py +0 -100
  912. graph_crawler-5.2.1/graph_crawler/shared/security/url_validator.py +0 -299
  913. graph_crawler-5.2.1/graph_crawler/shared/utils/__init__.py +0 -212
  914. graph_crawler-5.2.1/graph_crawler/shared/utils/async_compat.py +0 -140
  915. graph_crawler-5.2.1/graph_crawler/shared/utils/bloom_filter.py +0 -373
  916. graph_crawler-5.2.1/graph_crawler/shared/utils/captcha/__init__.py +0 -36
  917. graph_crawler-5.2.1/graph_crawler/shared/utils/captcha/base.py +0 -92
  918. graph_crawler-5.2.1/graph_crawler/shared/utils/captcha/manager.py +0 -474
  919. graph_crawler-5.2.1/graph_crawler/shared/utils/celery_config.py +0 -332
  920. graph_crawler-5.2.1/graph_crawler/shared/utils/celery_helpers.py +0 -153
  921. graph_crawler-5.2.1/graph_crawler/shared/utils/cgroup_limits.py +0 -227
  922. graph_crawler-5.2.1/graph_crawler/shared/utils/content_decoder.py +0 -150
  923. graph_crawler-5.2.1/graph_crawler/shared/utils/distributed_rate_limiter.py +0 -265
  924. graph_crawler-5.2.1/graph_crawler/shared/utils/distributed_rate_limiter_backends.py +0 -284
  925. graph_crawler-5.2.1/graph_crawler/shared/utils/dns_cache.py +0 -370
  926. graph_crawler-5.2.1/graph_crawler/shared/utils/enterprise_ua_generator.py +0 -294
  927. graph_crawler-5.2.1/graph_crawler/shared/utils/event_publisher_mixin.py +0 -188
  928. graph_crawler-5.2.1/graph_crawler/shared/utils/fast_json.py +0 -240
  929. graph_crawler-5.2.1/graph_crawler/shared/utils/fingerprint.py +0 -36
  930. graph_crawler-5.2.1/graph_crawler/shared/utils/fingerprint_data.py +0 -99
  931. graph_crawler-5.2.1/graph_crawler/shared/utils/fingerprint_generators.py +0 -128
  932. graph_crawler-5.2.1/graph_crawler/shared/utils/fingerprint_profile.py +0 -121
  933. graph_crawler-5.2.1/graph_crawler/shared/utils/fingerprint_stealth.py +0 -105
  934. graph_crawler-5.2.1/graph_crawler/shared/utils/html_utils.py +0 -118
  935. graph_crawler-5.2.1/graph_crawler/shared/utils/id_generator.py +0 -195
  936. graph_crawler-5.2.1/graph_crawler/shared/utils/memory_optimizer.py +0 -536
  937. graph_crawler-5.2.1/graph_crawler/shared/utils/rate_limiter.py +0 -185
  938. graph_crawler-5.2.1/graph_crawler/shared/utils/regex_validator.py +0 -966
  939. graph_crawler-5.2.1/graph_crawler/shared/utils/shadow_dom.py +0 -36
  940. graph_crawler-5.2.1/graph_crawler/shared/utils/text_utils.py +0 -387
  941. graph_crawler-5.2.1/graph_crawler/shared/utils/url_patterns.py +0 -135
  942. graph_crawler-5.2.1/graph_crawler/shared/utils/url_utils.py +0 -595
  943. graph_crawler-5.2.1/graph_crawler/shared/utils/user_agent_rotator.py +0 -333
  944. graph_crawler-5.2.1/graph_crawler/shared/utils/validation_helpers.py +0 -225
  945. graph_crawler-5.2.1/graph_crawler/shared/utils/visualization.py +0 -134
  946. graph_crawler-5.2.1/graph_crawler/shared/utils/visualization_core.py +0 -566
  947. graph_crawler-5.2.1/graph_crawler/tools/__init__.py +0 -1
  948. graph_crawler-5.2.1/graph_crawler/tools/db_cleanup.py +0 -263
  949. graph_crawler-5.2.1/graph_crawler.egg-info/PKG-INFO +0 -370
  950. graph_crawler-5.2.1/graph_crawler.egg-info/SOURCES.txt +0 -477
  951. graph_crawler-5.2.1/pyproject.toml +0 -301
  952. graph_crawler-5.2.1/setup.cfg +0 -4
  953. {graph_crawler-5.2.1 → graph_crawler-5.3.2}/graph_crawler.egg-info/dependency_links.txt +0 -0
  954. {graph_crawler-5.2.1 → graph_crawler-5.3.2}/graph_crawler.egg-info/entry_points.txt +0 -0
  955. {graph_crawler-5.2.1 → graph_crawler-5.3.2}/graph_crawler.egg-info/requires.txt +0 -0
  956. {graph_crawler-5.2.1 → graph_crawler-5.3.2}/graph_crawler.egg-info/top_level.txt +0 -0
@@ -0,0 +1,353 @@
1
+ # Changelog
2
+
3
+ ## 5.3.2 — 2026-06
4
+
5
+ ### Added
6
+
7
+ - **Fetch provenance on the node.** `Node.channel`, `bot_block_status`, `served_by_driver`, `served_by_engine`,
8
+ `escalations` and `fetch_info` read `metadata["fetch"]`; `Node.ok` (scanned, 2xx/3xx, not blocked, no error) and
9
+ `Node.is_blocked` separate useful pages from block and error pages.
10
+ - **Plugin routing.** `BaseNodePlugin.domains` (domain and subdomains) and `url_pattern` (regex), on the class or via
11
+ `config={"domains": [...], "url_pattern": ...}`, plus an overridable `applies_to(url)`. An invalid `url_pattern`
12
+ raises `ConfigurationError` on `register()`. Several instances of one plugin class with different routes run
13
+ side by side (they used to replace each other).
14
+ - **Typed plugin output.** `NodePluginContext.set_node_field(name, value)` writes a field declared by a `Node`
15
+ subclass, validated against its annotation (`"100"` → `int`); base fields are read-only. Fields are rolled back
16
+ together with `metadata`/`user_data` when the plugin fails.
17
+ - **Empty extraction warning.** `BaseNodePlugin.expects_nonempty` + `extraction_key`: a WARNING when the plugin left
18
+ `user_data[extraction_key]` empty.
19
+ - **`Graph.search(..., user_data_keys=("jobs",))`** searches the listed `user_data` keys as well.
20
+ - **`Node.public_user_data`** and `RESERVED_USER_DATA_KEYS` (`_link_anchors`, `_custom_fields`, `_node_class`).
21
+
22
+ ### Changed
23
+
24
+ - A response with status 400 or higher gets `metadata["error"] = "HTTP <code>"` and is logged as a WARNING
25
+ (`HTTP 404 for <url> — page not scanned`).
26
+ - A bare 403/401/405 without vendor markers is still classified as `none`; the decision is now logged at INFO.
27
+ - Quieter logs: import writes nothing at INFO, platform detection runs once, the start of a crawl is one line,
28
+ and each page is one INFO line with `[channel=…]`, `[block=…]`, `[error=…]`.
29
+ - The temporary `_link_anchors` map is removed from the node once its edges are created (the anchor text stays in
30
+ `edge.metadata["anchor_text"]`). The default JSON export writes `public_user_data`.
31
+ - A third-party plugin that overwrites a reserved `user_data` key gets a WARNING.
32
+
33
+ ### Fixed
34
+
35
+ - `load_graph()` without `node_class=` restores a custom `Node` subclass when its module is already imported (the
36
+ class name is stored with the node; nothing is imported from the file). `Graph.copy()`, `union`, `intersection`,
37
+ `difference` and nodes created in a loaded graph keep the node class.
38
+ - `metadata` written by a plugin on `ON_NODE_CREATED` or `ON_AFTER_SCAN` is no longer lost.
39
+ - **Placeholder lists are detected as a JavaScript shell.** A 2xx body with five or more `placeholder` /
40
+ `skeleton` / `shimmer` elements makes `needs_browser` true, so `escalating` goes straight to the browser tier.
41
+ With `driver="http"` the node gets `metadata["js_shell_suspected"]` and a WARNING (once per host) suggests
42
+ `driver="escalating"` or `"playwright"`.
43
+ - **No duplicate edges.** A link repeated on a page (menu + footer + body) created a new `Edge` each time
44
+ (17.5 % of edges on uk.wikipedia); `LinkProcessor` now skips existing `(source, target)` pairs. `Graph.has_edge`
45
+ also sees the backend edge index.
46
+ - **`h1` children are no longer joined with spaces** (`Портал : Поточні події` → `Портал:Поточні події`).
47
+ - **Default ports are normalized** (`http://x:80`, `https://x:443`, empty port).
48
+ - `Graph.normalize_url()` is public; `LinkProcessor` checks the scheduler with the canonical form as well.
49
+ - **`NetworkLogPlugin` waits for network quiet** before publishing the log (`settle_ms`=2000, `quiet_ms`=300;
50
+ `settle_ms=0` restores the old behaviour) — late XHR (search/listing after hydration) was lost.
51
+ - `create_trailing_slash_rule` keeps the root path; an empty path is `/` for PATH-scope rules.
52
+
53
+ ## 5.3.1 — 2026-06
54
+
55
+ ### Added
56
+
57
+ - **Hydration state globals snapshot.** The Playwright driver serialises `window.__NAME__` objects (`__NUXT__`,
58
+ `__APOLLO_STATE__`, `__INITIAL_STATE__`, `__PINIA__`, …) with `JSON.stringify` after the page has run and embeds
59
+ them into the HTML snapshot as `<script type="application/json" data-agc-state="__NAME__">`. Nuxt 2 ships its
60
+ state as an IIFE (`window.__NUXT__=(function(a,b){return {…}}(…))`) which is JavaScript, not JSON, and was
61
+ invisible to any static state parser. Globals that already exist as a JSON `<script id="__NAME__">`
62
+ (`__NEXT_DATA__`) are not duplicated; `PageFetcher.state_globals_max_chars` (5 MB) caps the snapshot.
63
+ `inject_state_globals(html, states)` is exported for tests and other drivers.
64
+
65
+ ## 5.3.0 — 2026-06
66
+
67
+ ### Added
68
+
69
+ - **Page actions as public API.** `driver_config={"actions": [PageAction(...) | dict, ...]}` for the Playwright driver:
70
+ `click` / `fill` / `select` / `press` / `wait_for(response=…|selector=…)` / `scroll`, target by `selector`, `text`,
71
+ `placeholder` or `label` (`nth` among visible matches). Actions are validated when the driver is created and run
72
+ after content is ready and before the HTML snapshot and `CONTENT_READY` hooks — the network log is published after
73
+ the actions. Results land in `node.metadata["actions_log"]`, `["requests_after_actions"]` and `["actions_error"]`
74
+ (the first failing action stops the chain with a reason). `from graph_crawler import PageAction`.
75
+ - `engine.page_error_types()` — page error classes of all installed browser SDKs.
76
+ - `PageAction(type="back")`; action errors name the element that intercepts pointer events.
77
+
78
+ ### Fixed
79
+
80
+ - Binary request bodies (gzip beacons) no longer raise `UnicodeDecodeError` inside Playwright event listeners
81
+ (`NetworkLogPlugin` and the action recorder read `post_data_buffer` with `errors="replace"`); the error used to break
82
+ the next Playwright call with `TypeError: function takes exactly 5 arguments`.
83
+
84
+ ### Fixed
85
+
86
+ - `graph.get_node_by_url(seed)` finds the node after a redirect in the graph returned by `async_crawl`: `add_node`
87
+ restores the alias from `metadata["was_redirected_from"]`.
88
+
89
+ ## 5.2.2 — 2026-06
90
+
91
+ ### Fixed (test infrastructure)
92
+
93
+ - **The library no longer configures logging.** `GraphCrawlerClient.__init__` called `logging.basicConfig(INFO)`
94
+ when its logger had no handlers, so every crawl printed to stderr and reconfigured the application's root
95
+ logger. Removed; `graph_crawler` gets a `NullHandler`.
96
+ - **Noise demoted:** `HTML executor shutdown` and `lmdb not installed … Falling back to SQLiteEvictionStorage` are
97
+ DEBUG; `channel='chrome' not installed, falling back to bundled Chromium` is a WARNING once per process.
98
+ - **One version source.** `graph_crawler.__version__` (and the default User-Agent) come from the installed
99
+ package metadata (`pyproject.toml`); `__version__.py` no longer hard-codes a number that drifted (5.1.0 vs 5.2.0).
100
+ - **Test suite collects without optional extras.** Tests that need `psutil`, `rapidfuzz`, `stop-words`,
101
+ `html2md-clean` or `playwright` are skipped via `importorskip` instead of failing collection under `-x`.
102
+ `test_div_inline_fix.py` / `test_phase1_fixes.py` tested `html2md_clean` itself (no `graph_crawler` code) and were
103
+ removed from the core suite.
104
+ - GitLab CI (`.gitlab-ci.yml`): offline suite with `[dev]` and a minimal job without extras.
105
+
106
+ ## 5.2.1 — 2026-06
107
+
108
+ ### Fixed (freelance cases)
109
+
110
+ - **Captured XHR/fetch traffic could not be replayed outside the browser.** `NetworkLogPlugin` recorded the
111
+ URL and method of a request but not its body, so every POST/GraphQL endpoint (robota.ua lists vacancies via
112
+ `POST dracula.robota.ua/?q=getPublishedVacanciesList`) was unusable: a GET of the same URL returns 400.
113
+ Records now carry `post_data` and (on `response`) `request_headers`.
114
+ - **GraphQL responses overwrote each other.** `body_ref` was `sha1(url|status|content-type)` — all operations
115
+ POSTed to one `/graphql` URL shared a key and only the last body survived. The key now includes method and
116
+ request body.
117
+ - **JSON family by default.** The capture allow-list matched exact MIME types only; `application/graphql-
118
+ response+json`, `problem+json`, `vnd.api+json`, `text/json` were dropped. Without an explicit
119
+ `capture_content_types` every `*/json` and `*+json` type is captured (RFC 6839). Default `max_body_kb` 64 → 256
120
+ (listing APIs routinely exceed 64 KB).
121
+ - **Shadow DOM was invisible.** `page.content()` serializes only light DOM: content of open shadow roots (web
122
+ components, embedded price widgets) never reached the node. When a page has open shadow roots, the browser
123
+ driver serializes it with `Element.getHTML({shadowRoots})` and expands the declarative shadow roots into their
124
+ hosts (`shared/utils/shadow_dom.expose_shadow_roots`) — Lexbor, like the HTML spec, does not descend into
125
+ `<template>` content, so a plain declarative-shadow-DOM serialization would still hide it from selectors and link
126
+ extraction. Pages without shadow roots are untouched.
127
+ - `tests/unit/domain/entities/test_graph_new_features.py` still expected the `DeprecationWarning` that
128
+ `export_nodes()` stopped emitting in 4aab7525; it now asserts the opposite.
129
+
130
+ ### Fixed (real-site tests)
131
+
132
+ - **Ctrl+C during `crawl()` hung until the crawl-level timeout** (28 s with `timeout=25`; forever without
133
+ one). `asyncio.wait_for` in Python 3.11 swallows the outer cancellation when the awaited coroutine finishes
134
+ at the same moment, so some workers survived `KeyboardInterrupt` and kept crawling. `NodeScanner` and the
135
+ escalation tier budget now use `asyncio.timeout()`; `CrawlCoordinator` cancels its workers on
136
+ `CancelledError`. Ctrl+C now returns in ~0.3 s.
137
+ - **`same_domain=False` was ignored** — without `allowed_domains` the `DomainFilter` default
138
+ (`domain+subdomains`) still applied and external links never entered the graph. Now maps to `allowed_domains=["*"]`.
139
+ - **`graph.metadata["stop_reason"]` was `None` after `timeout=` / `max_pages`** — only stop conditions were
140
+ recorded. Now `"timeout"`, `"max_pages"` or `"limit"`.
141
+ - **Network errors were invisible on the node**: a DNS/connection failure left `response_status=None`,
142
+ `scanned=True` and no message; `get_failed_nodes()` returned `[]`. The error text is now in
143
+ `node.metadata["error"]`, the HTTP status (if any) is kept, and `get_failed_nodes()` with default
144
+ arguments includes network-error nodes.
145
+ - **`storage="json", storage_config={"path": "site.json"}` was silently ignored** (file written to
146
+ `crawler_data/json/graph.json`). `path` is now honoured, like for sqlite (`JSONStorage(file_name=)`).
147
+ - `Graph.export_nodes()` / `Graph.export_edges()` are no longer deprecated: they are the public one-liners the
148
+ README shows and now delegate to `GraphExportUseCase` silently (no `DeprecationWarning`).
149
+ - `tests/manual/real_sites/run_all.py -j N` runs scenarios in parallel; `tests/manual/real_sites/test_user_cases.py`
150
+ — 23 pytest user scenarios on Wikipedia / robota.ua / GitHub / example.com, each hard-capped at 40 s.
151
+
152
+ ### Changed
153
+
154
+ - **Engine contract verified end-to-end**. `tests/transport/
155
+ test_engine_contract.py` drives the real `PlaywrightDriver.fetch()` through three engines registered via the
156
+ public `register_engine()` on a recording fake SDK: the call sequence is byte-for-byte identical across
157
+ engines, stealth is injected iff `provides_stealth is False`, and `executable_path`/`ignore_default_args`/
158
+ launch args come only from the engine. No runtime code changed.
159
+ - **`LexborDocument.clean_text()` no longer re-parses the page**. To strip `script/style/noscript/svg/head` without mutating the shared tree it
160
+ serialised the document and built a second `LexborHTMLParser` — i.e. every page with the default
161
+ `TextExtractorPlugin` was parsed twice (`count_parses.py`: 2.0 → **1.0** per page; with `MarkdownPlugin`
162
+ 1 parse + 1 clone). It now uses `tree.clone()`.
163
+ - **One `ContentDecoder` for every HTTP tier**. `AsyncDriver` (aiohttp) and `AsyncCurlCffiDriver` (curl_cffi) no longer rely on the client's own
164
+ `response.text`/`.text()`: they read the raw body and decode it through `ContentDecoder`
165
+ (`Content-Type` charset → `<meta charset>` → BOM → chardet → strict utf-8). Pages whose charset is only
166
+ declared in `<meta>` (e.g. windows-1251 without a header) were previously decoded as utf-8 by aiohttp,
167
+ failed, and silently became `html=None` with a "successful" 200. An undecodable body is now reported as
168
+ `FetchResponse.error` (`"ContentDecoder: cannot decode body …"`) with the status code preserved;
169
+ `ConnectionPoolManager.fetch_text()` goes through the same decoder. `FetchResponse.html` is a strict
170
+ `str` field — passing `bytes` raises `ValidationError` instead of being coerced. Browser tiers
171
+ (Playwright `page.content()`, nodriver `tab.get_content()`) already return `str`. Contract test:
172
+ `tests/transport/test_html_is_str_contract.py` (driver matrix returns `str`; cp1251 via meta/header;
173
+ binary → error).
174
+ - **Lazy public facade**. `graph_crawler/__init__.py` now
175
+ eagerly imports only `crawl`, `async_crawl`, `Graph`, `Node`, `save_graph`, `load_graph`,
176
+ `BaseStopCondition`; every other name in `__all__` (drivers, storages, exceptions, settings, views,
177
+ celery tasks, …) resolves on first access via module `__getattr__` and is cached. `aiohttp` is no longer
178
+ loaded by `import graph_crawler`. `bootstrap()` no longer calls `collect_system_metrics()`
179
+ (`psutil.cpu_percent(interval=0.1)` blocked import for 100 ms for a DEBUG line). Import time here:
180
+ 470 ms → 228 ms. Optional names (`PlaywrightDriver`, `celery`, `EasyDistributedCrawler`, …) still return
181
+ `None` without their extra.
182
+ - **Escalation re-probe replays the solving tier's User-Agent**.
183
+ Playwright and nodriver now export `navigator.userAgent` as `extras["user_agent"]`;
184
+ `SessionState.absorb` records it (pinned once the session is solved, like `impersonate`/`proxy`) and
185
+ `EscalatingDriver._fetch_tier` sends it as `extra_headers={"User-Agent": …}` to HTTP/TLS tiers together
186
+ with the stored cookies. `cf_clearance` is bound to UA+IP+JA4, so a re-probe on Tier 1 with aiohttp's
187
+ default UA was rejected and the host never descended from the browser tier.
188
+
189
+ ### Removed
190
+
191
+ - **`NodePluginContext.parser`**. Node plugins now read the
192
+ single Lexbor tree through the `HTMLDocument`/`HTMLNode` protocols: `LinkExtractorPlugin`
193
+ (`doc.css("a[href]")`, `doc.base_href()`), `MetadataExtractorPlugin`, `TextExtractorPlugin`
194
+ (`doc.clean_text()`, new in the protocol), `StructuredDataPlugin` (OG/Twitter/Microdata/RDFa parsers take
195
+ an `HTMLDocument`; `StructuredDataExtractor.extract(html=, doc=)`), `Email`/`PhoneExtractorPlugin`.
196
+ Migration: `context.parser.find_all(sel)` → `context.html_tree.css(sel)`, `.find()` → `.css_first()`,
197
+ `el.get_attribute()` → `el.attr()`. Fixed along the way in `LexborNode`: `attr()` returns `""` (not
198
+ `None`) for valueless boolean attributes such as `itemscope`, so nested Microdata/RDFa items are now
199
+ detected; `css()`/`css_first()` return descendants only (selectolax included the node itself, which made
200
+ Microdata recurse to `max_nesting_depth`).
201
+ - **`PooledPlaywrightDriver` legacy batch path**: `batch_legacy.py`
202
+ (`LegacyBatch._fetch_batch_legacy`, `_fetch_chain`) is gone. `persistent_browser=False` keeps its
203
+ "launch/stop per batch" semantics through the pool path: after a batch, once no fetch is in flight, the
204
+ pool and the engine session are closed (`_close_pool()` + `_stop_persistent_session()`, shared with
205
+ `close()`). Dead `self.playwright`/`self.browsers` cleanup removed from `close()`.
206
+ - **Escalation.** `classify_block()` rewritten to the
207
+ 6.0 decision table: challenge/captcha vendor headers first, then unambiguous body captcha/challenge
208
+ markers (ahead of vendor hard-block headers), then short/blocking-page widgets, status-based verdicts
209
+ and empty-2xx. A bare `401/403/405` with no vendor markers is no longer a block. On the classifier corpus
210
+ it goes 25/37 → **37/37**.
211
+
212
+ - `needs_browser` heuristic (SPA shell: little visible text + SPA root / `<noscript>` JS hint / no
213
+ `<a href>`) is now the default `EscalationPolicy.needs_browser`; on a clean HTTP/TLS response it jumps
214
+ straight to the first browser tier (`escalation_reason="needs_browser"`).
215
+ - Per-tier `TierTimeouts` + `escalation_deadline_s` (60s) budget: a tier is skipped (last response
216
+ returned, browser never started) when the remaining budget is below its `min_budget`; each tier fetch
217
+ is wrapped in `asyncio.wait_for`. New `PER_NODE_FETCH_TIMEOUT` constant with a validator warning.
218
+ - Cross-tier session: `SessionState` / `HostSessionStore` carry solved cookies (`cf_clearance`, `__cf_bm`,
219
+ `datadome`, …) forward and back down to cheaper tiers on re-probe; `impersonate`/`proxy` are pinned once
220
+ a session is solved. curl_cffi pins the impersonate fingerprint; Playwright/nodriver export context
221
+ cookies via `extras["cookies"]`.
222
+ - `extras` contract: every driver stamps `channel`/`driver`/`engine` (via `BaseDriver`/`BaseAsyncDriver`
223
+ `_stamp_extras` + `_finalize_response`) even outside escalation.
224
+ - New Prometheus metrics `crawl_fetch_duration_seconds{channel,engine}`, `crawl_escalations_total`,
225
+ `crawl_escalation_deadline_hits_total`.
226
+
227
+ - **HTML parsing: Lexbor (selectolax) is the only core parser**.
228
+ `beautifulsoup4`, `lxml`, `lxml_html_clean` removed from `[project].dependencies`;
229
+ `BeautifulSoupAdapter`, `LxmlAdapter`, `ScrapyAdapter` deleted. New `HTMLDocument` / `HTMLNode`
230
+ protocols in `domain/value_objects/html_document.py`, implemented by `LexborDocument` in
231
+ `infrastructure/adapters/selectolax_adapter.py`. `<template>` is renamed to `gc-template` before
232
+ parsing so Vue/React SSR links inside templates are not lost. `IParser.parse()` returns `HTMLDocument`;
233
+ `NodePluginContext.html_tree` is now a `LexborDocument`. `get_parser()` accepts `auto|selectolax|lexbor`.
234
+ - `HTMLUtils.extract_links/extract_text/extract_metadata` accept an `HTMLDocument` (string input still
235
+ works but is deprecated).
236
+ - `SitemapParser.parse_large_sitemap_streaming()` uses stdlib `iterparse` by default; lxml is an
237
+ optional fast-path via the new extra `sitemap-fast`.
238
+
239
+ - **`html2md-clean` moved to the optional extra `markdown`** (`pip install "graph-crawler[markdown]"`);
240
+ `MarkdownGenerator/MarkdownOptions/MarkdownResult` re-exports in `graph_crawler.shared.utils` are lazy.
241
+ `MarkdownPlugin` feeds the already-parsed Lexbor tree to html2md-clean 0.5 (`generate_from_tree`) —
242
+ one parse per page instead of 2–4. `import graph_crawler` no longer loads bs4/lxml.
243
+
244
+ - **Dependency map**. Core is now 10 packages: `requests`,
245
+ `httpx`, `pydantic-settings`, `pybloom-live`, `fastapi`, `tenacity`, `stop-words`, `tiktoken`,
246
+ `markdown-it-py` removed from `[project].dependencies`. New extras: `browser` (`playwright` kept as alias),
247
+ `server` (fastapi/uvicorn/websockets), `text` (tiktoken/stop-words), `captcha`; `markdown` also pulls
248
+ `markdown-it-py`; `all` is recursive. Extras `cloudscraper` and `undetected-sync` dropped.
249
+ Extra-gated imports are lazy and fail fast with `requires extra '<name>'`; `transport.PlaywrightDriver/
250
+ RequestsDriver/CloudscraperDriver/RequestsSessionAdapter` are lazy re-exports (ImportError instead of `None`).
251
+ `CrawlerSettings` keeps `GC_*`/`__`/`.env` without pydantic-settings; `CrawlerConfig` is a plain `BaseModel`.
252
+
253
+ - **Transport cleanup**. Deleted: sync drivers
254
+ (`RequestsDriver`, `CloudscraperDriver`, `UndetectedChromeDriver`, `BotasaurusDriver`, `BaseSyncDriver`),
255
+ `AsyncDriverHTTP2` (httpx), `AsyncCloudscraperDriver`, `tls_client.py`, `StealthHTTPDriver`,
256
+ `session_manager/session_adapters/session_protocol`, `shared/utils/captcha_bypass.py`,
257
+ `shared/utils/proxy_manager.py`, packages `transport/http` and `transport/browser`.
258
+ `DriverType` is now `aiohttp | tls | playwright | nodriver | escalating` (+ `asyncio` alias);
259
+ strings `http`/`async`/`asyncio` → `aiohttp` and `stealth`/`curl_cffi` → `tls` are accepted for one
260
+ release with `DeprecationWarning`. One `AsyncDriver` (former `driver_adaptive.py` is now
261
+ `async_http/driver.py`); request hints (`referer`, `extra_headers`, `cookies`) are honoured.
262
+ `requests` is gone from the package: proxy health-check, CAPTCHA solvers/bypass and `SitemapParser`
263
+ use aiohttp (`SitemapParser.parse_sitemap/parse_from_robots` are `asyncio.run` wrappers,
264
+ `http_client=` is deprecated and ignored). `BloomFilter` is pure-python (xxhash) — `pybloom-live`
265
+ no longer needed.
266
+ `import graph_crawler` no longer loads any extra (guarded by `tests/unit/test_import_surface.py`), 3.8 s → 1.7 s here.
267
+ `shared/constants.py` no longer imports aiohttp — `br`/`zstd` are advertised
268
+ by `transport.compression.runtime_browser_headers()` only when the runtime can decode them;
269
+ one driver registry — `application.services.driver_factory` delegates to
270
+ `transport.factory.DriverFactory` (`register_factory`, `registered_names`); `SitemapParser(driver=)`
271
+ fetches robots.txt/sitemaps through the crawl `IDriver` (same tier chain), `SitemapSpider` passes its
272
+ driver, aiohttp is used directly only for binary `.gz`; `tests/transport/test_all_drivers_report_redirects.py`
273
+ is an `IDriver` acceptance matrix (aiohttp / tls / fake playwright / fake nodriver / escalating).
274
+
275
+ - **Escalation**: `EscalationPolicy.reprobe_interval` (5 min) —
276
+ one request per interval re-probes tier 0 for a host remembered on a higher tier (no herd of browser
277
+ re-escalations after TTL); `EscalationPolicy.max_hosts` (10k) — `HostTierMemory` is an LRU and drops
278
+ per-host locks together with entries. In strict mode (`GC_ENGINE_STRICT`) an `ImportError` raised _during_
279
+ `fetch` (lazy browser start without the SDK) now propagates instead of being turned into a network error.
280
+
281
+ - **`extras` contract persisted.** New
282
+ `FetchResponse.fetch_provenance()` / `FETCH_EXTRAS_KEYS`: a JSON-safe slice
283
+ (`bot_block_status, channel, driver, engine, escalations` + `escalation_reason`; cookies/impersonate dropped).
284
+ `NodeScanner` stores it in `node.metadata["fetch"]` for every response, including blocked/error ones, so it
285
+ survives JSON/SQLite/MongoDB/PostgreSQL storage. Contract test `tests/transport/test_extras_contract.py`.
286
+
287
+ ### Fixed
288
+
289
+ - Transport `extras` (`bot_block_status`, tier, escalations) were dropped after fetch and never reached the
290
+ node or storage; for blocked pages nothing was transferred at all.
291
+ - `SmartPageFinder` read `html_tree.text` as a property; with Lexbor it is a method — page text was
292
+ silently dropped.
293
+ - `AsyncUndetectedDriver` accepts a plain `dict` config (`AsyncUndetectedConfig.from_mapping`) — building
294
+ the `nodriver` tier through `DriverFactory.create(DriverType.NODRIVER, config={...})` (as `EscalatingDriver`
295
+ does) raised `AttributeError`.
296
+
297
+ ## 5.2.0 — 2026-06
298
+
299
+ ### Added
300
+
301
+ - `infrastructure/transport/escalation.py`: `classify_block()` (Cloudflare / Akamai / DataDome /
302
+ PerimeterX / Incapsula markers, 403/429/503, empty 200), `EscalationPolicy`, `EscalationTier`,
303
+ `EscalatingDriver` — chain http → tls → browser → undetected with `max_tier`.
304
+ `driver="escalating"` works in `crawl()` / `async_crawl()` / `Crawler` / CLI.
305
+ - `HostTierMemory`: adaptive per-host tier memory — TTL from the moment of decision
306
+ (`GC_TIER_TTL`, default 1200 s), invalidation when the remembered tier gets blocked,
307
+ one escalation per host at a time (per-host lock). Per process.
308
+ - Strict engine mode: `GC_ENGINE_STRICT=1`, `{"browser_engine": {"strict": True}}` or
309
+ `driver_config={"engine_strict": True}` — `ImportError` instead of a silent fallback
310
+ `cloakbrowser → patchright → playwright` or a skipped escalation tier.
311
+ - Browser engine registry in `playwright/engine.py`: `register_engine()`, `resolve_engine()`,
312
+ `registered_engines()`. Built-in engines `cloakbrowser` → `patchright` → `playwright` with
313
+ automatic fail-open. `GC_BROWSER_ENGINE` env selects the engine when config has none.
314
+ `PlaywrightBrowserEngine.effective_name` / `fallback_reason`.
315
+ - `FetchResponse.extras` contract: `bot_block_status`, `channel`, `driver`, `engine`, `escalations`.
316
+ - `DriverType.TLS`, `NODRIVER`, `UNDETECTED`, `BOTASAURUS`, `ESCALATING`; `DriverFactory.create()`
317
+ accepts extra constructor kwargs (`policy=`).
318
+ - Extras: `tls`, `stealth`, `cloak`, `undetected`, `undetected-sync`, `antidetect`, `cloudscraper`, `system`.
319
+ - `README.md`, `CHANGELOG.md`.
320
+
321
+ ### Changed
322
+
323
+ - `normalize_protocol` defaults to `False`: `http://` and `https://` are different URLs.
324
+ The crawler follows the real redirect instead of rewriting the scheme itself, so
325
+ http-only hosts stay reachable. Enable it explicitly to merge both schemes on dedup.
326
+ - `Graph.handle_redirect()` stores the alias as the real `Location` the server sent
327
+ (provenance); the normalized form is used only to find and merge nodes.
328
+ - Single `DriverType` enum (`transport/base.py`); `factory.py` re-exports it.
329
+ - `cloudscraper` moved from required dependencies to extra `cloudscraper`.
330
+ - `psutil` is optional (`system` extra); `MemoryGuard` imports it lazily.
331
+ - `requires-python = ">=3.11"` (upper bound removed; classifiers 3.11–3.14).
332
+ - `pytest` runs offline by default (`-m 'not manual'`, no coverage in `addopts`).
333
+ Network / real-site tests live in `tests/manual/` and run with `pytest -m manual tests/manual`.
334
+ - Project URLs point to the GitLab repository.
335
+
336
+ ### Fixed
337
+
338
+ - `pooled_driver`: bounded walk over `redirected_from` (infinite loop on objects without a
339
+ `None` terminator); cookies are no longer added twice to a fresh browser.
340
+ - Tests synced with the code: redirect aliases, `html2md-clean` 0.4.0 API, `crawl_coordinator`
341
+ `per_host_max_in_flight`, `.gitignore` lookup at the repository root, `tools/db_cleanup.py`
342
+ CLI allow-listed for `print`. Playwright fake tests skip when `playwright` is not installed.
343
+
344
+ ### Removed
345
+
346
+ - `tests/345.py`, `tests/ДОДАТКОВІ_ТЕСТИ.py`, `tests/manual_4a_games_test.py`, `tests/google_maps_results.json`.
347
+ - `EXTRACTION_AUDIT.md` and other analysis / plan documents that described work, not the code.
348
+ - `graph_crawler/data/ARCHITECTURE.md`, `MIGRATION_50_STEPS.md`, `REFACTORING_PLAN.md`, `mkdocs.yml`
349
+ (finished plans / config without content).
350
+
351
+ ## 5.1.0
352
+
353
+ Previous release (sync-first API, Playwright pool, adaptive HTTP drivers, storage backends).