graph-crawler 5.4.1__tar.gz → 5.4.3__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 (481) hide show
  1. graph_crawler-5.4.3/PKG-INFO +130 -0
  2. graph_crawler-5.4.3/README.md +8 -0
  3. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/crawl_coordinator.py +65 -1
  4. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/worker_pool.py +4 -0
  5. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/data/backends/memory.py +2 -0
  6. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/data/backends/sqlite.py +18 -0
  7. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/graph.py +21 -0
  8. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/node.py +2 -0
  9. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/browser_profile.py +1 -1
  10. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/net/__init__.py +1 -1
  11. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/net/geoip.py +0 -1
  12. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/net/proxy_pool.py +0 -1
  13. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/net/rate_limiter.py +0 -1
  14. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/page_fetch.py +40 -8
  15. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/human_bezier.py +0 -1
  16. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/pooled_driver.py +1 -1
  17. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/constants.py +0 -2
  18. graph_crawler-5.4.3/graph_crawler.egg-info/PKG-INFO +130 -0
  19. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler.egg-info/SOURCES.txt +0 -1
  20. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/pyproject.toml +1 -1
  21. graph_crawler-5.4.1/CHANGELOG.md +0 -637
  22. graph_crawler-5.4.1/PKG-INFO +0 -523
  23. graph_crawler-5.4.1/README.md +0 -401
  24. graph_crawler-5.4.1/graph_crawler.egg-info/PKG-INFO +0 -523
  25. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/LICENSE +0 -0
  26. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/MANIFEST.in +0 -0
  27. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/__init__.py +0 -0
  28. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/__version__.py +0 -0
  29. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/ai/__init__.py +0 -0
  30. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/__init__.py +0 -0
  31. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/_core.py +0 -0
  32. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/_distributed.py +0 -0
  33. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/_shared.py +0 -0
  34. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/_sitemap_distributed.py +0 -0
  35. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/async_.py +0 -0
  36. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/cli.py +0 -0
  37. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/client/__init__.py +0 -0
  38. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/client/client.py +0 -0
  39. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/history_manager.py +0 -0
  40. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/project_init.py +0 -0
  41. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/__init__.py +0 -0
  42. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/crawl_monitor.py +0 -0
  43. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/dashboard.py +0 -0
  44. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/rest_api.py +0 -0
  45. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/webhooks.py +0 -0
  46. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/server/websocket_manager.py +0 -0
  47. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/stats_collector.py +0 -0
  48. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/api/sync.py +0 -0
  49. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/__init__.py +0 -0
  50. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/bootstrap.py +0 -0
  51. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/context/__init__.py +0 -0
  52. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/context/dependency_registry.py +0 -0
  53. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/context/graph_context.py +0 -0
  54. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/context/merge_context.py +0 -0
  55. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/__init__.py +0 -0
  56. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/edge_dto.py +0 -0
  57. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/graph_dto.py +0 -0
  58. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/mappers/__init__.py +0 -0
  59. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/mappers/edge_mapper.py +0 -0
  60. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/mappers/graph_mapper.py +0 -0
  61. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/mappers/node_data_codec.py +0 -0
  62. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/mappers/node_mapper.py +0 -0
  63. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/node_dto.py +0 -0
  64. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/dto/utils.py +0 -0
  65. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/__init__.py +0 -0
  66. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/application_container.py +0 -0
  67. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/driver_factory.py +0 -0
  68. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/__init__.py +0 -0
  69. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/base_exporter.py +0 -0
  70. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/csv_exporter.py +0 -0
  71. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/edge_exporter.py +0 -0
  72. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/excel_exporter.py +0 -0
  73. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/jsonl_exporter.py +0 -0
  74. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/node_exporter.py +0 -0
  75. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/parquet_exporter.py +0 -0
  76. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/exporters/sql_exporter.py +0 -0
  77. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/finalize.py +0 -0
  78. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/low_memory_graph_saver.py +0 -0
  79. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/resource_budget.py +0 -0
  80. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/scheduling/__init__.py +0 -0
  81. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/scheduling/rule_based_scheduler.py +0 -0
  82. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/services/storage_factory.py +0 -0
  83. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/__init__.py +0 -0
  84. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/__init__.py +0 -0
  85. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/adaptive_throttler.py +0 -0
  86. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/async_bridge.py +0 -0
  87. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/base_spider.py +0 -0
  88. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/celery_batch_spider.py +0 -0
  89. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/celery_spider.py +0 -0
  90. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/checkpoint.py +0 -0
  91. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/dead_letter_queue.py +0 -0
  92. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/domain_rate_limiter.py +0 -0
  93. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/filters/__init__.py +0 -0
  94. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/filters/base.py +0 -0
  95. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/filters/domain_filter.py +0 -0
  96. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/filters/domain_patterns.py +0 -0
  97. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/filters/path_filter.py +0 -0
  98. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/incremental_strategy.py +0 -0
  99. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/link_processor.py +0 -0
  100. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/multiprocess_spider.py +0 -0
  101. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/node_scanner.py +0 -0
  102. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/parsers/__init__.py +0 -0
  103. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/parsers/base.py +0 -0
  104. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/parsers/html_parser.py +0 -0
  105. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/progress_tracker.py +0 -0
  106. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/scheduler.py +0 -0
  107. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/serialization_mixin.py +0 -0
  108. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/sitemap_parser.py +0 -0
  109. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/sitemap_processor.py +0 -0
  110. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/sitemap_spider.py +0 -0
  111. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/spider.py +0 -0
  112. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/crawling/spider_lifecycle.py +0 -0
  113. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/graph_export.py +0 -0
  114. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/graph_merge/__init__.py +0 -0
  115. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/graph_merge/graph_operations.py +0 -0
  116. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/application/use_cases/graph_merge/merge_strategies.py +0 -0
  117. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/data/__init__.py +0 -0
  118. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/data/backends/__init__.py +0 -0
  119. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/data/interfaces.py +0 -0
  120. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/__init__.py +0 -0
  121. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/context/__init__.py +0 -0
  122. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/context/crawl_context.py +0 -0
  123. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/__init__.py +0 -0
  124. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/edge.py +0 -0
  125. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/edge_analysis.py +0 -0
  126. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/graph_operations.py +0 -0
  127. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/graph_statistics.py +0 -0
  128. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/merge_strategies.py +0 -0
  129. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/redirect_mode.py +0 -0
  130. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/registries.py +0 -0
  131. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/sitemap_node.py +0 -0
  132. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/entities/strategies.py +0 -0
  133. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/__init__.py +0 -0
  134. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/base.py +0 -0
  135. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/crawl.py +0 -0
  136. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/edge.py +0 -0
  137. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/event_bus.py +0 -0
  138. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/events.py +0 -0
  139. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/fetch.py +0 -0
  140. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/idempotent_subscriber.py +0 -0
  141. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/legacy_type_map.py +0 -0
  142. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/llm.py +0 -0
  143. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/node.py +0 -0
  144. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/plugin.py +0 -0
  145. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/scheduler.py +0 -0
  146. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/events/storage.py +0 -0
  147. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/__init__.py +0 -0
  148. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/adapter.py +0 -0
  149. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/control_channel.py +0 -0
  150. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/crawl_context.py +0 -0
  151. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/distributed_spider.py +0 -0
  152. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/driver.py +0 -0
  153. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/event_bus.py +0 -0
  154. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/exporters.py +0 -0
  155. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/filter.py +0 -0
  156. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/merge_context.py +0 -0
  157. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/node_interfaces.py +0 -0
  158. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/parser.py +0 -0
  159. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/plugin_manager.py +0 -0
  160. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/processor.py +0 -0
  161. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/scanner.py +0 -0
  162. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/scheduler.py +0 -0
  163. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/scheduling/__init__.py +0 -0
  164. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/scheduling/frontier.py +0 -0
  165. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/scheduling/scheduler.py +0 -0
  166. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/spider.py +0 -0
  167. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/stop_condition.py +0 -0
  168. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/storage/__init__.py +0 -0
  169. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/storage/base.py +0 -0
  170. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/storage/eviction.py +0 -0
  171. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/interfaces/storage/queue.py +0 -0
  172. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/__init__.py +0 -0
  173. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/adjacency_maintenance.py +0 -0
  174. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/cycle_detection.py +0 -0
  175. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/degree_ranking.py +0 -0
  176. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/depth_context.py +0 -0
  177. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/display_title.py +0 -0
  178. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/duplicate_detection.py +0 -0
  179. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/duplicate_selector.py +0 -0
  180. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/duplicate_stats.py +0 -0
  181. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/edge_filter.py +0 -0
  182. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/edge_statistics.py +0 -0
  183. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/eviction_policy.py +0 -0
  184. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/graph_query_cascade.py +0 -0
  185. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/graph_statistics.py +0 -0
  186. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/graph_traversal.py +0 -0
  187. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/language_versions.py +0 -0
  188. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/lsh_index.py +0 -0
  189. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/minimap_builder.py +0 -0
  190. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/node_content_resolver.py +0 -0
  191. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/node_view_builder.py +0 -0
  192. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/pagination_guards.py +0 -0
  193. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/predicate_ops.py +0 -0
  194. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/schema_filter.py +0 -0
  195. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/search_haystack.py +0 -0
  196. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/simhash_clustering.py +0 -0
  197. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/simhash_fallback.py +0 -0
  198. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/similarity_ranking.py +0 -0
  199. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/text_search.py +0 -0
  200. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/url_clustering.py +0 -0
  201. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/url_deduplication.py +0 -0
  202. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/url_normalizer.py +0 -0
  203. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/url_rule_matcher.py +0 -0
  204. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/services/url_tree_builder.py +0 -0
  205. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/__init__.py +0 -0
  206. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/configs.py +0 -0
  207. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/domain_patterns.py +0 -0
  208. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/fetch_options.py +0 -0
  209. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/html_document.py +0 -0
  210. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/lifecycle.py +0 -0
  211. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/models.py +0 -0
  212. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/page_actions.py +0 -0
  213. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/redirect_hop.py +0 -0
  214. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/scheduling/__init__.py +0 -0
  215. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/scheduling/crawl_request.py +0 -0
  216. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/scheduling/retry_policy.py +0 -0
  217. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/settings.py +0 -0
  218. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/url_normalization.py +0 -0
  219. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/domain/value_objects/views.py +0 -0
  220. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/__init__.py +0 -0
  221. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/__init__.py +0 -0
  222. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/base.py +0 -0
  223. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/cache_middleware.py +0 -0
  224. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/chain.py +0 -0
  225. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/error_recovery_middleware.py +0 -0
  226. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/logging_middleware.py +0 -0
  227. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/proxy_health.py +0 -0
  228. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/proxy_middleware.py +0 -0
  229. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/proxy_models.py +0 -0
  230. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/proxy_selection.py +0 -0
  231. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/rate_limit_middleware.py +0 -0
  232. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/request_response_middleware.py +0 -0
  233. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/retry_middleware.py +0 -0
  234. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/robots_cache.py +0 -0
  235. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/robots_middleware.py +0 -0
  236. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/robots_validator.py +0 -0
  237. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/middleware/user_agent_middleware.py +0 -0
  238. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/__init__.py +0 -0
  239. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/builtin/__init__.py +0 -0
  240. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/builtin/stats_export_plugin.py +0 -0
  241. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/crawl_engine/__init__.py +0 -0
  242. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/crawl_engine/base.py +0 -0
  243. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/crawl_engine/priority_provider.py +0 -0
  244. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/crawl_engine/smart_crawl.py +0 -0
  245. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/__init__.py +0 -0
  246. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/anti_bot_detection.py +0 -0
  247. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/anti_bot_playwright.py +0 -0
  248. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/anti_bot_scripts.py +0 -0
  249. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/anti_bot_stealth.py +0 -0
  250. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/base.py +0 -0
  251. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/captcha/__init__.py +0 -0
  252. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/captcha/detector.py +0 -0
  253. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/captcha/models.py +0 -0
  254. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/captcha/plugin.py +0 -0
  255. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/engine/captcha/services.py +0 -0
  256. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/__init__.py +0 -0
  257. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/base.py +0 -0
  258. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/__init__.py +0 -0
  259. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/base.py +0 -0
  260. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/goose3_extractor.py +0 -0
  261. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/newspaper_extractor.py +0 -0
  262. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/plugin.py +0 -0
  263. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/content_extractors/readability_extractor.py +0 -0
  264. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/defaults.py +0 -0
  265. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/extractors/__init__.py +0 -0
  266. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/extractors/email_extractor.py +0 -0
  267. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/extractors/phone_extractor.py +0 -0
  268. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/extractors/price_extractor.py +0 -0
  269. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/links.py +0 -0
  270. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/markdown_plugin.py +0 -0
  271. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/metadata.py +0 -0
  272. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/smart_page_finder.py +0 -0
  273. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/__init__.py +0 -0
  274. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/constants.py +0 -0
  275. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/exceptions.py +0 -0
  276. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/extractor.py +0 -0
  277. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/options.py +0 -0
  278. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/__init__.py +0 -0
  279. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/base.py +0 -0
  280. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/jsonld.py +0 -0
  281. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/microdata.py +0 -0
  282. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/opengraph.py +0 -0
  283. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/rdfa.py +0 -0
  284. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/parsers/twitter.py +0 -0
  285. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/plugin.py +0 -0
  286. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/structured_data/result.py +0 -0
  287. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/text.py +0 -0
  288. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/node/url_normalizer.py +0 -0
  289. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/extensions/plugins/registry.py +0 -0
  290. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/__init__.py +0 -0
  291. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/adapters/__init__.py +0 -0
  292. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/adapters/base.py +0 -0
  293. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/adapters/selectolax_adapter.py +0 -0
  294. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/__init__.py +0 -0
  295. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/celery_app.py +0 -0
  296. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/celery_batch.py +0 -0
  297. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/celery_job_task.py +0 -0
  298. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/celery_unified.py +0 -0
  299. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/config.py +0 -0
  300. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/easy_crawler.py +0 -0
  301. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/messaging/worker_api.py +0 -0
  302. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/__init__.py +0 -0
  303. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/auto_storage.py +0 -0
  304. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/base.py +0 -0
  305. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/eviction.py +0 -0
  306. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/graph_repository.py +0 -0
  307. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/json/__init__.py +0 -0
  308. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/json_storage.py +0 -0
  309. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/lmdb_eviction_storage.py +0 -0
  310. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/memory/__init__.py +0 -0
  311. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/memory_dedup_store.py +0 -0
  312. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/memory_frontier.py +0 -0
  313. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/memory_politeness_store.py +0 -0
  314. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/memory_storage.py +0 -0
  315. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/mongodb_storage.py +0 -0
  316. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/naming_strategy.py +0 -0
  317. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/postgresql_storage.py +0 -0
  318. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/protocols/__init__.py +0 -0
  319. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/redis_dedup_store.py +0 -0
  320. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/redis_politeness_store.py +0 -0
  321. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/repository.py +0 -0
  322. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/sqlite/__init__.py +0 -0
  323. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/sqlite_eviction_storage.py +0 -0
  324. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/sqlite_storage.py +0 -0
  325. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/__init__.py +0 -0
  326. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/file_job_storage.py +0 -0
  327. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/file_queue_storage.py +0 -0
  328. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/memory_job_storage.py +0 -0
  329. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/memory_queue_storage.py +0 -0
  330. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/postgresql_job_storage.py +0 -0
  331. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/postgresql_queue_storage.py +0 -0
  332. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/persistence/unified/unified_storage.py +0 -0
  333. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/__init__.py +0 -0
  334. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/__init__.py +0 -0
  335. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/config.py +0 -0
  336. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/context.py +0 -0
  337. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/driver.py +0 -0
  338. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/driver_curl_cffi.py +0 -0
  339. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/__init__.py +0 -0
  340. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle.py +0 -0
  341. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/autothrottle_adaptive.py +0 -0
  342. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/headers.py +0 -0
  343. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/http_cache.py +0 -0
  344. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/rate_limiter.py +0 -0
  345. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/plugins/retry.py +0 -0
  346. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/async_http/stages.py +0 -0
  347. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/base.py +0 -0
  348. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/base_plugin.py +0 -0
  349. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/compression/__init__.py +0 -0
  350. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/compression/strategy.py +0 -0
  351. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/connection_pool.py +0 -0
  352. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/context.py +0 -0
  353. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/__init__.py +0 -0
  354. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/base_async.py +0 -0
  355. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/body_decoder.py +0 -0
  356. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/body_limit.py +0 -0
  357. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/mixins.py +0 -0
  358. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/core/redirect_utils.py +0 -0
  359. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/escalation.py +0 -0
  360. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/factory.py +0 -0
  361. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/__init__.py +0 -0
  362. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/adaptive_semaphore.py +0 -0
  363. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/batch_scheduler.py +0 -0
  364. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/browser_factory.py +0 -0
  365. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/config.py +0 -0
  366. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/context.py +0 -0
  367. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/driver.py +0 -0
  368. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/engine.py +0 -0
  369. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/fetch_metrics.py +0 -0
  370. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/page_actions.py +0 -0
  371. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/__init__.py +0 -0
  372. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/_network_record.py +0 -0
  373. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/captcha_detector.py +0 -0
  374. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/captcha_solver.py +0 -0
  375. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/cookie_consent.py +0 -0
  376. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/form_filler.py +0 -0
  377. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/network_log.py +0 -0
  378. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/ram_adaptive.py +0 -0
  379. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/screenshot.py +0 -0
  380. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/plugins/user_profile.py +0 -0
  381. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/pool_lifecycle.py +0 -0
  382. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/stages.py +0 -0
  383. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/playwright/stealth_hints.py +0 -0
  384. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/plugin_manager.py +0 -0
  385. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/protocols.py +0 -0
  386. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/undetected/__init__.py +0 -0
  387. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/infrastructure/transport/undetected/async_driver.py +0 -0
  388. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/native/__init__.py +0 -0
  389. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/native/bloom_filter.pyx +0 -0
  390. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/native/html_parser.pyx +0 -0
  391. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/native/setup.py +0 -0
  392. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/native/url_utils.pyx +0 -0
  393. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/__init__.py +0 -0
  394. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/error_tracing.py +0 -0
  395. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/extensions/__init__.py +0 -0
  396. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/extensions/memory_guard.py +0 -0
  397. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/extensions/state_manager.py +0 -0
  398. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/__init__.py +0 -0
  399. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/base.py +0 -0
  400. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/base_metrics_listener.py +0 -0
  401. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/crawl_listener.py +0 -0
  402. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/dlq_listener.py +0 -0
  403. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/error_listener.py +0 -0
  404. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/logging_listener.py +0 -0
  405. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/metrics_listener.py +0 -0
  406. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/node_listener.py +0 -0
  407. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/plugin_listener.py +0 -0
  408. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/storage_listener.py +0 -0
  409. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/listeners/url_listener.py +0 -0
  410. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/metrics/__init__.py +0 -0
  411. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/metrics/memory_profiler.py +0 -0
  412. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/metrics/metrics_collector.py +0 -0
  413. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/metrics/prometheus_metrics.py +0 -0
  414. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/metrics_core.py +0 -0
  415. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/structured_logging.py +0 -0
  416. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/observability/tracing.py +0 -0
  417. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/optimizations/__init__.py +0 -0
  418. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/optimizations/generators.py +0 -0
  419. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/optimizations/memory_slots.py +0 -0
  420. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/optimizations/simhash_numba.py +0 -0
  421. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/py.typed +0 -0
  422. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/__init__.py +0 -0
  423. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/dto/__init__.py +0 -0
  424. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/dto/edge_dto.py +0 -0
  425. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/dto/graph_dto.py +0 -0
  426. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/dto/node_dto.py +0 -0
  427. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/error_handling/__init__.py +0 -0
  428. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/error_handling/error_handler.py +0 -0
  429. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/exceptions.py +0 -0
  430. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/__init__.py +0 -0
  431. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/adaptive_resolver.py +0 -0
  432. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/config.py +0 -0
  433. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/detector.py +0 -0
  434. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/diagnostics.py +0 -0
  435. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/platform/metrics.py +0 -0
  436. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/security/__init__.py +0 -0
  437. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/security/url_sanitizer.py +0 -0
  438. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/security/url_validator.py +0 -0
  439. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/__init__.py +0 -0
  440. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/async_compat.py +0 -0
  441. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/best_effort.py +0 -0
  442. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/bloom_filter.py +0 -0
  443. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/captcha/__init__.py +0 -0
  444. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/captcha/base.py +0 -0
  445. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/captcha/manager.py +0 -0
  446. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/celery_config.py +0 -0
  447. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/celery_helpers.py +0 -0
  448. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/cgroup_limits.py +0 -0
  449. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/content_decoder.py +0 -0
  450. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/distributed_rate_limiter.py +0 -0
  451. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/distributed_rate_limiter_backends.py +0 -0
  452. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/dns_cache.py +0 -0
  453. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/enterprise_ua_generator.py +0 -0
  454. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/event_publisher_mixin.py +0 -0
  455. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fast_json.py +0 -0
  456. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fingerprint.py +0 -0
  457. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fingerprint_data.py +0 -0
  458. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fingerprint_generators.py +0 -0
  459. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fingerprint_profile.py +0 -0
  460. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/fingerprint_stealth.py +0 -0
  461. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/html_utils.py +0 -0
  462. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/id_generator.py +0 -0
  463. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/isolated_executor.py +0 -0
  464. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/memory_optimizer.py +0 -0
  465. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/rate_limiter.py +0 -0
  466. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/regex_validator.py +0 -0
  467. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/shadow_dom.py +0 -0
  468. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/text_utils.py +0 -0
  469. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/url_patterns.py +0 -0
  470. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/url_utils.py +0 -0
  471. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/user_agent_rotator.py +0 -0
  472. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/validation_helpers.py +0 -0
  473. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/visualization.py +0 -0
  474. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/shared/utils/visualization_core.py +0 -0
  475. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/tools/__init__.py +0 -0
  476. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler/tools/db_cleanup.py +0 -0
  477. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler.egg-info/dependency_links.txt +0 -0
  478. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler.egg-info/entry_points.txt +0 -0
  479. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler.egg-info/requires.txt +0 -0
  480. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/graph_crawler.egg-info/top_level.txt +0 -0
  481. {graph_crawler-5.4.1 → graph_crawler-5.4.3}/setup.cfg +0 -0
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: graph-crawler
3
+ Version: 5.4.3
4
+ Summary: Web crawler that builds a graph of a site. HTTP → TLS → browser escalation with pluggable browser engines.
5
+ Author: 0-EternalJunior-0
6
+ Maintainer: 0-EternalJunior-0
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://gitlab.com/demoprogrammer/web_graf
9
+ Project-URL: Documentation, https://gitlab.com/demoprogrammer/web_graf/-/blob/main/web_graf/README.md
10
+ Project-URL: Repository, https://gitlab.com/demoprogrammer/web_graf
11
+ Project-URL: Changelog, https://gitlab.com/demoprogrammer/web_graf/-/blob/main/web_graf/CHANGELOG.md
12
+ Project-URL: Bug Tracker, https://gitlab.com/demoprogrammer/web_graf/-/issues
13
+ Keywords: web,crawler,scraper,graph,spider,playwright,anti-bot,tls-fingerprint
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Operating System :: OS Independent
24
+ Requires-Python: >=3.11
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: aiohttp>=3.13.0
28
+ Requires-Dist: backports.zstd>=1.6.0; python_version < "3.14"
29
+ Requires-Dist: Brotli
30
+ Requires-Dist: selectolax<1.0.0,>=0.4.0
31
+ Requires-Dist: defusedxml>=0.7.0
32
+ Requires-Dist: pydantic>=2.12.0
33
+ Requires-Dist: orjson>=3.11.0
34
+ Requires-Dist: aiofiles>=24.1.0
35
+ Requires-Dist: aiosqlite>=0.20.0
36
+ Requires-Dist: typing_extensions>=4.5; python_version < "3.12"
37
+ Requires-Dist: xxhash>=3.0.0
38
+ Requires-Dist: resilix<2,>=1.1
39
+ Provides-Extra: native
40
+ Requires-Dist: cython>=3.0.0; extra == "native"
41
+ Requires-Dist: mmh3>=5.0.0; extra == "native"
42
+ Provides-Extra: browser
43
+ Requires-Dist: playwright>=1.58.0; extra == "browser"
44
+ Provides-Extra: playwright
45
+ Requires-Dist: graph-crawler[browser]; extra == "playwright"
46
+ Provides-Extra: tls
47
+ Requires-Dist: curl_cffi>=0.7; extra == "tls"
48
+ Provides-Extra: stealth
49
+ Requires-Dist: patchright>=1.52; extra == "stealth"
50
+ Requires-Dist: playwright-stealth>=1.0; extra == "stealth"
51
+ Provides-Extra: cloak
52
+ Requires-Dist: cloakbrowser>=0.5; extra == "cloak"
53
+ Requires-Dist: playwright>=1.58.0; extra == "cloak"
54
+ Provides-Extra: undetected
55
+ Requires-Dist: nodriver>=0.38; extra == "undetected"
56
+ Provides-Extra: antidetect
57
+ Requires-Dist: graph-crawler[browser,cloak,stealth,tls,undetected]; extra == "antidetect"
58
+ Provides-Extra: server
59
+ Requires-Dist: fastapi>=0.135.0; extra == "server"
60
+ Requires-Dist: uvicorn>=0.30; extra == "server"
61
+ Requires-Dist: websockets>=13; extra == "server"
62
+ Provides-Extra: text
63
+ Requires-Dist: tiktoken>=0.13.0; extra == "text"
64
+ Requires-Dist: stop-words>=2018.7.23; extra == "text"
65
+ Provides-Extra: captcha
66
+ Provides-Extra: mongodb
67
+ Requires-Dist: pymongo[srv]>=4.9.0; extra == "mongodb"
68
+ Provides-Extra: postgresql
69
+ Requires-Dist: asyncpg>=0.30.0; extra == "postgresql"
70
+ Provides-Extra: newspaper
71
+ Requires-Dist: newspaper3k>=0.2.8; extra == "newspaper"
72
+ Provides-Extra: goose
73
+ Requires-Dist: goose3>=3.1.0; extra == "goose"
74
+ Provides-Extra: readability
75
+ Requires-Dist: readability-lxml>=0.8.0; extra == "readability"
76
+ Provides-Extra: markdown
77
+ Requires-Dist: html2md-clean>=0.5.0; extra == "markdown"
78
+ Requires-Dist: markdown-it-py>=4.0.0; extra == "markdown"
79
+ Provides-Extra: sitemap-fast
80
+ Requires-Dist: lxml>=5.1.0; extra == "sitemap-fast"
81
+ Provides-Extra: articles
82
+ Requires-Dist: newspaper3k>=0.2.8; extra == "articles"
83
+ Requires-Dist: goose3>=3.1.0; extra == "articles"
84
+ Requires-Dist: readability-lxml>=0.8.0; extra == "articles"
85
+ Provides-Extra: viz
86
+ Requires-Dist: pyvis>=0.3.0; extra == "viz"
87
+ Requires-Dist: networkx>=3.6; extra == "viz"
88
+ Provides-Extra: celery
89
+ Requires-Dist: celery>=5.5.0; extra == "celery"
90
+ Requires-Dist: redis>=5.2.0; extra == "celery"
91
+ Provides-Extra: performance
92
+ Requires-Dist: aiodns>=3.6.0; extra == "performance"
93
+ Requires-Dist: uvloop>=0.22.0; platform_system != "Windows" and extra == "performance"
94
+ Provides-Extra: fuzzy
95
+ Requires-Dist: rapidfuzz>=3.6.0; extra == "fuzzy"
96
+ Provides-Extra: dev
97
+ Requires-Dist: pytest>=9.0.0; extra == "dev"
98
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
99
+ Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
100
+ Requires-Dist: black>=24.0.0; extra == "dev"
101
+ Requires-Dist: ruff>=0.8.0; extra == "dev"
102
+ Requires-Dist: mypy>=1.13.0; extra == "dev"
103
+ Requires-Dist: psutil; extra == "dev"
104
+ Requires-Dist: rapidfuzz>=3.6.0; extra == "dev"
105
+ Requires-Dist: pytest-timeout>=2.3.0; extra == "dev"
106
+ Requires-Dist: pytest-xdist>=3.5.0; extra == "dev"
107
+ Requires-Dist: build>=1.2.0; extra == "dev"
108
+ Requires-Dist: twine>=5.0.0; extra == "dev"
109
+ Requires-Dist: playwright>=1.58.0; extra == "dev"
110
+ Requires-Dist: curl_cffi>=0.7; extra == "dev"
111
+ Requires-Dist: html2md-clean>=0.5.0; extra == "dev"
112
+ Requires-Dist: markdown-it-py>=4.0.0; extra == "dev"
113
+ Requires-Dist: tiktoken>=0.13.0; extra == "dev"
114
+ Requires-Dist: stop-words>=2018.7.23; extra == "dev"
115
+ Requires-Dist: fastapi>=0.135.0; extra == "dev"
116
+ Requires-Dist: httpx>=0.28; extra == "dev"
117
+ Provides-Extra: system
118
+ Requires-Dist: psutil>=5.9.0; extra == "system"
119
+ Provides-Extra: all
120
+ Requires-Dist: graph-crawler[antidetect,articles,celery,fuzzy,markdown,mongodb,performance,postgresql,server,sitemap-fast,system,text,viz]; extra == "all"
121
+ Dynamic: license-file
122
+
123
+ # graph-crawler
124
+
125
+ Веб-краулер, що будує граф сайту (сторінки — ноди, посилання — ребра) з ескалацією HTTP → TLS-fingerprint → браузер.
126
+
127
+ ```bash
128
+ pip install graph-crawler # лише HTTP
129
+ pip install "graph-crawler[browser]" # + Playwright
130
+ ```
@@ -0,0 +1,8 @@
1
+ # graph-crawler
2
+
3
+ Веб-краулер, що будує граф сайту (сторінки — ноди, посилання — ребра) з ескалацією HTTP → TLS-fingerprint → браузер.
4
+
5
+ ```bash
6
+ pip install graph-crawler # лише HTTP
7
+ pip install "graph-crawler[browser]" # + Playwright
8
+ ```
@@ -42,6 +42,7 @@ from graph_crawler.shared.constants import (
42
42
  BROWSER_PAGE_RAM_ESTIMATE_MB,
43
43
  BROWSER_RAM_BASELINE_MB,
44
44
  DEFAULT_BATCH_SIZE,
45
+ DEFAULT_NODE_ENRICH_TIMEOUT,
45
46
  MAX_PAGES_LIMIT,
46
47
  )
47
48
  from graph_crawler.shared.utils.cgroup_limits import (
@@ -85,6 +86,12 @@ logger = logging.getLogger(__name__)
85
86
  # Скільки секунд після crawl-level timeout даємо in-flight нодам дозавершитись.
86
87
  TIMEOUT_DRAIN_GRACE_S = 1.0
87
88
 
89
+ # NEW-3-5: браузерний пул «завис», якщо жодна нода не завершилась за
90
+ # 2 × fetch_timeout + enrich-таймаут + запас (найдовший законний шлях однієї ноди).
91
+ STALL_FETCH_TIMEOUT_MULTIPLIER = 2.0
92
+ STALL_GRACE_S = 10.0
93
+ STALL_CHECK_INTERVAL_S = 5.0
94
+
88
95
 
89
96
  def _stats_for_log(stats: dict) -> dict:
90
97
  """Копія stats для логу без шумового ``redirect_deduped_scanned=0``.
@@ -425,6 +432,14 @@ class CrawlCoordinator:
425
432
  asyncio.create_task(self._worker_loop(i, state), name=f"crawl-worker-{i}")
426
433
  for i in range(pool_size)
427
434
  ]
435
+ stall_timeout = self._resolve_stall_timeout()
436
+ watchdog = (
437
+ asyncio.create_task(
438
+ self._stall_watchdog(workers, state, stall_timeout), name="crawl-stall-watchdog"
439
+ )
440
+ if stall_timeout
441
+ else None
442
+ )
428
443
  try:
429
444
  await self._await_workers(workers, state)
430
445
  except asyncio.CancelledError:
@@ -436,6 +451,9 @@ class CrawlCoordinator:
436
451
  await asyncio.gather(*workers, return_exceptions=True)
437
452
  raise
438
453
  finally:
454
+ if watchdog is not None:
455
+ watchdog.cancel()
456
+ await asyncio.gather(watchdog, return_exceptions=True)
439
457
  self._pool_state = None
440
458
 
441
459
  if state.stop_reason == "timeout":
@@ -444,6 +462,8 @@ class CrawlCoordinator:
444
462
  self.spider, "stop_reason", None
445
463
  ):
446
464
  self._record_stop(state.stop_reason, "limit")
465
+ if state.stop_reason == "stalled" and not self.scheduler.is_empty():
466
+ self._record_stop("stalled", "limit")
447
467
 
448
468
  logger.debug(
449
469
  "Worker pool finished: %d nodes processed, reason=%s, %.1fs",
@@ -457,7 +477,8 @@ class CrawlCoordinator:
457
477
  async def _await_workers(self, workers: list[asyncio.Task], state: PoolState) -> None:
458
478
  """Чекає воркерів; при crawl-level timeout скасовує in-flight (інакше ретраї тягнуть хвіст)."""
459
479
  if self.timeout is None or not self.start_time:
460
- await asyncio.gather(*workers)
480
+ done, _ = await asyncio.wait(workers)
481
+ self._raise_worker_errors(done)
461
482
  return
462
483
  deadline = self.start_time + self.timeout + TIMEOUT_DRAIN_GRACE_S
463
484
  done, pending = await asyncio.wait(workers, timeout=max(0.0, deadline - time.time()))
@@ -478,10 +499,53 @@ class CrawlCoordinator:
478
499
  for task in pending:
479
500
  task.cancel()
480
501
  await asyncio.gather(*pending, return_exceptions=True)
502
+ self._raise_worker_errors(done)
503
+
504
+ @staticmethod
505
+ def _raise_worker_errors(done: set[asyncio.Task]) -> None:
506
+ """Скасований сторожем простою воркер — не помилка; справжню помилку воркера прокидаємо."""
481
507
  for task in done:
482
508
  if not task.cancelled() and task.exception() is not None:
483
509
  raise task.exception()
484
510
 
511
+ def _resolve_stall_timeout(self) -> float | None:
512
+ """Поріг «пул завис» (NEW-3-5): лише для браузерних драйверів, що мають ``fetch_timeout``."""
513
+ if not _is_js_heavy_driver(self.driver):
514
+ return None
515
+ fetch_timeout = getattr(self.driver, "fetch_timeout", None)
516
+ if isinstance(fetch_timeout, bool) or not isinstance(fetch_timeout, (int, float)):
517
+ return None
518
+ if fetch_timeout <= 0:
519
+ return None
520
+ enrich_timeout = (
521
+ getattr(self.config, "node_enrich_timeout", None) or DEFAULT_NODE_ENRICH_TIMEOUT
522
+ )
523
+ return STALL_FETCH_TIMEOUT_MULTIPLIER * fetch_timeout + enrich_timeout + STALL_GRACE_S
524
+
525
+ async def _stall_watchdog(
526
+ self, workers: list[asyncio.Task], state: PoolState, stall_timeout: float
527
+ ) -> None:
528
+ """Жодна нода не завершилась за ``stall_timeout`` — вкладки зависли: скасовуємо їх, фаза завершується."""
529
+ interval = min(STALL_CHECK_INTERVAL_S, stall_timeout / 4)
530
+ while not state.stop:
531
+ await asyncio.sleep(interval)
532
+ idle = time.monotonic() - state.last_progress_at
533
+ if state.in_flight == 0 or idle < stall_timeout:
534
+ continue
535
+ logger.warning(
536
+ "Worker pool stalled: no page finished for %.0fs (limit %.0fs), in_flight=%d, "
537
+ "queue=%d, stuck=%s - cancelling stuck workers",
538
+ idle,
539
+ stall_timeout,
540
+ state.in_flight,
541
+ self.scheduler.size() if hasattr(self.scheduler, "size") else 0,
542
+ list(state.in_flight_urls)[:5],
543
+ )
544
+ state.request_stop("stalled")
545
+ for task in workers:
546
+ task.cancel()
547
+ return
548
+
485
549
  def _resolve_worker_pool_size(self) -> int:
486
550
  """N воркерів: override з конфігу → конкурентність драйвера → кап для JS-heavy.
487
551
 
@@ -15,6 +15,7 @@ from __future__ import annotations
15
15
 
16
16
  import asyncio
17
17
  import logging
18
+ import time
18
19
  from collections import defaultdict
19
20
  from urllib.parse import urlsplit
20
21
 
@@ -119,6 +120,8 @@ class PoolState:
119
120
  self.stop = False
120
121
  self.stop_reason: str | None = None
121
122
  self.wakeup = asyncio.Event()
123
+ # NEW-3-5: час останньої завершеної ноди — сторож простою пулу.
124
+ self.last_progress_at = time.monotonic()
122
125
 
123
126
  def request_stop(self, reason: str) -> None:
124
127
  if not self.stop:
@@ -141,6 +144,7 @@ class PoolState:
141
144
  """Повертає True, якщо eviction-watermark просунувся."""
142
145
  self.in_flight -= 1
143
146
  self.completed += 1
147
+ self.last_progress_at = time.monotonic()
144
148
  if node_id:
145
149
  self.in_flight_node_ids.discard(node_id)
146
150
  self.in_flight_urls.pop(url, None)
@@ -182,6 +182,8 @@ class MemoryBackend:
182
182
  async with self._lock:
183
183
  count = 0
184
184
  for node in nodes:
185
+ if getattr(node, "_removed_from_graph", False):
186
+ continue
185
187
  normalized_url = self._normalize_url(node.url)
186
188
  node.url = normalized_url
187
189
  new_scanned = bool(getattr(node, "scanned", False))
@@ -235,6 +235,11 @@ class SQLiteBackend:
235
235
  """
236
236
  self.db_path = db_path
237
237
  self.journal_mode = journal_mode
238
+ # Скільки відкладених insert-ів пропущено через tombstone (діагностика).
239
+ self.tombstone_skips = 0
240
+ # URL нод, видалених з графа (remove_node): відкладений insert_nodes_batch
241
+ # їх не воскрешає; явний insert_node/insert_node_sync tombstone знімає.
242
+ self._tombstoned_urls: set[str] = set()
238
243
  self._conn = None
239
244
  self._is_open = False
240
245
 
@@ -895,6 +900,7 @@ class SQLiteBackend:
895
900
  # Normalize URL
896
901
  original_url = node.url
897
902
  normalized_url = self._normalize_url(original_url)
903
+ self._tombstoned_urls.discard(normalized_url)
898
904
 
899
905
  if original_url != normalized_url:
900
906
  node.url = normalized_url
@@ -1002,7 +1008,16 @@ class SQLiteBackend:
1002
1008
  for node in nodes:
1003
1009
  from graph_crawler.shared.utils.id_generator import generate_node_id
1004
1010
 
1011
+ # Tombstone: нода вже видалена з графа (редірект на існуючу) —
1012
+ # відкладений write-through не повинен її воскресити.
1013
+ if getattr(node, "_removed_from_graph", False):
1014
+ self.tombstone_skips += 1
1015
+ continue
1016
+
1005
1017
  normalized_url = self._normalize_url(node.url)
1018
+ if normalized_url in self._tombstoned_urls:
1019
+ self.tombstone_skips += 1
1020
+ continue
1006
1021
  node.url = normalized_url
1007
1022
 
1008
1023
  # BUGFIX /: пере-обчислити node_id після
@@ -1241,6 +1256,7 @@ class SQLiteBackend:
1241
1256
  else:
1242
1257
  url = node.url
1243
1258
 
1259
+ self._tombstoned_urls.add(self._normalize_url(url))
1244
1260
  # Delete from DB
1245
1261
  await self._conn.execute("DELETE FROM nodes WHERE node_id = ?", (node_id,))
1246
1262
  await self._conn.execute(
@@ -1647,6 +1663,7 @@ class SQLiteBackend:
1647
1663
  from graph_crawler.shared.utils.id_generator import generate_node_id
1648
1664
 
1649
1665
  normalized_url = self._normalize_url(node.url)
1666
+ self._tombstoned_urls.discard(normalized_url)
1650
1667
  cached = self._cache_get_by_url(normalized_url)
1651
1668
  if cached is not None:
1652
1669
  return cached
@@ -1690,6 +1707,7 @@ class SQLiteBackend:
1690
1707
  if not rows:
1691
1708
  return False
1692
1709
  url = rows[0][0]
1710
+ self._tombstoned_urls.add(self._normalize_url(url))
1693
1711
  deleted = self._sync_execute(
1694
1712
  [
1695
1713
  ("DELETE FROM nodes WHERE node_id = ?", (node_id,)),
@@ -124,6 +124,21 @@ from graph_crawler.shared.exceptions import GraphIntegrityError
124
124
  logger = logging.getLogger(__name__)
125
125
 
126
126
 
127
+
128
+ def _set_removed_flag(node: Any, value: bool) -> None:
129
+ try:
130
+ node._removed_from_graph = value
131
+ except (AttributeError, ValueError, TypeError):
132
+ pass
133
+
134
+
135
+ def is_removed_from_graph(node: Any) -> bool:
136
+ """Чи нода видалена з графа (tombstone від ``Graph.remove_node``)."""
137
+ try:
138
+ return bool(getattr(node, "_removed_from_graph", False))
139
+ except Exception: # noqa: BLE001
140
+ return False
141
+
127
142
  class Graph:
128
143
  """Менеджер графу: CRUD над вузлами/ребрами, URL-дедуплікація, evict у RAM/на диск.
129
144
 
@@ -759,6 +774,8 @@ class Graph:
759
774
  self._stale_node_id_map[node.node_id] = expected_id
760
775
  node.node_id = expected_id
761
776
 
777
+ # Явне повторне додавання знімає tombstone.
778
+ _set_removed_flag(node, False)
762
779
  return node
763
780
 
764
781
  def add_node(self, node: Node, overwrite: bool = False) -> Node:
@@ -1339,6 +1356,10 @@ class Graph:
1339
1356
  if not node:
1340
1357
  return False
1341
1358
 
1359
+ # Tombstone до видалення з backend: drain write-through, що тримає посилання
1360
+ # на цей об'єкт, після DELETE не має зробити INSERT (зомбі-нода).
1361
+ _set_removed_flag(node, True)
1362
+
1342
1363
  # BUGFIX: у backend-режимі backend — джерело правди для
1343
1364
  # edges/adjacency. Делегуємо йому видалення (він почистить БД + власний
1344
1365
  # кеш edges + adjacency), інакше лишаються "мертві" edges у backend →
@@ -358,6 +358,8 @@ class Node(BaseModel):
358
358
  _lifecycle_lock: threading.Lock = PrivateAttr(default_factory=threading.Lock)
359
359
  # Лінки з ON_HTML_PARSED поточного enrich_node: переживають його переривання (per-node timeout).
360
360
  _discovered_links: list[str] = PrivateAttr(default_factory=list)
361
+ # Tombstone: Graph.remove_node видалив ноду — відкладений write-through не має її воскресити.
362
+ _removed_from_graph: bool = PrivateAttr(default=False)
361
363
 
362
364
  # Контент і обхід: хеші рахує enrich_node (дедуплікація, near-duplicates);
363
365
  # priority — з URL-правил для черги; lifecycle_stage змінює лише transition_state.
@@ -1,6 +1,6 @@
1
1
  """BrowserProfile — єдине джерело істини для fingerprint.
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §1.6/§1.7/§2: раніше UA, platform, screen,
3
+ UA, platform, screen,
4
4
  viewport, WebGL, hardwareConcurrency, languages, locale/timezone задавались у
5
5
  різних місцях (constants, StealthPlugin, EnhancedStealthPlugin, UserProfilePlugin)
6
6
  і між собою НЕ узгоджувались — це головна причина детекту. Тепер усе виводиться
@@ -1,6 +1,6 @@
1
1
  """Мережевий шар для Playwright-гілки.
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §4.4: proxy не підтримується в
3
+ proxy не підтримується в
4
4
  `PooledPlaywrightDriver` жодним чином → увесь флот сидить на одному IP,
5
5
  а locale/timezone/Accept-Language не пов'язані з GeoIP.
6
6
 
@@ -1,6 +1,5 @@
1
1
  """GeoResolver — виведення locale/timezone з проксі-запису (Крок 3).
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §2.6:
4
3
  IP з Німеччини + `timeZone: "UTC"` + `Accept-Language: en-US` +
5
4
  Windows-UA на Linux — чотири незалежні суперечності в ОДНОМУ запиті.
6
5
  Для Cloudflare/DataDome достатньо challenge без JS-аналізу.
@@ -1,6 +1,5 @@
1
1
  """ProxyPool — sticky-прив'язка «домен ↔ proxy».
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §4.4 / §5.4:
4
3
  Правильна архітектура:
5
4
 
6
5
  ProxyPool → обраний proxy → GeoIP → BrowserProfile → new_context()
@@ -1,6 +1,5 @@
1
1
  """DomainRateLimiter — per-domain concurrency + мінімальний інтервал (Крок 3).
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §3.2:
4
3
  Наявний `calculate_optimal_jitter` збільшує затримку між стартами,
5
4
  але **не обмежує concurrency per-domain**: 25 URL одного домену
6
5
  підуть у 25 паралельних вкладок з одного IP → 429/challenge раніше,
@@ -28,6 +28,7 @@ from graph_crawler.infrastructure.transport.core.redirect_utils import (
28
28
  )
29
29
  from graph_crawler.infrastructure.transport.playwright.context import BrowserContext
30
30
  from graph_crawler.infrastructure.transport.playwright.stages import BrowserStage
31
+ from graph_crawler.shared.utils.best_effort import close_quietly
31
32
  from graph_crawler.shared.utils.shadow_dom import expose_shadow_roots
32
33
 
33
34
  logger = logging.getLogger(__name__)
@@ -49,6 +50,11 @@ logger = logging.getLogger(__name__)
49
50
  # =============================================================================
50
51
  PARTIAL_TIMEOUT_STATUS = 504
51
52
 
53
+ # NEW-3-5: після fetch_timeout вкладку ще питають про частковий HTML і адресу; зависла вкладка
54
+ # (скрипт сторінки тримає її) не відповідає ніколи — без ліміту воркер чекав до кінця фази.
55
+ TIMEOUT_RECOVERY_S = 5.0
56
+ FROZEN_PAGE_CLOSE_S = 3.0
57
+
52
58
  # ``page.content()`` серіалізує лише light DOM: вміст відкритих shadow root'ів (веб-компоненти,
53
59
  # Lit/Stencil/Salesforce LWC, вбудовані віджети цін) у HTML не потрапляє, і парсер «не бачить»
54
60
  # того, що бачить користувач. Якщо на сторінці є відкриті shadow root'и, серіалізуємо DOM
@@ -228,12 +234,7 @@ class PageFetcher:
228
234
  timeout=float(self.fetch_timeout),
229
235
  )
230
236
  except asyncio.TimeoutError:
231
- # Спробувати отримати частковий HTML що вже завантажився
232
- partial_html = None
233
- async with protect.suppress(
234
- Exception, log=logger.debug, message="_fetch_with_page_impl"
235
- ):
236
- partial_html = await page.content()
237
+ partial_html, frozen = await self._partial_html_after_timeout(page, url)
237
238
  partial_html = self._drop_oversized_partial(partial_html, url)
238
239
 
239
240
  error_msg = f"Fetch timeout ({self.fetch_timeout}s) for {url}"
@@ -261,8 +262,18 @@ class PageFetcher:
261
262
  )
262
263
  # Навіть у fetch-timeout page.url може містити final URL.
263
264
  # Зберігаємо провенанс, щоб graph.handle_redirect() спрацював
264
- # для timeout-нод з JS-редіректом.
265
- ft_final, ft_chain, ft_hops = await self._build_playwright_provenance(url, page, None)
265
+ # для timeout-нод з JS-редіректом. Завислу вкладку не питаємо (NEW-3-5).
266
+ ft_final, ft_chain, ft_hops = url, [], []
267
+ if not frozen:
268
+ try:
269
+ ft_final, ft_chain, ft_hops = await asyncio.wait_for(
270
+ self._build_playwright_provenance(url, page, None),
271
+ timeout=TIMEOUT_RECOVERY_S,
272
+ )
273
+ except asyncio.TimeoutError:
274
+ frozen = True
275
+ if frozen:
276
+ await self._close_frozen_page(page, url)
266
277
  return self._finalize_response(
267
278
  FetchResponse(
268
279
  url=url,
@@ -282,6 +293,27 @@ class PageFetcher:
282
293
  logger.error(error_msg)
283
294
  return FetchResponse(url=url, html=None, status_code=None, headers={}, error=error_msg)
284
295
 
296
+ @staticmethod
297
+ async def _partial_html_after_timeout(page: Any, url: str) -> tuple[str | None, bool]:
298
+ """Частковий HTML після fetch_timeout і ознака «вкладка зависла» (не відповіла за ``TIMEOUT_RECOVERY_S``)."""
299
+ try:
300
+ return await asyncio.wait_for(page.content(), timeout=TIMEOUT_RECOVERY_S), False
301
+ except asyncio.TimeoutError:
302
+ logger.warning(
303
+ "Browser tab frozen after fetch timeout: page.content() did not answer in %.0fs for %s",
304
+ TIMEOUT_RECOVERY_S,
305
+ url,
306
+ )
307
+ return None, True
308
+ except Exception as e: # noqa: BLE001 — сторінка закрилась/переходить
309
+ logger.debug("partial content after timeout unavailable for %s: %s", url, e)
310
+ return None, False
311
+
312
+ @staticmethod
313
+ async def _close_frozen_page(page: Any, url: str) -> None:
314
+ """Закрита вкладка не повертається в пул — пул відкриє нову замість завислої."""
315
+ await close_quietly(page.close(), name=f"frozen page {url}", timeout=FROZEN_PAGE_CLOSE_S)
316
+
285
317
  @staticmethod
286
318
  def _log_fetch_timeout(
287
319
  error_msg: str,
@@ -1,6 +1,5 @@
1
1
  """BezierHumanBehaviorPlugin.
2
2
 
3
- ANTIBOT_AUDIT_pooled_driver.md §3.3:
4
3
  Існуючий `HumanBehaviorPlugin` виконує рухи миші прямолінійно
5
4
  (steps=3-5), а `_scroll_page()` у драйвері викликає
6
5
  `page.evaluate("window.scrollTo(...)")` — але події, ініційовані з
@@ -570,7 +570,7 @@ class PooledPlaywrightDriver(PageFetcher, BrowserPool, BatchScheduler, BaseDrive
570
570
  ) -> list[FetchResponse]:
571
571
  """Async паралельне завантаження багатьох сторінок.
572
572
 
573
- Аудит §1.9 (ANTIBOT_AUDIT_pooled_driver.md): раніше ці параметри
573
+ Ці параметри
574
574
  мовчки ігнорувались — тепер `referer` передається у `page.goto`
575
575
  per-URL, а `cookies` / `extra_headers` мержаться і застосовуються
576
576
  на рівні контексту (Playwright не дає per-URL headers/cookies при
@@ -660,7 +660,6 @@ DEFAULT_POST_NAVIGATION_WAIT_NETWORKIDLE_MS = 5000
660
660
  """
661
661
 
662
662
  # Playwright Stealth Mode Arguments
663
- # Аудит ANTIBOT_AUDIT_pooled_driver.md §1.3 / §1.14 / Крок 0:
664
663
  # прибрано `--disable-web-security` та `--disable-features=IsolateOrigins,site-per-process`
665
664
  # (вимкнення Site Isolation детектується як anti-stealth сигнал у реальному Chrome
666
665
  # такої конфігурації не буває) та `--disable-background-networking`
@@ -747,7 +746,6 @@ F15 (§11.2): 600 → 500 за реальним заміром — PSS дере
747
746
  Перевизначається env ``GRAPH_CRAWLER_BROWSER_RAM_BASELINE_MB``."""
748
747
 
749
748
  # Дефолтні ресурси для блокування (економія трафіку та RAM)
750
- # Аудит ANTIBOT_AUDIT_pooled_driver.md §2.5 / §3.5 / Крок 0:
751
749
  # прибрано "font" і "stylesheet" — жоден реальний браузер не вантажить HTML
752
750
  # без CSS/шрифтів; порожній network waterfall (нуль .css/.woff2) + зламаний
753
751
  # layout під getBoundingClientRect() = поведінковий маркер рівня «скрапер».