unrealon 1.1.5__py3-none-any.whl → 2.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. {unrealon-1.1.5.dist-info/licenses → unrealon-2.0.4.dist-info}/LICENSE +1 -1
  2. unrealon-2.0.4.dist-info/METADATA +491 -0
  3. unrealon-2.0.4.dist-info/RECORD +129 -0
  4. {unrealon-1.1.5.dist-info → unrealon-2.0.4.dist-info}/WHEEL +2 -1
  5. unrealon-2.0.4.dist-info/entry_points.txt +3 -0
  6. unrealon-2.0.4.dist-info/top_level.txt +3 -0
  7. unrealon_browser/__init__.py +5 -2
  8. unrealon_browser/cli/browser_cli.py +18 -9
  9. unrealon_browser/cli/interactive_mode.py +18 -7
  10. unrealon_browser/core/browser_manager.py +76 -13
  11. unrealon_browser/dto/__init__.py +21 -0
  12. unrealon_browser/dto/bot_detection.py +175 -0
  13. unrealon_browser/dto/models/config.py +14 -1
  14. unrealon_browser/managers/__init__.py +4 -1
  15. unrealon_browser/managers/logger_bridge.py +3 -6
  16. unrealon_browser/managers/page_wait_manager.py +198 -0
  17. unrealon_browser/stealth/__init__.py +27 -0
  18. unrealon_browser/stealth/bypass_techniques.pyc +0 -0
  19. unrealon_browser/stealth/manager.pyc +0 -0
  20. unrealon_browser/stealth/nodriver_stealth.pyc +0 -0
  21. unrealon_browser/stealth/playwright_stealth.pyc +0 -0
  22. unrealon_browser/stealth/scanner_tester.pyc +0 -0
  23. unrealon_browser/stealth/undetected_chrome.pyc +0 -0
  24. unrealon_core/__init__.py +160 -0
  25. unrealon_core/config/__init__.py +16 -0
  26. unrealon_core/config/environment.py +98 -0
  27. unrealon_core/config/urls.py +93 -0
  28. unrealon_core/enums/__init__.py +24 -0
  29. unrealon_core/enums/status.py +216 -0
  30. unrealon_core/enums/types.py +240 -0
  31. unrealon_core/error_handling/__init__.py +45 -0
  32. unrealon_core/error_handling/circuit_breaker.py +292 -0
  33. unrealon_core/error_handling/error_context.py +324 -0
  34. unrealon_core/error_handling/recovery.py +371 -0
  35. unrealon_core/error_handling/retry.py +268 -0
  36. unrealon_core/exceptions/__init__.py +46 -0
  37. unrealon_core/exceptions/base.py +292 -0
  38. unrealon_core/exceptions/communication.py +22 -0
  39. unrealon_core/exceptions/driver.py +11 -0
  40. unrealon_core/exceptions/proxy.py +11 -0
  41. unrealon_core/exceptions/task.py +12 -0
  42. unrealon_core/exceptions/validation.py +17 -0
  43. unrealon_core/models/__init__.py +98 -0
  44. unrealon_core/models/arq_context.py +252 -0
  45. unrealon_core/models/arq_responses.py +125 -0
  46. unrealon_core/models/base.py +291 -0
  47. unrealon_core/models/bridge_stats.py +58 -0
  48. unrealon_core/models/communication.py +39 -0
  49. unrealon_core/models/config.py +47 -0
  50. unrealon_core/models/connection_stats.py +47 -0
  51. unrealon_core/models/driver.py +30 -0
  52. unrealon_core/models/driver_details.py +98 -0
  53. unrealon_core/models/logging.py +28 -0
  54. unrealon_core/models/task.py +21 -0
  55. unrealon_core/models/typed_responses.py +210 -0
  56. unrealon_core/models/websocket/__init__.py +91 -0
  57. unrealon_core/models/websocket/base.py +49 -0
  58. unrealon_core/models/websocket/config.py +200 -0
  59. unrealon_core/models/websocket/driver.py +215 -0
  60. unrealon_core/models/websocket/errors.py +138 -0
  61. unrealon_core/models/websocket/heartbeat.py +100 -0
  62. unrealon_core/models/websocket/logging.py +261 -0
  63. unrealon_core/models/websocket/proxy.py +496 -0
  64. unrealon_core/models/websocket/tasks.py +275 -0
  65. unrealon_core/models/websocket/utils.py +153 -0
  66. unrealon_core/models/websocket_session.py +144 -0
  67. unrealon_core/monitoring/__init__.py +43 -0
  68. unrealon_core/monitoring/alerts.py +398 -0
  69. unrealon_core/monitoring/dashboard.py +307 -0
  70. unrealon_core/monitoring/health_check.py +354 -0
  71. unrealon_core/monitoring/metrics.py +352 -0
  72. unrealon_core/utils/__init__.py +11 -0
  73. unrealon_core/utils/time.py +61 -0
  74. unrealon_core/version.py +219 -0
  75. unrealon_driver/__init__.py +88 -50
  76. unrealon_driver/core_module/__init__.py +34 -0
  77. unrealon_driver/core_module/base.py +184 -0
  78. unrealon_driver/core_module/config.py +30 -0
  79. unrealon_driver/core_module/event_manager.py +127 -0
  80. unrealon_driver/core_module/protocols.py +98 -0
  81. unrealon_driver/core_module/registry.py +146 -0
  82. unrealon_driver/decorators/__init__.py +15 -0
  83. unrealon_driver/decorators/retry.py +117 -0
  84. unrealon_driver/decorators/schedule.py +137 -0
  85. unrealon_driver/decorators/task.py +61 -0
  86. unrealon_driver/decorators/timing.py +132 -0
  87. unrealon_driver/driver/__init__.py +20 -0
  88. unrealon_driver/driver/communication/__init__.py +10 -0
  89. unrealon_driver/driver/communication/session.py +203 -0
  90. unrealon_driver/driver/communication/websocket_client.py +197 -0
  91. unrealon_driver/driver/core/__init__.py +10 -0
  92. unrealon_driver/driver/core/config.py +85 -0
  93. unrealon_driver/driver/core/driver.py +221 -0
  94. unrealon_driver/driver/factory/__init__.py +9 -0
  95. unrealon_driver/driver/factory/manager_factory.py +130 -0
  96. unrealon_driver/driver/lifecycle/__init__.py +11 -0
  97. unrealon_driver/driver/lifecycle/daemon.py +76 -0
  98. unrealon_driver/driver/lifecycle/initialization.py +97 -0
  99. unrealon_driver/driver/lifecycle/shutdown.py +48 -0
  100. unrealon_driver/driver/monitoring/__init__.py +9 -0
  101. unrealon_driver/driver/monitoring/health.py +63 -0
  102. unrealon_driver/driver/utilities/__init__.py +10 -0
  103. unrealon_driver/driver/utilities/logging.py +51 -0
  104. unrealon_driver/driver/utilities/serialization.py +61 -0
  105. unrealon_driver/managers/__init__.py +32 -0
  106. unrealon_driver/managers/base.py +174 -0
  107. unrealon_driver/managers/browser.py +98 -0
  108. unrealon_driver/managers/cache.py +116 -0
  109. unrealon_driver/managers/http.py +107 -0
  110. unrealon_driver/managers/logger.py +286 -0
  111. unrealon_driver/managers/proxy.py +99 -0
  112. unrealon_driver/managers/registry.py +87 -0
  113. unrealon_driver/managers/threading.py +54 -0
  114. unrealon_driver/managers/update.py +107 -0
  115. unrealon_driver/utils/__init__.py +9 -0
  116. unrealon_driver/utils/time.py +10 -0
  117. unrealon/__init__.py +0 -40
  118. unrealon-1.1.5.dist-info/METADATA +0 -621
  119. unrealon-1.1.5.dist-info/RECORD +0 -54
  120. unrealon-1.1.5.dist-info/entry_points.txt +0 -9
  121. unrealon_browser/managers/stealth.py +0 -388
  122. unrealon_driver/exceptions.py +0 -33
  123. unrealon_driver/html_analyzer/__init__.py +0 -32
  124. unrealon_driver/html_analyzer/cleaner.py +0 -657
  125. unrealon_driver/html_analyzer/config.py +0 -64
  126. unrealon_driver/html_analyzer/manager.py +0 -247
  127. unrealon_driver/html_analyzer/models.py +0 -115
  128. unrealon_driver/html_analyzer/websocket_analyzer.py +0 -157
  129. unrealon_driver/models/__init__.py +0 -31
  130. unrealon_driver/models/websocket.py +0 -98
  131. unrealon_driver/parser/__init__.py +0 -36
  132. unrealon_driver/parser/cli_manager.py +0 -142
  133. unrealon_driver/parser/daemon_manager.py +0 -403
  134. unrealon_driver/parser/managers/__init__.py +0 -25
  135. unrealon_driver/parser/managers/config.py +0 -293
  136. unrealon_driver/parser/managers/error.py +0 -412
  137. unrealon_driver/parser/managers/result.py +0 -321
  138. unrealon_driver/parser/parser_manager.py +0 -458
  139. unrealon_driver/smart_logging/__init__.py +0 -24
  140. unrealon_driver/smart_logging/models.py +0 -44
  141. unrealon_driver/smart_logging/smart_logger.py +0 -406
  142. unrealon_driver/smart_logging/unified_logger.py +0 -525
  143. unrealon_driver/websocket/__init__.py +0 -31
  144. unrealon_driver/websocket/client.py +0 -249
  145. unrealon_driver/websocket/config.py +0 -188
  146. unrealon_driver/websocket/manager.py +0 -90
@@ -1,388 +0,0 @@
1
- """
2
- Stealth Manager - Anti-detection system for browser automation
3
- Layer 1: Advanced stealth capabilities inspired by unrealparser
4
- """
5
-
6
- import logging
7
- import asyncio
8
- from typing import Dict, Any, Optional, List
9
- from playwright.async_api import Page, BrowserContext
10
-
11
- # CRITICAL REQUIREMENTS COMPLIANCE - NO INLINE IMPORTS!
12
- from playwright_stealth import stealth, Stealth
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
-
17
- class StealthManager:
18
- """
19
- Advanced anti-detection system for browser automation
20
-
21
- Layer 1: Stealth capabilities
22
- - Playwright-stealth integration
23
- - WebDriver property removal
24
- - Bot detection testing
25
- - Stealth arguments optimization
26
- """
27
-
28
- def __init__(self, logger_bridge=None):
29
- """Initialize stealth manager"""
30
- self.stealth_applied = False
31
- self.test_results: Optional[Dict[str, Any]] = None
32
- self.logger_bridge = logger_bridge
33
-
34
- def get_stealth_args(self) -> List[str]:
35
- """
36
- Get browser launch arguments for stealth mode
37
- Based on unrealparser's proven stealth arguments
38
- """
39
- return [
40
- # Minimal stealth arguments from working unrealparser code
41
- "--disable-blink-features=AutomationControlled", # Remove navigator.webdriver
42
- "--no-sandbox", # Required for container environments
43
- "--disable-dev-shm-usage", # Fix memory issues in containers
44
- # Additional safe arguments for better stealth
45
- "--disable-extensions",
46
- "--no-first-run",
47
- "--no-default-browser-check",
48
- ]
49
-
50
- # private warpper for logger with if self.logger_bridge
51
- def _logger(self, message: str, level: str = "info") -> None:
52
- if self.logger_bridge:
53
- if level == "info":
54
- self.logger_bridge.log_info(message)
55
- elif level == "error":
56
- self.logger_bridge.log_error(message)
57
- elif level == "warning":
58
- self.logger_bridge.log_warning(message)
59
- else:
60
- self.logger_bridge.log_info(message)
61
- else:
62
- if level == "info":
63
- logger.info(message)
64
- elif level == "error":
65
- logger.error(message)
66
- elif level == "warning":
67
- logger.warning(message)
68
- else:
69
- logger.info(message)
70
-
71
- async def apply_stealth(self, page: Page) -> bool:
72
- """
73
- Apply stealth measures to page
74
- Combines multiple anti-detection techniques
75
- """
76
- try:
77
- self._logger("🥷 Applying stealth measures...", "info")
78
-
79
- # 1. Apply playwright-stealth if available
80
- stealth_applied = await self._apply_playwright_stealth(page)
81
-
82
- # 2. Remove webdriver property
83
- await self._remove_webdriver_property(page)
84
-
85
- # 3. Apply additional stealth scripts
86
- await self._apply_custom_stealth_scripts(page)
87
-
88
- # 4. Set realistic properties
89
- await self._set_realistic_properties(page)
90
-
91
- self.stealth_applied = True
92
- self._logger("✅ Stealth measures applied successfully", "info")
93
-
94
- return True
95
-
96
- except Exception as e:
97
- self._logger(f"❌ Failed to apply stealth measures: {e}", "error")
98
- self.stealth_applied = False
99
- return False
100
-
101
- async def _apply_playwright_stealth(self, page: Page) -> bool:
102
- """Apply playwright-stealth with custom config"""
103
- try:
104
- # 🔥 WEBDRIVER ONLY CONFIG: Only remove webdriver, nothing else!
105
- stealth_config = Stealth(
106
- navigator_webdriver=True, # ONLY webdriver removal
107
- chrome_runtime=False, # DISABLE - we do it ourselves
108
- navigator_languages=False, # DISABLE - we do it ourselves
109
- navigator_permissions=False, # DISABLE - we do it ourselves
110
- navigator_plugins=False, # DISABLE - we do it ourselves
111
- webgl_vendor=False, # DISABLE - we do it ourselves
112
- chrome_app=False, # DISABLE
113
- chrome_csi=False, # DISABLE
114
- chrome_load_times=False, # DISABLE
115
- iframe_content_window=False, # DISABLE
116
- media_codecs=False, # DISABLE
117
- navigator_user_agent=False, # DISABLE
118
- navigator_vendor=False, # DISABLE
119
- navigator_platform=False, # DISABLE
120
- hairline=False, # DISABLE
121
- sec_ch_ua=False, # DISABLE
122
- navigator_hardware_concurrency=False, # DISABLE
123
- )
124
-
125
- await stealth(page, config=stealth_config)
126
- self._logger("✅ Playwright-stealth applied with CUSTOM config", "info")
127
- return True
128
- except Exception as e:
129
- self._logger(f"❌ playwright-stealth failed: {e}", "error")
130
- return False
131
-
132
- async def _remove_webdriver_property(self, page: Page) -> None:
133
- """Remove navigator.webdriver property - HANDLED BY PLAYWRIGHT-STEALTH"""
134
- # 🔥 REDUNDANT: playwright-stealth already does this with webdriver=True
135
- self._logger("✅ WebDriver property removal handled by playwright-stealth", "info")
136
-
137
- async def _apply_custom_stealth_scripts(self, page: Page) -> None:
138
- """Apply custom stealth scripts"""
139
- # Create proper chrome object (bot.sannysoft.com expects this!)
140
- chrome_runtime_script = """
141
- // Create realistic window.chrome object
142
- if (!window.chrome) {
143
- window.chrome = {
144
- app: {
145
- isInstalled: false,
146
- },
147
- runtime: {
148
- onConnect: {
149
- addListener: function() {},
150
- hasListener: function() { return false; },
151
- removeListener: function() {},
152
- },
153
- onMessage: {
154
- addListener: function() {},
155
- hasListener: function() { return false; },
156
- removeListener: function() {},
157
- },
158
- connect: function() { return {}; },
159
- sendMessage: function() {},
160
- },
161
- storage: {
162
- local: {
163
- get: function() {},
164
- set: function() {},
165
- remove: function() {},
166
- clear: function() {},
167
- },
168
- sync: {
169
- get: function() {},
170
- set: function() {},
171
- remove: function() {},
172
- clear: function() {},
173
- },
174
- },
175
- tabs: {
176
- create: function() {},
177
- query: function() {},
178
- update: function() {},
179
- },
180
- };
181
- }
182
- """
183
- await page.add_init_script(chrome_runtime_script)
184
-
185
- # Override permissions
186
- permissions_script = """
187
- const originalQuery = window.navigator.permissions.query;
188
- window.navigator.permissions.query = (parameters) => (
189
- parameters.name === 'notifications' ?
190
- Promise.resolve({ state: Notification.permission }) :
191
- originalQuery(parameters)
192
- );
193
- """
194
- await page.add_init_script(permissions_script)
195
-
196
- self._logger("✅ Custom stealth scripts applied", "info")
197
-
198
- async def _set_realistic_properties(self, page: Page) -> None:
199
- """Set realistic browser properties"""
200
- realistic_script = """
201
- // Set realistic hardwareConcurrency
202
- Object.defineProperty(navigator, 'hardwareConcurrency', {
203
- get: () => 4,
204
- });
205
-
206
- // Set realistic deviceMemory
207
- Object.defineProperty(navigator, 'deviceMemory', {
208
- get: () => 8,
209
- });
210
-
211
- // Set realistic connection
212
- Object.defineProperty(navigator, 'connection', {
213
- get: () => ({
214
- effectiveType: '4g',
215
- rtt: 50,
216
- downlink: 10,
217
- }),
218
- });
219
- """
220
- await page.add_init_script(realistic_script)
221
- self._logger("✅ Realistic properties set", "info")
222
-
223
- async def test_stealth_on_sannysoft(self, browser_manager) -> Dict[str, Any]:
224
- """
225
- Test stealth effectiveness on bot.sannysoft.com
226
- Based on unrealparser's stealth testing approach
227
- """
228
- if not browser_manager or not browser_manager.page:
229
- return {
230
- "success": False,
231
- "error": "Browser manager or page not available",
232
- "skipped": True,
233
- }
234
-
235
- try:
236
- self._logger("🧪 Testing stealth on bot.sannysoft.com...", "info")
237
-
238
- # Navigate to test page
239
- test_url = "https://bot.sannysoft.com/"
240
- result = await browser_manager.navigate_async(test_url, wait_for="body")
241
-
242
- if not result["success"]:
243
- return {
244
- "success": False,
245
- "error": f"Failed to load test page: {result['error']}",
246
- "skipped": False,
247
- }
248
-
249
- # Wait for page to fully load
250
- await asyncio.sleep(3)
251
-
252
- # Extract test results
253
- page_content = await browser_manager.get_page_content_async()
254
- if not page_content:
255
- return {
256
- "success": False,
257
- "error": "Failed to get page content",
258
- "skipped": False,
259
- }
260
-
261
- # Parse results using simple text analysis
262
- test_results = await self._parse_sannysoft_results(page_content)
263
-
264
- # Store results
265
- self.test_results = test_results
266
-
267
- self._logger("✅ Stealth test completed", "info")
268
- self._logger(f" Detection score: {test_results.get('detection_score', 'Unknown')}", "info")
269
- self._logger(f"Tests passed: {test_results.get('tests_passed', 0)}/{test_results.get('total_tests', 0)}")
270
-
271
- return {
272
- "success": True,
273
- "results": test_results,
274
- "error": None,
275
- "skipped": False,
276
- }
277
-
278
- except Exception as e:
279
- self._logger(f"❌ Stealth test failed: {e}", "error")
280
- return {
281
- "success": False,
282
- "error": str(e),
283
- "skipped": False,
284
- }
285
-
286
- async def _parse_sannysoft_results(self, content: str) -> Dict[str, Any]:
287
- """Parse sannysoft test results from page content"""
288
- results = {
289
- "webdriver_detected": "webdriver" in content.lower(),
290
- "chrome_detected": "chrome" in content.lower(),
291
- "permissions_detected": "permissions" in content.lower(),
292
- "plugins_detected": "plugins" in content.lower(),
293
- "languages_detected": "languages" in content.lower(),
294
- "total_tests": 0,
295
- "tests_passed": 0,
296
- "detection_score": "Unknown",
297
- }
298
-
299
- # Count basic detection indicators
300
- detection_indicators = [
301
- results["webdriver_detected"],
302
- results["chrome_detected"],
303
- results["permissions_detected"],
304
- results["plugins_detected"],
305
- results["languages_detected"],
306
- ]
307
-
308
- results["total_tests"] = len(detection_indicators)
309
- results["tests_passed"] = len([x for x in detection_indicators if not x])
310
-
311
- # Calculate detection score
312
- if results["total_tests"] > 0:
313
- pass_rate = results["tests_passed"] / results["total_tests"]
314
- if pass_rate >= 0.8:
315
- results["detection_score"] = "Excellent"
316
- elif pass_rate >= 0.6:
317
- results["detection_score"] = "Good"
318
- elif pass_rate >= 0.4:
319
- results["detection_score"] = "Fair"
320
- else:
321
- results["detection_score"] = "Poor"
322
-
323
- return results
324
-
325
- def get_stealth_status(self) -> Dict[str, Any]:
326
- """Get current stealth status and test results"""
327
- return {
328
- "stealth_applied": self.stealth_applied,
329
- "test_results": self.test_results,
330
- }
331
-
332
- def print_stealth_status(self) -> None:
333
- """Print current stealth status"""
334
- status = self.get_stealth_status()
335
-
336
- self._logger("\n🥷 Stealth Status:", "info")
337
- self._logger(f"Applied: {status['stealth_applied']}", "info")
338
-
339
- if status["test_results"]:
340
- results = status["test_results"]
341
- self._logger(f" Last test score: {results.get('detection_score', 'Unknown')}", "info")
342
- self._logger(f"Tests passed: {results.get('tests_passed', 0)}/{results.get('total_tests', 0)}")
343
-
344
- async def apply_stealth_to_context(self, context: BrowserContext) -> bool:
345
- """Apply stealth measures to entire browser context"""
346
- try:
347
- self._logger("🥷 Applying stealth to browser context...", "info")
348
-
349
- # SIMPLE OLD STYLE SCRIPT - exactly like working unrealparser!
350
- stealth_script = """
351
- if (navigator.webdriver !== undefined) {
352
- delete Object.getPrototypeOf(navigator).webdriver;
353
- }
354
- """
355
-
356
- await context.add_init_script(stealth_script)
357
- self._logger("✅ Context stealth script applied", "info")
358
-
359
- return True
360
-
361
- except Exception as e:
362
- self._logger(f"❌ Failed to apply context stealth: {e}", "error")
363
- return False
364
-
365
- async def apply_webdriver_removal(self, context) -> bool:
366
- """
367
- Remove navigator.webdriver property from context - OLD STYLE method like unrealparser
368
-
369
- Args:
370
- context: Playwright browser context
371
-
372
- Returns:
373
- True if successful, False otherwise
374
- """
375
- try:
376
- # Remove navigator.webdriver property before page creation - EXACTLY like old unrealparser
377
- await context.add_init_script(
378
- """
379
- if (navigator.webdriver !== undefined) {
380
- delete Object.getPrototypeOf(navigator).webdriver;
381
- }
382
- """
383
- )
384
- self._logger("✅ Webdriver removal script applied (OLD STYLE)", "info")
385
- return True
386
- except Exception as e:
387
- self._logger(f"❌ Error applying webdriver removal: {e}", "error")
388
- return False
@@ -1,33 +0,0 @@
1
- """
2
- UnrealOn Driver exceptions
3
- """
4
-
5
-
6
- class ParserError(Exception):
7
- """Base exception for parser errors"""
8
-
9
- pass
10
-
11
-
12
- class BrowserError(ParserError):
13
- """Browser-related errors"""
14
-
15
- pass
16
-
17
-
18
- class HTMLCleaningError(ParserError):
19
- """HTML cleaning errors"""
20
-
21
- pass
22
-
23
-
24
- class ConfigurationError(ParserError):
25
- """Configuration errors"""
26
-
27
- pass
28
-
29
-
30
- class ConnectionError(ParserError):
31
- """Connection errors"""
32
-
33
- pass
@@ -1,32 +0,0 @@
1
- """
2
- HTML Analyzer module for unrealon_driver.
3
-
4
- Provides intelligent HTML processing, cleaning, and analysis with WebSocket communication.
5
- """
6
-
7
- from .manager import HTMLAnalyzer, create_html_analyzer
8
- from .config import HTMLAnalyzerConfig, HTMLCleaningConfig
9
- from .cleaner import HTMLCleaner, HTMLCleaningStats
10
- from .websocket_analyzer import WebSocketHTMLAnalyzer
11
- from .models import HTMLAnalysisResult, HTMLParseResult, HTMLAnalyzerStats, HTMLAnalysisRequest, HTMLParseRequest, HTMLAnalyzerError, HTMLCleaningError, HTMLAnalysisError, WebSocketAnalysisError
12
-
13
- __all__ = [
14
- "HTMLAnalyzer",
15
- "HTMLAnalyzerConfig",
16
- "HTMLCleaningConfig",
17
- "HTMLCleaningStats",
18
- "HTMLCleaner",
19
- "WebSocketHTMLAnalyzer",
20
- "create_html_analyzer",
21
- # Models
22
- "HTMLAnalysisResult",
23
- "HTMLParseResult",
24
- "HTMLAnalyzerStats",
25
- "HTMLAnalysisRequest",
26
- "HTMLParseRequest",
27
- # Exceptions
28
- "HTMLAnalyzerError",
29
- "HTMLCleaningError",
30
- "HTMLAnalysisError",
31
- "WebSocketAnalysisError",
32
- ]