unrealon 1.1.1__py3-none-any.whl → 1.1.5__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 (83) hide show
  1. unrealon/__init__.py +16 -6
  2. unrealon-1.1.5.dist-info/METADATA +621 -0
  3. unrealon-1.1.5.dist-info/RECORD +54 -0
  4. {unrealon-1.1.1.dist-info → unrealon-1.1.5.dist-info}/entry_points.txt +1 -1
  5. unrealon_browser/__init__.py +3 -6
  6. unrealon_browser/core/browser_manager.py +86 -84
  7. unrealon_browser/dto/models/config.py +2 -0
  8. unrealon_browser/managers/captcha.py +165 -185
  9. unrealon_browser/managers/cookies.py +57 -28
  10. unrealon_browser/managers/logger_bridge.py +94 -34
  11. unrealon_browser/managers/profile.py +186 -158
  12. unrealon_browser/managers/stealth.py +58 -47
  13. unrealon_driver/__init__.py +8 -21
  14. unrealon_driver/exceptions.py +5 -0
  15. unrealon_driver/html_analyzer/__init__.py +32 -0
  16. unrealon_driver/{parser/managers/html.py → html_analyzer/cleaner.py} +330 -405
  17. unrealon_driver/html_analyzer/config.py +64 -0
  18. unrealon_driver/html_analyzer/manager.py +247 -0
  19. unrealon_driver/html_analyzer/models.py +115 -0
  20. unrealon_driver/html_analyzer/websocket_analyzer.py +157 -0
  21. unrealon_driver/models/__init__.py +31 -0
  22. unrealon_driver/models/websocket.py +98 -0
  23. unrealon_driver/parser/__init__.py +4 -23
  24. unrealon_driver/parser/cli_manager.py +6 -5
  25. unrealon_driver/parser/daemon_manager.py +242 -66
  26. unrealon_driver/parser/managers/__init__.py +0 -21
  27. unrealon_driver/parser/managers/config.py +15 -3
  28. unrealon_driver/parser/parser_manager.py +225 -395
  29. unrealon_driver/smart_logging/__init__.py +24 -0
  30. unrealon_driver/smart_logging/models.py +44 -0
  31. unrealon_driver/smart_logging/smart_logger.py +406 -0
  32. unrealon_driver/smart_logging/unified_logger.py +525 -0
  33. unrealon_driver/websocket/__init__.py +31 -0
  34. unrealon_driver/websocket/client.py +249 -0
  35. unrealon_driver/websocket/config.py +188 -0
  36. unrealon_driver/websocket/manager.py +90 -0
  37. unrealon-1.1.1.dist-info/METADATA +0 -722
  38. unrealon-1.1.1.dist-info/RECORD +0 -82
  39. unrealon_bridge/__init__.py +0 -114
  40. unrealon_bridge/cli.py +0 -316
  41. unrealon_bridge/client/__init__.py +0 -93
  42. unrealon_bridge/client/base.py +0 -78
  43. unrealon_bridge/client/commands.py +0 -89
  44. unrealon_bridge/client/connection.py +0 -90
  45. unrealon_bridge/client/events.py +0 -65
  46. unrealon_bridge/client/health.py +0 -38
  47. unrealon_bridge/client/html_parser.py +0 -146
  48. unrealon_bridge/client/logging.py +0 -139
  49. unrealon_bridge/client/proxy.py +0 -70
  50. unrealon_bridge/client/scheduler.py +0 -450
  51. unrealon_bridge/client/session.py +0 -70
  52. unrealon_bridge/configs/__init__.py +0 -14
  53. unrealon_bridge/configs/bridge_config.py +0 -212
  54. unrealon_bridge/configs/bridge_config.yaml +0 -39
  55. unrealon_bridge/models/__init__.py +0 -138
  56. unrealon_bridge/models/base.py +0 -28
  57. unrealon_bridge/models/command.py +0 -41
  58. unrealon_bridge/models/events.py +0 -40
  59. unrealon_bridge/models/html_parser.py +0 -79
  60. unrealon_bridge/models/logging.py +0 -55
  61. unrealon_bridge/models/parser.py +0 -63
  62. unrealon_bridge/models/proxy.py +0 -41
  63. unrealon_bridge/models/requests.py +0 -95
  64. unrealon_bridge/models/responses.py +0 -88
  65. unrealon_bridge/models/scheduler.py +0 -592
  66. unrealon_bridge/models/session.py +0 -28
  67. unrealon_bridge/server/__init__.py +0 -91
  68. unrealon_bridge/server/base.py +0 -171
  69. unrealon_bridge/server/handlers/__init__.py +0 -23
  70. unrealon_bridge/server/handlers/command.py +0 -110
  71. unrealon_bridge/server/handlers/html_parser.py +0 -139
  72. unrealon_bridge/server/handlers/logging.py +0 -95
  73. unrealon_bridge/server/handlers/parser.py +0 -95
  74. unrealon_bridge/server/handlers/proxy.py +0 -75
  75. unrealon_bridge/server/handlers/scheduler.py +0 -545
  76. unrealon_bridge/server/handlers/session.py +0 -66
  77. unrealon_driver/browser/__init__.py +0 -8
  78. unrealon_driver/browser/config.py +0 -74
  79. unrealon_driver/browser/manager.py +0 -416
  80. unrealon_driver/parser/managers/browser.py +0 -51
  81. unrealon_driver/parser/managers/logging.py +0 -609
  82. {unrealon-1.1.1.dist-info → unrealon-1.1.5.dist-info}/WHEEL +0 -0
  83. {unrealon-1.1.1.dist-info → unrealon-1.1.5.dist-info}/licenses/LICENSE +0 -0
@@ -8,13 +8,27 @@ import asyncio
8
8
  from pathlib import Path
9
9
  from typing import Dict, List, Optional, Any, Union
10
10
  from datetime import datetime, timezone
11
+ import logging
11
12
 
12
13
  # Browser DTOs
13
14
  from unrealon_browser.dto import ProxyInfo, CookieMetadata
15
+ from pydantic import BaseModel
14
16
 
15
17
  # Playwright imports
16
18
  from playwright.async_api import Page, BrowserContext
17
19
 
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class CookieSet(BaseModel):
24
+ proxy_info: ProxyInfo
25
+ cookies: Dict[str, str]
26
+ metadata: CookieMetadata
27
+
28
+
29
+ class CookieStorage(BaseModel):
30
+ cookies_array: List[CookieSet]
31
+
18
32
 
19
33
  class CookieManager:
20
34
  """
@@ -28,11 +42,12 @@ class CookieManager:
28
42
  - Support for multiple parsers
29
43
  """
30
44
 
31
- def __init__(self, cookies_dir: str = "cookies", parser_name: str = "default_parser"):
45
+ def __init__(self, cookies_dir: str = "cookies", parser_name: str = "default_parser", logger_bridge=None):
32
46
  """Initialize cookie manager"""
33
47
  self.cookies_dir = Path(cookies_dir)
34
48
  self.parser_name = parser_name
35
49
  self.cookies_file = self.cookies_dir / f"{parser_name}_cookies.json"
50
+ self.logger_bridge = logger_bridge
36
51
 
37
52
  # Create cookies directory if it doesn't exist
38
53
  self.cookies_dir.mkdir(parents=True, exist_ok=True)
@@ -48,6 +63,26 @@ class CookieManager:
48
63
  # Load existing cookies
49
64
  self._load_cookies_from_file()
50
65
 
66
+ def _logger(self, message: str, level: str = "info") -> None:
67
+ if self.logger_bridge:
68
+ if level == "info":
69
+ self.logger_bridge.log_info(message)
70
+ elif level == "error":
71
+ self.logger_bridge.log_error(message)
72
+ elif level == "warning":
73
+ self.logger_bridge.log_warning(message)
74
+ else:
75
+ self.logger_bridge.log_info(message)
76
+ else:
77
+ if level == "info":
78
+ logger.info(message)
79
+ elif level == "error":
80
+ logger.error(message)
81
+ elif level == "warning":
82
+ logger.warning(message)
83
+ else:
84
+ logger.info(message)
85
+
51
86
  def _generate_proxy_key(self, proxy_info: ProxyInfo) -> str:
52
87
  """Generate unique key for proxy configuration"""
53
88
  return f"{proxy_info.host}:{proxy_info.port}"
@@ -68,12 +103,12 @@ class CookieManager:
68
103
  self._current_cookies[proxy_key] = cookie_set
69
104
 
70
105
  self._proxies_with_cookies = len(self._current_cookies)
71
- print(f"🍪 Loaded cookies for {self._proxies_with_cookies} proxies")
106
+ self._logger(f"🍪 Loaded cookies for {self._proxies_with_cookies} proxies", "info")
72
107
  else:
73
- print(f"🍪 No existing cookies file found, starting fresh")
108
+ self._logger(f"🍪 No existing cookies file found, starting fresh", "info")
74
109
 
75
110
  except Exception as e:
76
- print(f"❌ Error loading cookies: {e}")
111
+ self._logger(f"❌ Error loading cookies: {e}", "error")
77
112
  self._current_cookies = {}
78
113
 
79
114
  def _save_cookies_to_file(self) -> None:
@@ -87,10 +122,10 @@ class CookieManager:
87
122
  with open(self.cookies_file, "w", encoding="utf-8") as f:
88
123
  json.dump(storage.model_dump(), f, indent=2, ensure_ascii=False, default=str)
89
124
 
90
- print(f"💾 Saved cookies for {len(cookies_array)} proxies to {self.cookies_file}")
125
+ self._logger(f"💾 Saved cookies for {len(cookies_array)} proxies to {self.cookies_file}", "info")
91
126
 
92
127
  except Exception as e:
93
- print(f"❌ Error saving cookies: {e}")
128
+ self._logger(f"❌ Error saving cookies: {e}", "error")
94
129
 
95
130
  async def load_cookies_for_proxy(self, page: Page, proxy_info: ProxyInfo) -> bool:
96
131
  """
@@ -108,7 +143,7 @@ class CookieManager:
108
143
  proxy_key = self._generate_proxy_key(proxy_info)
109
144
 
110
145
  if proxy_key not in self._current_cookies:
111
- print(f"🍪 No cookies found for proxy {proxy_key}")
146
+ self._logger(f"🍪 No cookies found for proxy {proxy_key}", "info")
112
147
  return False
113
148
 
114
149
  cookie_set = self._current_cookies[proxy_key]
@@ -130,12 +165,12 @@ class CookieManager:
130
165
  await context.add_cookies(playwright_cookies)
131
166
 
132
167
  self._cookies_loaded += 1
133
- print(f"✅ Loaded {len(playwright_cookies)} cookies for proxy {proxy_key}")
168
+ self._logger(f"✅ Loaded {len(playwright_cookies)} cookies for proxy {proxy_key}", "info")
134
169
 
135
170
  return True
136
171
 
137
172
  except Exception as e:
138
- print(f"❌ Error loading cookies for proxy {proxy_info.host}:{proxy_info.port}: {e}")
173
+ self._logger(f"❌ Error loading cookies for proxy {proxy_info.host}:{proxy_info.port}: {e}", "error")
139
174
  return False
140
175
 
141
176
  async def save_cookies_with_proxy(self, page: Page, proxy_info: ProxyInfo) -> bool:
@@ -156,7 +191,7 @@ class CookieManager:
156
191
  playwright_cookies = await context.cookies()
157
192
 
158
193
  if not playwright_cookies:
159
- print(f"🍪 No cookies to save for proxy {proxy_info.host}:{proxy_info.port}")
194
+ self._logger(f"🍪 No cookies to save for proxy {proxy_info.host}:{proxy_info.port}", "info")
160
195
  return False
161
196
 
162
197
  # Convert to our format
@@ -188,12 +223,12 @@ class CookieManager:
188
223
  self._cookies_saved += 1
189
224
  self._proxies_with_cookies = len(self._current_cookies)
190
225
 
191
- print(f"💾 Saved {len(cookies_dict)} cookies for proxy {proxy_key}")
226
+ self._logger(f"💾 Saved {len(cookies_dict)} cookies for proxy {proxy_key}", "info")
192
227
 
193
228
  return True
194
229
 
195
230
  except Exception as e:
196
- print(f"❌ Error saving cookies for proxy {proxy_info.host}:{proxy_info.port}: {e}")
231
+ self._logger(f"❌ Error saving cookies for proxy {proxy_info.host}:{proxy_info.port}: {e}", "error")
197
232
  return False
198
233
 
199
234
  def get_proxies_with_cookies(self) -> List[ProxyInfo]:
@@ -222,7 +257,7 @@ class CookieManager:
222
257
  del self._current_cookies[proxy_key]
223
258
  self._save_cookies_to_file()
224
259
  self._proxies_with_cookies = len(self._current_cookies)
225
- print(f"🗑️ Cleared cookies for proxy {proxy_key}")
260
+ self._logger(f"🗑️ Cleared cookies for proxy {proxy_key}", "info")
226
261
  return True
227
262
 
228
263
  return False
@@ -232,7 +267,7 @@ class CookieManager:
232
267
  self._current_cookies.clear()
233
268
  self._save_cookies_to_file()
234
269
  self._proxies_with_cookies = 0
235
- print("🗑️ Cleared all cookies")
270
+ self._logger("🗑️ Cleared all cookies", "info")
236
271
 
237
272
  def cleanup_old_cookies(self, max_age_days: int = 30) -> int:
238
273
  """
@@ -262,13 +297,11 @@ class CookieManager:
262
297
  if removed_count > 0:
263
298
  self._save_cookies_to_file()
264
299
  self._proxies_with_cookies = len(self._current_cookies)
265
- print(f"🧹 Cleaned up {removed_count} old cookie sets (>{max_age_days} days)")
300
+ self._logger(f"🧹 Cleaned up {removed_count} old cookie sets (>{max_age_days} days)", "info")
266
301
 
267
302
  return removed_count
268
303
 
269
- async def test_cookies_with_proxy(
270
- self, page: Page, proxy_info: ProxyInfo, test_url: str = "https://httpbin.org/cookies"
271
- ) -> Dict[str, Any]:
304
+ async def test_cookies_with_proxy(self, page: Page, proxy_info: ProxyInfo, test_url: str = "https://httpbin.org/cookies") -> Dict[str, Any]:
272
305
  """
273
306
  Test cookie functionality with specific proxy
274
307
 
@@ -322,9 +355,7 @@ class CookieManager:
322
355
  "cookies_loaded": self._cookies_loaded,
323
356
  "total_cookie_sets": len(self._current_cookies),
324
357
  "storage_file_exists": self.cookies_file.exists(),
325
- "storage_file_size_bytes": (
326
- self.cookies_file.stat().st_size if self.cookies_file.exists() else 0
327
- ),
358
+ "storage_file_size_bytes": (self.cookies_file.stat().st_size if self.cookies_file.exists() else 0),
328
359
  }
329
360
 
330
361
  def print_statistics(self) -> None:
@@ -341,14 +372,12 @@ class CookieManager:
341
372
 
342
373
  # Show proxy details
343
374
  if self._current_cookies:
344
- print(" Cookie details:")
375
+ self._logger(" Cookie details:", "info")
345
376
  for proxy_key, cookie_set in self._current_cookies.items():
346
377
  metadata = cookie_set.metadata
347
- print(
348
- f" {proxy_key}: {metadata.cookies_count} cookies (saved {metadata.saved_at.strftime('%Y-%m-%d %H:%M')})"
349
- )
378
+ self._logger(f" {proxy_key}: {metadata.cookies_count} cookies (saved {metadata.saved_at.strftime('%Y-%m-%d %H:%M')})", "info")
350
379
  else:
351
- print(" No cookies stored")
380
+ self._logger(" No cookies stored", "info")
352
381
 
353
382
  def export_cookies_for_proxy(self, proxy_info: ProxyInfo) -> Optional[Dict[str, Any]]:
354
383
  """
@@ -387,9 +416,9 @@ class CookieManager:
387
416
  self._save_cookies_to_file()
388
417
  self._proxies_with_cookies = len(self._current_cookies)
389
418
 
390
- print(f"📥 Imported cookies for proxy {proxy_key}")
419
+ self._logger(f"📥 Imported cookies for proxy {proxy_key}", "info")
391
420
  return True
392
421
 
393
422
  except Exception as e:
394
- print(f"❌ Error importing cookies: {e}")
423
+ self._logger(f"❌ Error importing cookies: {e}", "error")
395
424
  return False
@@ -14,8 +14,16 @@ from unrealon_browser.dto import (
14
14
  CaptchaDetectionResult,
15
15
  )
16
16
 
17
- # Import from unrealon_driver
18
- from unrealon_driver.parser.managers.logging import LoggingManager, LoggingConfig, LogLevel, get_logging_manager
17
+ # Smart logging with fallback to avoid circular imports
18
+ import logging
19
+
20
+ # Try to import smart logging, fallback to standard logging
21
+ try:
22
+ from unrealon_driver.smart_logging import create_unified_logger
23
+ from unrealon_driver.smart_logging.unified_logger import UnifiedLoggerConfig
24
+ SMART_LOGGING_AVAILABLE = True
25
+ except ImportError:
26
+ SMART_LOGGING_AVAILABLE = False
19
27
 
20
28
 
21
29
  class BrowserLoggerBridge:
@@ -29,17 +37,41 @@ class BrowserLoggerBridge:
29
37
  def __init__(
30
38
  self,
31
39
  session_id: Optional[str] = None,
32
- bridge_client: Optional[Any] = None,
40
+ parser_id: Optional[str] = None,
41
+ bridge_logs_url: Optional[str] = None,
33
42
  enable_console: bool = True,
34
43
  ):
35
44
  """Initialize logger bridge"""
36
45
  self.session_id = session_id or str(uuid.uuid4())
37
-
38
- # Create logging manager from driver
39
- self.logger = get_logging_manager(parser_name="unrealon_browser", bridge_client=bridge_client, console_enabled=enable_console, file_enabled=True, bridge_enabled=bridge_client is not None)
40
-
41
- # Set session context
42
- self.logger.set_session(self.session_id)
46
+ self.parser_id = parser_id or f"browser_{uuid.uuid4().hex[:8]}"
47
+
48
+ # Initialize logger based on availability
49
+ if SMART_LOGGING_AVAILABLE:
50
+ # Use smart logging if available
51
+ self.logger = create_unified_logger(
52
+ parser_id=self.parser_id,
53
+ parser_name="unrealon_browser",
54
+ bridge_logs_url=bridge_logs_url,
55
+ console_enabled=enable_console,
56
+ )
57
+ # Set session context
58
+ self.logger.set_session(self.session_id)
59
+ self._use_smart_logging = True
60
+ else:
61
+ # Fallback to standard Python logging
62
+ self.logger = logging.getLogger(f"unrealon_browser.{self.parser_id}")
63
+ self.logger.setLevel(logging.DEBUG)
64
+
65
+ # Add console handler if needed
66
+ if enable_console and not self.logger.handlers:
67
+ handler = logging.StreamHandler()
68
+ formatter = logging.Formatter(
69
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
70
+ )
71
+ handler.setFormatter(formatter)
72
+ self.logger.addHandler(handler)
73
+
74
+ self._use_smart_logging = False
43
75
 
44
76
  # Statistics
45
77
  self._events_logged = 0
@@ -56,25 +88,49 @@ class BrowserLoggerBridge:
56
88
 
57
89
  self._log_debug(f"BrowserLoggerBridge initialized for session {self.session_id}")
58
90
 
59
- def _log_debug(self, message: str, **context: Any) -> None:
60
- """Debug level logging using driver logger"""
91
+ def _log(self, level: str, message: str, **context: Any) -> None:
92
+ """Universal logging method"""
61
93
  self._events_logged += 1
62
- self.logger.debug(message, **context)
94
+
95
+ if self._use_smart_logging:
96
+ # Use smart logging with context
97
+ getattr(self.logger, level)(message, **context)
98
+ else:
99
+ # Use standard logging with formatted context
100
+ context_str = f" {context}" if context else ""
101
+ getattr(self.logger, level)(f"{message}{context_str}")
102
+
103
+ def _log_debug(self, message: str, **context: Any) -> None:
104
+ """Debug level logging"""
105
+ self._log("debug", message, **context)
106
+
107
+ def log_debug(self, message: str, **context: Any) -> None:
108
+ """Public debug level logging"""
109
+ self._log_debug(message, **context)
63
110
 
64
111
  def _log_info(self, message: str, **context: Any) -> None:
65
- """Info level logging using driver logger"""
66
- self._events_logged += 1
67
- self.logger.info(message, **context)
112
+ """Info level logging"""
113
+ self._log("info", message, **context)
114
+
115
+ def log_info(self, message: str, **context: Any) -> None:
116
+ """Public info level logging"""
117
+ self._log_info(message, **context)
68
118
 
69
119
  def _log_warning(self, message: str, **context: Any) -> None:
70
- """Warning level logging using driver logger"""
71
- self._events_logged += 1
72
- self.logger.warning(message, **context)
120
+ """Warning level logging"""
121
+ self._log("warning", message, **context)
122
+
123
+ def log_warning(self, message: str, **context: Any) -> None:
124
+ """Public warning level logging"""
125
+ self._log_warning(message, **context)
73
126
 
74
127
  def _log_error(self, message: str, **context: Any) -> None:
75
- """Error level logging using driver logger"""
76
- self._events_logged += 1
77
- self.logger.error(message, **context)
128
+ """Error level logging"""
129
+ self._log("error", message, **context)
130
+
131
+ def log_error(self, message: str, **context: Any) -> None:
132
+ """Public error level logging"""
133
+ self._log_error(message, **context)
78
134
 
79
135
  # Browser-specific logging methods
80
136
  def log_browser_initialized(self, metadata: BrowserSession) -> None:
@@ -192,40 +248,44 @@ class BrowserLoggerBridge:
192
248
  "total_events_logged": self._events_logged,
193
249
  "browser_events": self._browser_events.copy(),
194
250
  "session_id": self.session_id,
195
- "logger_stats": self.logger.get_log_stats(),
251
+ "parser_id": self.parser_id,
252
+ "logger_stats": {"events_logged": self._events_logged},
196
253
  }
197
254
 
198
255
  def print_statistics(self) -> None:
199
256
  """Print logging statistics"""
200
257
  stats = self.get_statistics()
201
258
 
202
- print("\n📊 Browser Logger Bridge Statistics:")
203
- print(f" Total events logged: {stats['total_events_logged']}")
204
- print(f" Session ID: {stats['session_id']}")
259
+ self._log_info("\n📊 Browser Logger Bridge Statistics:")
260
+ self._log_info(f" Total events logged: {stats['total_events_logged']}")
261
+ self._log_info(f" Session ID: {stats['session_id']}")
205
262
 
206
- print(" Browser events:")
263
+ self._log_info(" Browser events:")
207
264
  for event, count in stats["browser_events"].items():
208
- print(f" {event}: {count}")
265
+ self._log_info(f" {event}: {count}")
209
266
 
210
- print(" Logger stats:")
267
+ self._log_info(" Logger stats:")
211
268
  for key, value in stats["logger_stats"].items():
212
- print(f" {key}: {value}")
269
+ self._log_info(f" {key}: {value}")
213
270
 
214
271
 
215
272
  # Factory function for easy integration
216
273
  def create_browser_logger_bridge(
217
274
  session_id: Optional[str] = None,
218
- bridge_client: Optional[Any] = None,
275
+ parser_id: Optional[str] = None,
276
+ bridge_logs_url: Optional[str] = None,
219
277
  enable_console: bool = True,
220
278
  ) -> BrowserLoggerBridge:
221
279
  """
222
- Create browser logger bridge with driver integration
280
+ Create browser logger bridge with smart logging integration
223
281
 
224
- This function creates a logger bridge that uses the driver's LoggingManager
225
- for consistent logging across the ecosystem.
282
+ This function creates a logger bridge that uses the driver's UnifiedLogger
283
+ for consistent logging across the ecosystem with Rich console, WebSocket batching,
284
+ and structured logging.
226
285
  """
227
286
  return BrowserLoggerBridge(
228
287
  session_id=session_id,
229
- bridge_client=bridge_client,
288
+ parser_id=parser_id,
289
+ bridge_logs_url=bridge_logs_url,
230
290
  enable_console=enable_console,
231
291
  )