unrealon 1.1.6__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.
- {unrealon-1.1.6.dist-info/licenses → unrealon-2.0.4.dist-info}/LICENSE +1 -1
- unrealon-2.0.4.dist-info/METADATA +491 -0
- unrealon-2.0.4.dist-info/RECORD +129 -0
- {unrealon-1.1.6.dist-info → unrealon-2.0.4.dist-info}/WHEEL +2 -1
- unrealon-2.0.4.dist-info/entry_points.txt +3 -0
- unrealon-2.0.4.dist-info/top_level.txt +3 -0
- unrealon_browser/__init__.py +5 -6
- unrealon_browser/cli/browser_cli.py +18 -9
- unrealon_browser/cli/interactive_mode.py +13 -4
- unrealon_browser/core/browser_manager.py +29 -16
- unrealon_browser/dto/__init__.py +21 -0
- unrealon_browser/dto/bot_detection.py +175 -0
- unrealon_browser/dto/models/config.py +9 -3
- unrealon_browser/managers/__init__.py +1 -1
- unrealon_browser/managers/logger_bridge.py +1 -4
- unrealon_browser/stealth/__init__.py +27 -0
- unrealon_browser/stealth/bypass_techniques.pyc +0 -0
- unrealon_browser/stealth/manager.pyc +0 -0
- unrealon_browser/stealth/nodriver_stealth.pyc +0 -0
- unrealon_browser/stealth/playwright_stealth.pyc +0 -0
- unrealon_browser/stealth/scanner_tester.pyc +0 -0
- unrealon_browser/stealth/undetected_chrome.pyc +0 -0
- unrealon_core/__init__.py +160 -0
- unrealon_core/config/__init__.py +16 -0
- unrealon_core/config/environment.py +98 -0
- unrealon_core/config/urls.py +93 -0
- unrealon_core/enums/__init__.py +24 -0
- unrealon_core/enums/status.py +216 -0
- unrealon_core/enums/types.py +240 -0
- unrealon_core/error_handling/__init__.py +45 -0
- unrealon_core/error_handling/circuit_breaker.py +292 -0
- unrealon_core/error_handling/error_context.py +324 -0
- unrealon_core/error_handling/recovery.py +371 -0
- unrealon_core/error_handling/retry.py +268 -0
- unrealon_core/exceptions/__init__.py +46 -0
- unrealon_core/exceptions/base.py +292 -0
- unrealon_core/exceptions/communication.py +22 -0
- unrealon_core/exceptions/driver.py +11 -0
- unrealon_core/exceptions/proxy.py +11 -0
- unrealon_core/exceptions/task.py +12 -0
- unrealon_core/exceptions/validation.py +17 -0
- unrealon_core/models/__init__.py +98 -0
- unrealon_core/models/arq_context.py +252 -0
- unrealon_core/models/arq_responses.py +125 -0
- unrealon_core/models/base.py +291 -0
- unrealon_core/models/bridge_stats.py +58 -0
- unrealon_core/models/communication.py +39 -0
- unrealon_core/models/config.py +47 -0
- unrealon_core/models/connection_stats.py +47 -0
- unrealon_core/models/driver.py +30 -0
- unrealon_core/models/driver_details.py +98 -0
- unrealon_core/models/logging.py +28 -0
- unrealon_core/models/task.py +21 -0
- unrealon_core/models/typed_responses.py +210 -0
- unrealon_core/models/websocket/__init__.py +91 -0
- unrealon_core/models/websocket/base.py +49 -0
- unrealon_core/models/websocket/config.py +200 -0
- unrealon_core/models/websocket/driver.py +215 -0
- unrealon_core/models/websocket/errors.py +138 -0
- unrealon_core/models/websocket/heartbeat.py +100 -0
- unrealon_core/models/websocket/logging.py +261 -0
- unrealon_core/models/websocket/proxy.py +496 -0
- unrealon_core/models/websocket/tasks.py +275 -0
- unrealon_core/models/websocket/utils.py +153 -0
- unrealon_core/models/websocket_session.py +144 -0
- unrealon_core/monitoring/__init__.py +43 -0
- unrealon_core/monitoring/alerts.py +398 -0
- unrealon_core/monitoring/dashboard.py +307 -0
- unrealon_core/monitoring/health_check.py +354 -0
- unrealon_core/monitoring/metrics.py +352 -0
- unrealon_core/utils/__init__.py +11 -0
- unrealon_core/utils/time.py +61 -0
- unrealon_core/version.py +219 -0
- unrealon_driver/__init__.py +90 -51
- unrealon_driver/core_module/__init__.py +34 -0
- unrealon_driver/core_module/base.py +184 -0
- unrealon_driver/core_module/config.py +30 -0
- unrealon_driver/core_module/event_manager.py +127 -0
- unrealon_driver/core_module/protocols.py +98 -0
- unrealon_driver/core_module/registry.py +146 -0
- unrealon_driver/decorators/__init__.py +15 -0
- unrealon_driver/decorators/retry.py +117 -0
- unrealon_driver/decorators/schedule.py +137 -0
- unrealon_driver/decorators/task.py +61 -0
- unrealon_driver/decorators/timing.py +132 -0
- unrealon_driver/driver/__init__.py +20 -0
- unrealon_driver/driver/communication/__init__.py +10 -0
- unrealon_driver/driver/communication/session.py +203 -0
- unrealon_driver/driver/communication/websocket_client.py +197 -0
- unrealon_driver/driver/core/__init__.py +10 -0
- unrealon_driver/driver/core/config.py +85 -0
- unrealon_driver/driver/core/driver.py +221 -0
- unrealon_driver/driver/factory/__init__.py +9 -0
- unrealon_driver/driver/factory/manager_factory.py +130 -0
- unrealon_driver/driver/lifecycle/__init__.py +11 -0
- unrealon_driver/driver/lifecycle/daemon.py +76 -0
- unrealon_driver/driver/lifecycle/initialization.py +97 -0
- unrealon_driver/driver/lifecycle/shutdown.py +48 -0
- unrealon_driver/driver/monitoring/__init__.py +9 -0
- unrealon_driver/driver/monitoring/health.py +63 -0
- unrealon_driver/driver/utilities/__init__.py +10 -0
- unrealon_driver/driver/utilities/logging.py +51 -0
- unrealon_driver/driver/utilities/serialization.py +61 -0
- unrealon_driver/managers/__init__.py +32 -0
- unrealon_driver/managers/base.py +174 -0
- unrealon_driver/managers/browser.py +98 -0
- unrealon_driver/managers/cache.py +116 -0
- unrealon_driver/managers/http.py +107 -0
- unrealon_driver/managers/logger.py +286 -0
- unrealon_driver/managers/proxy.py +99 -0
- unrealon_driver/managers/registry.py +87 -0
- unrealon_driver/managers/threading.py +54 -0
- unrealon_driver/managers/update.py +107 -0
- unrealon_driver/utils/__init__.py +9 -0
- unrealon_driver/utils/time.py +10 -0
- unrealon-1.1.6.dist-info/METADATA +0 -625
- unrealon-1.1.6.dist-info/RECORD +0 -55
- unrealon-1.1.6.dist-info/entry_points.txt +0 -9
- unrealon_browser/managers/stealth.py +0 -388
- unrealon_driver/README.md +0 -0
- unrealon_driver/exceptions.py +0 -33
- unrealon_driver/html_analyzer/__init__.py +0 -32
- unrealon_driver/html_analyzer/cleaner.py +0 -657
- unrealon_driver/html_analyzer/config.py +0 -64
- unrealon_driver/html_analyzer/manager.py +0 -247
- unrealon_driver/html_analyzer/models.py +0 -115
- unrealon_driver/html_analyzer/websocket_analyzer.py +0 -157
- unrealon_driver/models/__init__.py +0 -31
- unrealon_driver/models/websocket.py +0 -98
- unrealon_driver/parser/__init__.py +0 -36
- unrealon_driver/parser/cli_manager.py +0 -142
- unrealon_driver/parser/daemon_manager.py +0 -403
- unrealon_driver/parser/managers/__init__.py +0 -25
- unrealon_driver/parser/managers/config.py +0 -293
- unrealon_driver/parser/managers/error.py +0 -412
- unrealon_driver/parser/managers/result.py +0 -321
- unrealon_driver/parser/parser_manager.py +0 -458
- unrealon_driver/smart_logging/__init__.py +0 -24
- unrealon_driver/smart_logging/models.py +0 -44
- unrealon_driver/smart_logging/smart_logger.py +0 -406
- unrealon_driver/smart_logging/unified_logger.py +0 -525
- unrealon_driver/websocket/__init__.py +0 -31
- unrealon_driver/websocket/client.py +0 -249
- unrealon_driver/websocket/config.py +0 -188
- unrealon_driver/websocket/manager.py +0 -90
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: unrealon
|
|
3
|
+
Version: 2.0.4
|
|
4
|
+
Summary: Enterprise-grade web scraping platform with AI-powered automation and real-time orchestration capabilities
|
|
5
|
+
Author-email: UnrealOn Team <team@unrealon.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://unrealon.com
|
|
8
|
+
Project-URL: Repository, https://github.com/markolofsen/unrealon-parser-amazon
|
|
9
|
+
Project-URL: Documentation, https://unrealon.com
|
|
10
|
+
Keywords: web-scraping,automation,ai,browser,driver,parsing,orchestration
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: Software Development :: Testing
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: <4.0,>=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
26
|
+
Requires-Dist: selenium>=4.15.0
|
|
27
|
+
Requires-Dist: playwright>=1.40.0
|
|
28
|
+
Requires-Dist: undetected-chromedriver>=3.5.0
|
|
29
|
+
Requires-Dist: fake-useragent>=1.4.0
|
|
30
|
+
Requires-Dist: aiofiles>=23.0.0
|
|
31
|
+
Requires-Dist: click>=8.1.0
|
|
32
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
33
|
+
Requires-Dist: httpx>=0.23.0
|
|
34
|
+
Requires-Dist: beautifulsoup4>=4.13.5
|
|
35
|
+
Requires-Dist: pydantic-yaml>=1.6.0
|
|
36
|
+
Requires-Dist: rich>=13.0.0
|
|
37
|
+
Requires-Dist: pyyaml>=6.0
|
|
38
|
+
Requires-Dist: python-socketio>=5.0
|
|
39
|
+
Requires-Dist: python-dateutil>=2.8
|
|
40
|
+
Requires-Dist: playwright-stealth>=2.0.0
|
|
41
|
+
Requires-Dist: questionary>=2.0.0
|
|
42
|
+
Requires-Dist: asyncio-extras>=1.3.0
|
|
43
|
+
Requires-Dist: pathlib2>=2.3.0
|
|
44
|
+
Requires-Dist: openai>=1.0.0
|
|
45
|
+
Requires-Dist: tiktoken>=0.9.0
|
|
46
|
+
Requires-Dist: fast-langdetect>=0.3.2
|
|
47
|
+
Requires-Dist: langid>=1.1.6
|
|
48
|
+
Requires-Dist: langdetect>=1.0.9
|
|
49
|
+
Requires-Dist: cachetools>=5.3.0
|
|
50
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
51
|
+
Requires-Dist: tomlkit>=0.13.3
|
|
52
|
+
Provides-Extra: ai
|
|
53
|
+
Requires-Dist: openai>=1.0.0; extra == "ai"
|
|
54
|
+
Requires-Dist: tiktoken>=0.9.0; extra == "ai"
|
|
55
|
+
Requires-Dist: fast-langdetect>=0.3.2; extra == "ai"
|
|
56
|
+
Requires-Dist: langid>=1.1.6; extra == "ai"
|
|
57
|
+
Requires-Dist: langdetect>=1.0.9; extra == "ai"
|
|
58
|
+
Provides-Extra: browser
|
|
59
|
+
Requires-Dist: selenium>=4.15.0; extra == "browser"
|
|
60
|
+
Requires-Dist: playwright>=1.40.0; extra == "browser"
|
|
61
|
+
Requires-Dist: undetected-chromedriver>=3.5.0; extra == "browser"
|
|
62
|
+
Requires-Dist: playwright-stealth>=2.0.0; extra == "browser"
|
|
63
|
+
Provides-Extra: dev
|
|
64
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
65
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
66
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
67
|
+
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
|
|
68
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == "dev"
|
|
69
|
+
Requires-Dist: pytest-html>=4.0.0; extra == "dev"
|
|
70
|
+
Requires-Dist: pytest-xdist>=3.3.0; extra == "dev"
|
|
71
|
+
Requires-Dist: pytest-timeout>=2.1.0; extra == "dev"
|
|
72
|
+
Requires-Dist: pytest-playwright>=0.4.0; extra == "dev"
|
|
73
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
74
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
75
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
76
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
77
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
78
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
79
|
+
Requires-Dist: questionary>=2.1.0; extra == "dev"
|
|
80
|
+
Requires-Dist: tomlkit>=0.13.3; extra == "dev"
|
|
81
|
+
Requires-Dist: bandit>=1.7.5; extra == "dev"
|
|
82
|
+
Requires-Dist: safety>=2.3.0; extra == "dev"
|
|
83
|
+
Requires-Dist: pylint>=2.17.0; extra == "dev"
|
|
84
|
+
Requires-Dist: locust>=2.0.0; extra == "dev"
|
|
85
|
+
Requires-Dist: responses>=0.23.0; extra == "dev"
|
|
86
|
+
Requires-Dist: aioresponses>=0.7.4; extra == "dev"
|
|
87
|
+
Requires-Dist: pre-commit>=3.3.0; extra == "dev"
|
|
88
|
+
Requires-Dist: types-PyYAML>=6.0; extra == "dev"
|
|
89
|
+
Requires-Dist: types-python-dateutil>=2.8; extra == "dev"
|
|
90
|
+
Provides-Extra: full
|
|
91
|
+
Requires-Dist: selenium>=4.15.0; extra == "full"
|
|
92
|
+
Requires-Dist: playwright>=1.40.0; extra == "full"
|
|
93
|
+
Requires-Dist: undetected-chromedriver>=3.5.0; extra == "full"
|
|
94
|
+
Requires-Dist: playwright-stealth>=2.0.0; extra == "full"
|
|
95
|
+
Requires-Dist: openai>=1.0.0; extra == "full"
|
|
96
|
+
Requires-Dist: tiktoken>=0.9.0; extra == "full"
|
|
97
|
+
Requires-Dist: fast-langdetect>=0.3.2; extra == "full"
|
|
98
|
+
Requires-Dist: langid>=1.1.6; extra == "full"
|
|
99
|
+
Requires-Dist: langdetect>=1.0.9; extra == "full"
|
|
100
|
+
|
|
101
|
+
# 🚀 UnrealOn v2.0
|
|
102
|
+
|
|
103
|
+
**The easiest way to build production-ready web scrapers in Python.**
|
|
104
|
+
|
|
105
|
+
[](https://badge.fury.io/py/unrealon)
|
|
106
|
+
[](https://www.python.org/downloads/)
|
|
107
|
+
[](https://opensource.org/licenses/MIT)
|
|
108
|
+
|
|
109
|
+
## 🎯 Why UnrealOn?
|
|
110
|
+
|
|
111
|
+
**Stop fighting infrastructure. Start building parsers.**
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
# Just focus on YOUR parsing logic
|
|
115
|
+
class MyParser:
|
|
116
|
+
def __init__(self, driver):
|
|
117
|
+
self.driver = driver
|
|
118
|
+
|
|
119
|
+
async def parse_products(self, url: str):
|
|
120
|
+
html = await self.driver.http.get_html(url) # Auto proxy, retries, etc.
|
|
121
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
122
|
+
|
|
123
|
+
products = []
|
|
124
|
+
for item in soup.select('.product'):
|
|
125
|
+
products.append({
|
|
126
|
+
'title': item.select_one('.title').text,
|
|
127
|
+
'price': item.select_one('.price').text
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
return products # Auto-saved, logged, monitored
|
|
131
|
+
|
|
132
|
+
# Everything else is handled automatically!
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**What you get for free:**
|
|
136
|
+
- ✅ **HTTP Client** with proxy rotation, retries, rate limiting
|
|
137
|
+
- ✅ **Browser Automation** with stealth mode and anti-detection
|
|
138
|
+
- ✅ **Error Handling** with automatic retries and graceful failures
|
|
139
|
+
- ✅ **Logging & Monitoring** with structured logs and performance metrics
|
|
140
|
+
- ✅ **CLI Interface** auto-generated from your parser methods
|
|
141
|
+
- ✅ **Configuration** with YAML files and validation
|
|
142
|
+
- ✅ **Production Deployment** with RPC server integration
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 📦 Installation
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pip install unrealon
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
That's it! No complex setup, no configuration files to write.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 🚀 Quick Start
|
|
157
|
+
|
|
158
|
+
### 1. Create Your Parser
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
# my_parser.py
|
|
162
|
+
from unrealon_driver import UniversalDriver, DriverConfig
|
|
163
|
+
from bs4 import BeautifulSoup
|
|
164
|
+
|
|
165
|
+
class MyWebsiteParser:
|
|
166
|
+
def __init__(self, driver: UniversalDriver):
|
|
167
|
+
self.driver = driver
|
|
168
|
+
|
|
169
|
+
async def parse_products(self, search_query: str):
|
|
170
|
+
"""Parse products from search results."""
|
|
171
|
+
|
|
172
|
+
# UnrealOn handles all the HTTP complexity
|
|
173
|
+
url = f"https://example.com/search?q={search_query}"
|
|
174
|
+
html = await self.driver.http.get_html(url)
|
|
175
|
+
|
|
176
|
+
# Focus on YOUR parsing logic
|
|
177
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
178
|
+
products = []
|
|
179
|
+
|
|
180
|
+
for item in soup.select('.product-item'):
|
|
181
|
+
product = {
|
|
182
|
+
'title': item.select_one('.title').text.strip(),
|
|
183
|
+
'price': item.select_one('.price').text.strip(),
|
|
184
|
+
'url': item.select_one('a')['href']
|
|
185
|
+
}
|
|
186
|
+
products.append(product)
|
|
187
|
+
|
|
188
|
+
# Results are automatically saved and logged
|
|
189
|
+
await self.driver.logger.info(f"Found {len(products)} products")
|
|
190
|
+
return products
|
|
191
|
+
|
|
192
|
+
# Setup (one time)
|
|
193
|
+
config = DriverConfig.for_development("my_parser")
|
|
194
|
+
driver = UniversalDriver(config)
|
|
195
|
+
parser = MyWebsiteParser(driver)
|
|
196
|
+
|
|
197
|
+
# Use it
|
|
198
|
+
await driver.initialize()
|
|
199
|
+
results = await parser.parse_products("laptop")
|
|
200
|
+
print(f"Found {len(results)} products!")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 2. Add CLI Interface (Optional)
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
# cli.py
|
|
207
|
+
import click
|
|
208
|
+
from my_parser import MyWebsiteParser, driver
|
|
209
|
+
|
|
210
|
+
@click.command()
|
|
211
|
+
@click.option('--query', required=True, help='Search query')
|
|
212
|
+
@click.option('--limit', default=10, help='Max results')
|
|
213
|
+
def search(query: str, limit: int):
|
|
214
|
+
"""Search for products."""
|
|
215
|
+
|
|
216
|
+
async def run():
|
|
217
|
+
await driver.initialize()
|
|
218
|
+
parser = MyWebsiteParser(driver)
|
|
219
|
+
results = await parser.parse_products(query)
|
|
220
|
+
|
|
221
|
+
for i, product in enumerate(results[:limit], 1):
|
|
222
|
+
print(f"{i}. {product['title']} - {product['price']}")
|
|
223
|
+
|
|
224
|
+
await driver.shutdown()
|
|
225
|
+
|
|
226
|
+
import asyncio
|
|
227
|
+
asyncio.run(run())
|
|
228
|
+
|
|
229
|
+
if __name__ == '__main__':
|
|
230
|
+
search()
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Now you have a CLI!
|
|
235
|
+
python cli.py search --query "laptop" --limit 5
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 3. Production Deployment (Optional)
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
# For production, just add RPC task decorators
|
|
242
|
+
class ProductionParser(UniversalDriver):
|
|
243
|
+
def __init__(self):
|
|
244
|
+
super().__init__(DriverConfig.for_production("my_parser"))
|
|
245
|
+
self.parser = MyWebsiteParser(self)
|
|
246
|
+
|
|
247
|
+
@self.task("parse_products") # Auto-registered RPC task
|
|
248
|
+
async def parse_products_task(self, task_data):
|
|
249
|
+
query = task_data.parameters['query']
|
|
250
|
+
results = await self.parser.parse_products(query)
|
|
251
|
+
|
|
252
|
+
return TaskResultData(
|
|
253
|
+
task_id=task_data.task_id,
|
|
254
|
+
status="completed",
|
|
255
|
+
result=results
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Deploy and scale automatically!
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 🎨 Features
|
|
264
|
+
|
|
265
|
+
### 🔧 HTTP Client (Built-in)
|
|
266
|
+
```python
|
|
267
|
+
# All of this is handled automatically:
|
|
268
|
+
html = await driver.http.get_html(url)
|
|
269
|
+
# ✅ Proxy rotation
|
|
270
|
+
# ✅ User-Agent rotation
|
|
271
|
+
# ✅ Automatic retries
|
|
272
|
+
# ✅ Rate limiting
|
|
273
|
+
# ✅ Cookie management
|
|
274
|
+
# ✅ Session persistence
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### 🌐 Browser Automation (Built-in)
|
|
278
|
+
```python
|
|
279
|
+
# When you need a real browser:
|
|
280
|
+
page = await driver.browser.get_page(url)
|
|
281
|
+
await page.click('.load-more')
|
|
282
|
+
html = await page.content()
|
|
283
|
+
# ✅ Stealth mode
|
|
284
|
+
# ✅ Anti-detection
|
|
285
|
+
# ✅ JavaScript execution
|
|
286
|
+
# ✅ Screenshot capture
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 📊 Monitoring & Logging (Built-in)
|
|
290
|
+
```python
|
|
291
|
+
# Structured logging that just works:
|
|
292
|
+
await driver.logger.info("Starting parse", extra={
|
|
293
|
+
'url': url,
|
|
294
|
+
'products_found': len(products)
|
|
295
|
+
})
|
|
296
|
+
# ✅ Centralized logging
|
|
297
|
+
# ✅ Performance metrics
|
|
298
|
+
# ✅ Error tracking
|
|
299
|
+
# ✅ Real-time monitoring
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### ⚙️ Configuration (Built-in)
|
|
303
|
+
```yaml
|
|
304
|
+
# config.yaml - Simple YAML configuration
|
|
305
|
+
parser:
|
|
306
|
+
name: "My Parser"
|
|
307
|
+
max_pages: 10
|
|
308
|
+
|
|
309
|
+
http:
|
|
310
|
+
request_delay: 1.0
|
|
311
|
+
max_retries: 3
|
|
312
|
+
|
|
313
|
+
output:
|
|
314
|
+
format: json
|
|
315
|
+
directory: ./results
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 🚀 Production Scaling (Built-in)
|
|
319
|
+
```python
|
|
320
|
+
# Scale to multiple instances automatically
|
|
321
|
+
@driver.task("parse_category")
|
|
322
|
+
async def parse_category_task(self, task_data):
|
|
323
|
+
# This runs on any available parser instance
|
|
324
|
+
category = task_data.parameters['category']
|
|
325
|
+
return await self.parse_category(category)
|
|
326
|
+
|
|
327
|
+
# Deploy multiple instances, they auto-coordinate!
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 📚 Examples
|
|
333
|
+
|
|
334
|
+
### E-commerce Parser
|
|
335
|
+
```python
|
|
336
|
+
class EcommerceParser:
|
|
337
|
+
async def parse_product(self, product_url: str):
|
|
338
|
+
html = await self.driver.http.get_html(product_url)
|
|
339
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
'title': soup.select_one('h1').text,
|
|
343
|
+
'price': soup.select_one('.price').text,
|
|
344
|
+
'description': soup.select_one('.description').text,
|
|
345
|
+
'images': [img['src'] for img in soup.select('.gallery img')]
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### News Scraper
|
|
350
|
+
```python
|
|
351
|
+
class NewsParser:
|
|
352
|
+
async def parse_articles(self, category: str):
|
|
353
|
+
url = f"https://news-site.com/{category}"
|
|
354
|
+
html = await self.driver.http.get_html(url)
|
|
355
|
+
soup = BeautifulSoup(html, 'html.parser')
|
|
356
|
+
|
|
357
|
+
articles = []
|
|
358
|
+
for article in soup.select('.article'):
|
|
359
|
+
articles.append({
|
|
360
|
+
'headline': article.select_one('.headline').text,
|
|
361
|
+
'summary': article.select_one('.summary').text,
|
|
362
|
+
'published': article.select_one('.date').text,
|
|
363
|
+
'url': article.select_one('a')['href']
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
return articles
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Real Estate Listings
|
|
370
|
+
```python
|
|
371
|
+
class RealEstateParser:
|
|
372
|
+
async def parse_listings(self, city: str, max_price: int):
|
|
373
|
+
url = f"https://realestate.com/search?city={city}&max_price={max_price}"
|
|
374
|
+
|
|
375
|
+
# Use browser for JavaScript-heavy sites
|
|
376
|
+
page = await self.driver.browser.get_page(url)
|
|
377
|
+
await page.wait_for_selector('.listing')
|
|
378
|
+
|
|
379
|
+
listings = await page.evaluate('''
|
|
380
|
+
() => Array.from(document.querySelectorAll('.listing')).map(listing => ({
|
|
381
|
+
address: listing.querySelector('.address').textContent,
|
|
382
|
+
price: listing.querySelector('.price').textContent,
|
|
383
|
+
bedrooms: listing.querySelector('.bedrooms').textContent,
|
|
384
|
+
url: listing.querySelector('a').href
|
|
385
|
+
}))
|
|
386
|
+
''')
|
|
387
|
+
|
|
388
|
+
return listings
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## 🆚 Why Not Scrapy/BeautifulSoup/Selenium?
|
|
394
|
+
|
|
395
|
+
| Feature | UnrealOn | Scrapy | BeautifulSoup + Requests | Selenium |
|
|
396
|
+
|---------|----------|--------|-------------------------|----------|
|
|
397
|
+
| **Setup Time** | ✅ 5 minutes | ❌ Hours | ❌ Hours | ❌ Hours |
|
|
398
|
+
| **Proxy Rotation** | ✅ Built-in | ❌ Manual setup | ❌ Manual setup | ❌ Manual setup |
|
|
399
|
+
| **Anti-Detection** | ✅ Built-in | ❌ Manual setup | ❌ Manual setup | ❌ Partial |
|
|
400
|
+
| **Error Handling** | ✅ Built-in | ❌ Manual setup | ❌ Manual setup | ❌ Manual setup |
|
|
401
|
+
| **Monitoring** | ✅ Built-in | ❌ Manual setup | ❌ Manual setup | ❌ Manual setup |
|
|
402
|
+
| **CLI Generation** | ✅ Automatic | ❌ Manual | ❌ Manual | ❌ Manual |
|
|
403
|
+
| **Production Deploy** | ✅ Built-in | ❌ Complex | ❌ Very complex | ❌ Very complex |
|
|
404
|
+
| **Learning Curve** | ✅ Minimal | ❌ Steep | ❌ Medium | ❌ Steep |
|
|
405
|
+
|
|
406
|
+
**UnrealOn = All the power, none of the setup.**
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## 🛠️ Advanced Features
|
|
411
|
+
|
|
412
|
+
### Type-Safe Data Models
|
|
413
|
+
```python
|
|
414
|
+
from pydantic import BaseModel
|
|
415
|
+
from typing import Optional
|
|
416
|
+
|
|
417
|
+
class Product(BaseModel):
|
|
418
|
+
title: str
|
|
419
|
+
price: Optional[float] = None
|
|
420
|
+
url: str
|
|
421
|
+
in_stock: bool = True
|
|
422
|
+
|
|
423
|
+
# Automatic validation and serialization
|
|
424
|
+
product = Product(title="Laptop", price=999.99, url="https://...")
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Scheduled Tasks
|
|
428
|
+
```python
|
|
429
|
+
@driver.schedule("0 */6 * * *") # Every 6 hours
|
|
430
|
+
async def monitor_prices():
|
|
431
|
+
"""Monitor price changes automatically."""
|
|
432
|
+
products = await parser.parse_products("laptop")
|
|
433
|
+
# Check for price drops, send alerts, etc.
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Batch Processing
|
|
437
|
+
```python
|
|
438
|
+
async def parse_multiple_categories():
|
|
439
|
+
categories = ["electronics", "books", "clothing"]
|
|
440
|
+
|
|
441
|
+
# Process all categories concurrently
|
|
442
|
+
tasks = [parser.parse_category(cat) for cat in categories]
|
|
443
|
+
results = await driver.threads.submit_batch(tasks, max_workers=3)
|
|
444
|
+
|
|
445
|
+
return results
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## 🚀 Getting Started
|
|
451
|
+
|
|
452
|
+
1. **Install**: `pip install unrealon`
|
|
453
|
+
2. **Create parser**: Write your parsing logic (focus on the scraping, not infrastructure)
|
|
454
|
+
3. **Run**: `python my_parser.py`
|
|
455
|
+
4. **Scale**: Add `@driver.task` decorators for production
|
|
456
|
+
|
|
457
|
+
### Complete Example Repository
|
|
458
|
+
- **[Amazon Parser](https://github.com/markolofsen/unrealon-parser-amazon)** - Production-ready Amazon scraper
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## 📚 Documentation
|
|
463
|
+
|
|
464
|
+
- **[GitHub Repository](https://github.com/markolofsen/unrealon-parser-amazon)** - Source code and examples
|
|
465
|
+
- **[API Documentation](https://unrealon.com)** - Full API reference
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 🎉 Success Stories
|
|
470
|
+
|
|
471
|
+
### 🚗 CarAPIs - Automotive Data Platform
|
|
472
|
+
**[carapis.com](https://carapis.com)** - Vehicle listings from 50+ dealerships
|
|
473
|
+
*"Went from prototype to production in 2 days with UnrealOn"*
|
|
474
|
+
|
|
475
|
+
### 🛒 ShopAPIs - E-commerce Intelligence
|
|
476
|
+
**[shopapis.com](https://shopapis.com)** - Price monitoring across 100+ stores
|
|
477
|
+
*"Handles 1M+ products daily with zero maintenance"*
|
|
478
|
+
|
|
479
|
+
### 📊 StockAPIs - Financial Data Platform
|
|
480
|
+
**[stockapis.com](https://stockapis.com)** - Real-time market data collection
|
|
481
|
+
*"Rock-solid reliability for financial data that can't afford downtime"*
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## 📄 License
|
|
486
|
+
|
|
487
|
+
MIT License - Use it however you want!
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
**Stop building infrastructure. Start building parsers.** 🚀
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
unrealon_browser/README.md,sha256=9pP6RrfMGHtdT5uDLFAUB1e4nNGzZudXViEo1940gKw,396
|
|
2
|
+
unrealon_browser/__init__.py,sha256=aYEmGQyhGEwcr-XPKqWJb21uQPB9XvqwZgKSSwkbb_I,1521
|
|
3
|
+
unrealon_browser/cli/__init__.py,sha256=b3r88oeCYsqZF8EU8EZXP9v54Q8cIimN7UmxJsXcB84,264
|
|
4
|
+
unrealon_browser/cli/browser_cli.py,sha256=dQ7p3Ml1touWbkbo-U4jkhknhRvAYT9mzbe2ZTLylZ0,8505
|
|
5
|
+
unrealon_browser/cli/cookies_cli.py,sha256=yhZvGrg8bknlH4zlySdi8ue-25Ue-1rI_u1G06OIMg4,13304
|
|
6
|
+
unrealon_browser/cli/interactive_mode.py,sha256=sXjiGZi-BK-Q5KhxYs8HJZ2EqkQK0Jx7MhtVnULRqLg,12120
|
|
7
|
+
unrealon_browser/cli/main.py,sha256=XCYcTxJUqaz320KCU_JPKizYMk6bdljb8Boyok3uO-4,1353
|
|
8
|
+
unrealon_browser/core/__init__.py,sha256=uVL_t4sZelUzflWPdgrwoXGnAkSV1WNQ98-eu0QB2eM,151
|
|
9
|
+
unrealon_browser/core/browser_manager.py,sha256=9xxo0kqbUcssFBNpvIXavWBya2E3TmgHKplQQ2kkZeU,29598
|
|
10
|
+
unrealon_browser/dto/__init__.py,sha256=bApqcLz-KanEi0_MCiFPrQmGBoX3VBijP7XtBUyIfjo,1636
|
|
11
|
+
unrealon_browser/dto/bot_detection.py,sha256=qXfC0HghV7m4L6qA87t3STi-166jM-QgoP6OYbCb4o4,6884
|
|
12
|
+
unrealon_browser/dto/models/config.py,sha256=krNAqzlEk0HnrmZRoTdfuKoDWnuXwv3pGl0mcFwr4zs,1747
|
|
13
|
+
unrealon_browser/dto/models/core.py,sha256=HvbwYG27rmmWtp401uws7lfalN_9QPad0M6ceCiN5iQ,2741
|
|
14
|
+
unrealon_browser/dto/models/dataclasses.py,sha256=zqhJVyzp4CvtuTBsZwm6n6TodVWrZf9gkdDG-0_tgeA,2571
|
|
15
|
+
unrealon_browser/dto/models/detection.py,sha256=ma9ZNIjPR7HnjqZaAj6ZoskiewPFiSn_FgFXSkgiQc8,2715
|
|
16
|
+
unrealon_browser/dto/models/enums.py,sha256=Q4WzHdfSKf7dhKyX00i_Pvl2U8w3lBsxOYfSIoaQY3Q,1219
|
|
17
|
+
unrealon_browser/dto/models/statistics.py,sha256=aIzJNV5r23VBxjhEoja4tXwI1Z7_UCw5zOaxuPya2E8,2728
|
|
18
|
+
unrealon_browser/managers/__init__.py,sha256=WMzrYGrCXn467XWBr8msrvT43ckX_EQSe9Ye9cfMozg,528
|
|
19
|
+
unrealon_browser/managers/captcha.py,sha256=KGBO7sfq9XusAlcPByUFdIg-v6rlruzS2oHx-Zx28wo,21453
|
|
20
|
+
unrealon_browser/managers/cookies.py,sha256=r4VVnKLXH82vhU7qgtY-dF7KPf0Ie3QxGD3FEi6geFA,15085
|
|
21
|
+
unrealon_browser/managers/logger_bridge.py,sha256=I3KNUmxSV9xL1JHpc6WOVCzn_kLlOxJzfZy76rsxr48,10912
|
|
22
|
+
unrealon_browser/managers/page_wait_manager.py,sha256=UyZqiSfkjzahrxp9x1odXFIT_sFhZGvdECxWuIMCVBY,7876
|
|
23
|
+
unrealon_browser/managers/profile.py,sha256=HjddlSeUry_65WPtF8CMkT7cfJ6X3Jap9kJaaZpwtAA,18956
|
|
24
|
+
unrealon_browser/stealth/__init__.py,sha256=zUfkPPafYlPANLVQIy-Se11R_UjcJakUb3krCxxUK5Q,842
|
|
25
|
+
unrealon_browser/stealth/bypass_techniques.pyc,sha256=Tys_I4tnJmL9aQLB1k1mL-4OtzedhpYTmW4XPEIb3cI,25790
|
|
26
|
+
unrealon_browser/stealth/manager.pyc,sha256=JC9g-LWoKPo1QuY1LUIyMmFEDgZJjrFlLuA3KbctQ3U,21178
|
|
27
|
+
unrealon_browser/stealth/nodriver_stealth.pyc,sha256=SnDMdeG_W2LDK_3UfrjDeolMpqxTMDNjRbId_YC_cKA,15286
|
|
28
|
+
unrealon_browser/stealth/playwright_stealth.pyc,sha256=Y-IiRTu136R6LIstGdKbns1j-CODX3sTGVT0IGx_MF4,6529
|
|
29
|
+
unrealon_browser/stealth/scanner_tester.pyc,sha256=m5jUXySno0g9AScJt5dyjppkM0QXENX3Sh5W4fRR5ZA,21706
|
|
30
|
+
unrealon_browser/stealth/undetected_chrome.pyc,sha256=HNp2_84zwp-JG-Y3jqQwCNldnG6P5bBnbf9dBV_pOuw,12765
|
|
31
|
+
unrealon_core/__init__.py,sha256=bFKK6AOQVb34OLq3RlduDokLjf4cR0q1_sWAK5GQ2js,4954
|
|
32
|
+
unrealon_core/version.py,sha256=qZOlKA_Hsz7_KXsCLO_0l9Mf0u_iNTxvHZPV21DwCqs,5803
|
|
33
|
+
unrealon_core/config/__init__.py,sha256=57-KZaTDya0oyfOCfZ3pU1xLLbnZPBgqwfP9VrfhcKE,395
|
|
34
|
+
unrealon_core/config/environment.py,sha256=VNPse_SU-hFd1rT3WTxZl65CsTxeaXWxcQuAvWv1TJI,2774
|
|
35
|
+
unrealon_core/config/urls.py,sha256=dlQCZSz5NasA5A4v3ff9beVqOkXL5aCa_rt1VDNIs9Q,2751
|
|
36
|
+
unrealon_core/enums/__init__.py,sha256=C-fqNVSWofnaq2Ed6GbGtck8WkN8gpHYA_NiIlaEbTI,520
|
|
37
|
+
unrealon_core/enums/status.py,sha256=DT6rth7Ve7chsYhJtccY6plsgQQ8jEMhfhcZTpK308c,6861
|
|
38
|
+
unrealon_core/enums/types.py,sha256=hf1NkA2sBIfgtNHqdQPr7Uow_E2SeDGh1Jpxls0RFYg,8704
|
|
39
|
+
unrealon_core/error_handling/__init__.py,sha256=s7VXUJG7nvD6Od76-ZfFmn5e6r29mxNusP8YPba73GM,1248
|
|
40
|
+
unrealon_core/error_handling/circuit_breaker.py,sha256=IPT7I8nrDm4eDojrjMgM3-vLIaz-0raS-9W3LUpFnhY,10066
|
|
41
|
+
unrealon_core/error_handling/error_context.py,sha256=jfluYy1FVyyU_8dwjBN1w2vPq9oLRYLg2fgndlc_8As,9798
|
|
42
|
+
unrealon_core/error_handling/recovery.py,sha256=r177qIIE127idm_UEa9kuwc0mN25L_qQ2hfskyWtdFQ,12732
|
|
43
|
+
unrealon_core/error_handling/retry.py,sha256=u2XToj598gdC-S7d3ULZA75SSCXf0SZvcGcC_K2YRqI,8306
|
|
44
|
+
unrealon_core/exceptions/__init__.py,sha256=vjLRVe5No31HiNinAPft6pAwdiEgVB0aWpMByt5M8ZU,1205
|
|
45
|
+
unrealon_core/exceptions/base.py,sha256=CPWSjWj8HXucQ0vQ1zEgZbI9kIcThgAZWr5xOcCh8_s,8926
|
|
46
|
+
unrealon_core/exceptions/communication.py,sha256=W4W5IREKYIH8Aq9aMsD3OruSZ7_uaLscwb9KFLJiNuw,414
|
|
47
|
+
unrealon_core/exceptions/driver.py,sha256=YB3_oRgOMzD4cCSEhqpqpP5iD6ChbZmaOtnw4BaOr20,247
|
|
48
|
+
unrealon_core/exceptions/proxy.py,sha256=oqy3gV8jha1a2JrOtbJU8zTpWq_XA8Ooou2cl4eHF0o,246
|
|
49
|
+
unrealon_core/exceptions/task.py,sha256=uNSyJgZvBSHtimQ-ZLPjjDZrVzq6sXscJUQDkCmQ0No,285
|
|
50
|
+
unrealon_core/exceptions/validation.py,sha256=f7nWbi5ag1nqo7kwN0QaXYNfRrIwHhYVNlKHGiyhuQ8,351
|
|
51
|
+
unrealon_core/models/__init__.py,sha256=rSpjZ4PiOMgkQ1iocsr2zPA2ziSV9_7Fdg5XU6EXY1g,1699
|
|
52
|
+
unrealon_core/models/arq_context.py,sha256=9a6yJgdQ3ZifoCgEEiN90q5qRzQ9pk0ivHnowhzLF7c,8389
|
|
53
|
+
unrealon_core/models/arq_responses.py,sha256=OYEIjLZ1iEoWEKAOqAuudYWT4I_ZVeftDFOOmWjgEaM,4471
|
|
54
|
+
unrealon_core/models/base.py,sha256=5x5Ie77wH_qRrezd8kSQ23DgOffSmCmICmVqEeXX4Hc,8964
|
|
55
|
+
unrealon_core/models/bridge_stats.py,sha256=trVoAQkFG5fc8TSzUmH133Xwf8htKYM5Xyl_3-5ApnE,1878
|
|
56
|
+
unrealon_core/models/communication.py,sha256=YFdiR-J0ncjmvg4yudU1bTfR61BEmV6sQ1zCXWN_xR0,1152
|
|
57
|
+
unrealon_core/models/config.py,sha256=VFOFyjAdDVqNMVUruIeqdbOvo-_FvXhCtt9LQvPOijE,1355
|
|
58
|
+
unrealon_core/models/connection_stats.py,sha256=KngZoi78WXsLAvl9ZYq6xRoVUaTBUVmnI8hrxZ8y038,1522
|
|
59
|
+
unrealon_core/models/driver.py,sha256=RVl69fPFWW-E9yINUi2yXEWcw3sycc-bgVOw00VfkdU,690
|
|
60
|
+
unrealon_core/models/driver_details.py,sha256=0Bc1J16Zika7p1SflsqssiF4IjpQbwNFij17H1pQR44,3737
|
|
61
|
+
unrealon_core/models/logging.py,sha256=MKGjMmhJhediGNVKmX0wfm1GO2kfvEqOp2cCfq42Vbo,542
|
|
62
|
+
unrealon_core/models/task.py,sha256=QSOQMXNbvD7vfP6ddYUBPwD7jj0N9_zQxjwDMrznXo4,435
|
|
63
|
+
unrealon_core/models/typed_responses.py,sha256=shEvV4A7mYUKIzG3zD4zoRO2PmVLL3iLtGjzRGSW8Ks,7034
|
|
64
|
+
unrealon_core/models/websocket_session.py,sha256=q3RXQP2CwRTgUTYMRnb4xzzdGWUOeL8maYxVFPmF92w,5119
|
|
65
|
+
unrealon_core/models/websocket/__init__.py,sha256=F-KDDZAMJvCVQMo2Z-xLPQmG0B8JEQ2auxxI89ZCsro,2551
|
|
66
|
+
unrealon_core/models/websocket/base.py,sha256=gmkJ-vLpsajc4aGlPBeMURIFNg3AgX4yYSnJQAqqkf0,1388
|
|
67
|
+
unrealon_core/models/websocket/config.py,sha256=AZz9wK8j0UIkRkDE17Nsxdocimh-41MJQkS-_VzTnM0,4665
|
|
68
|
+
unrealon_core/models/websocket/driver.py,sha256=Bi1B7nSSWkLFCwfIOLJSkPUxGS5r9x4Mw9XWvHuSxa0,5206
|
|
69
|
+
unrealon_core/models/websocket/errors.py,sha256=l5w1rCx_RrzdISPwLOoKtoPCuSNjHL5XExyFaHgayS4,3095
|
|
70
|
+
unrealon_core/models/websocket/heartbeat.py,sha256=OFCOqZTOnwtKxYP3G9TrI6G8l6s940LdjdXznTqz0xo,2424
|
|
71
|
+
unrealon_core/models/websocket/logging.py,sha256=AiL0ctpLfAtr4Th8qu7JxsXT9mKYgJpuuuEJyiaQI0Y,6242
|
|
72
|
+
unrealon_core/models/websocket/proxy.py,sha256=NdSDc-twiMfnEn71dF56PV8CEkDyMOwaHYvhVxIPIE0,12443
|
|
73
|
+
unrealon_core/models/websocket/tasks.py,sha256=X-NP4D8TRcUsDHnOiEz2-YubaJ7xP1Wvfh_sCAfUFAg,6582
|
|
74
|
+
unrealon_core/models/websocket/utils.py,sha256=lsKHh889H5dNqZcvkgfJgPoFjza-wCi2sCj4E2NQ1ZE,4170
|
|
75
|
+
unrealon_core/monitoring/__init__.py,sha256=dsDhc_fn8Zlplk44JDNU4pXDEqhTJ3jqotD4JrnZI1c,1119
|
|
76
|
+
unrealon_core/monitoring/alerts.py,sha256=hodZdeksmjQa0J5m6JIJGyiBmqialFA25_tPCM4PKLs,13875
|
|
77
|
+
unrealon_core/monitoring/dashboard.py,sha256=QUU2YtD33ojnnneD9K35lLvLJdqKcWGEwd5Ysif8C70,11366
|
|
78
|
+
unrealon_core/monitoring/health_check.py,sha256=UAdZ1Of0LCWFVfVXQP0BF-4HDOe4rxyh6dLQpxq8P_U,12072
|
|
79
|
+
unrealon_core/monitoring/metrics.py,sha256=UPCRoridgGVxQ1kh--NuXzH-2dY0WyKljfXDH96OroU,11705
|
|
80
|
+
unrealon_core/utils/__init__.py,sha256=L4nJum_ekqh3Rn324pcIASfr6QQtnT_PwWKCtl2L0mU,179
|
|
81
|
+
unrealon_core/utils/time.py,sha256=27iWhOEl4wHgBOag7gqFlI0hl5cTHPnKHoe8GxmnKHA,1356
|
|
82
|
+
unrealon_driver/__init__.py,sha256=HC6QTY6ufzQdBZ5-GrrNFH-VWoIKKqS0nyzZ2ZPhEak,1924
|
|
83
|
+
unrealon_driver/core_module/__init__.py,sha256=v4bHF0eqSQBAUBBEl8RnQWrvb3LjAeIAQCeIXrRTy3w,620
|
|
84
|
+
unrealon_driver/core_module/base.py,sha256=RbC6MVQSA-1145gnDMdsMJ_QnMpQT52pIg86UfRSSMc,6135
|
|
85
|
+
unrealon_driver/core_module/config.py,sha256=N0XGWsoYmv2ruKZOZKOyfaHOZ_jstUDqH7aTqURG2TI,1023
|
|
86
|
+
unrealon_driver/core_module/event_manager.py,sha256=K9fd7Mse_wb-XmIzszZIR5fHJQRZwMSrTj4vS6R3qG8,4328
|
|
87
|
+
unrealon_driver/core_module/protocols.py,sha256=uqp5djefaubyKePzlzVGtZXP04DEiyrCtor-B6Q2LE0,2238
|
|
88
|
+
unrealon_driver/core_module/registry.py,sha256=2EzKcPzRjTXMRchykl1OptKpV-t9lZKeVUD9RhAGM6Y,4926
|
|
89
|
+
unrealon_driver/decorators/__init__.py,sha256=QU2juAsdXq-avmtozSGBE-0ZsVCDtiqz1V4Zz6yDV80,230
|
|
90
|
+
unrealon_driver/decorators/retry.py,sha256=xjFehfqu695B5CTrnd4jdfCxsn6HqECvRx31N7qNIGM,4206
|
|
91
|
+
unrealon_driver/decorators/schedule.py,sha256=k9sJfwbalgbg7boIwTI-hJBSMlUnBcnSV3zV_9Pq8Og,4781
|
|
92
|
+
unrealon_driver/decorators/task.py,sha256=nnG-S99BSdtKYXZ97XBkQLDc-jpc4a6SKv-6b7mUwPk,2028
|
|
93
|
+
unrealon_driver/decorators/timing.py,sha256=Bmtsp2tWxY4EOq3onF1OTSk0rqf9lQNlX4RL-hyr4ZM,3927
|
|
94
|
+
unrealon_driver/driver/__init__.py,sha256=P_NJXcsigIjROwErqUXgS0VneUfGggFL4bWDbdB73iw,419
|
|
95
|
+
unrealon_driver/driver/communication/__init__.py,sha256=SalrzX_55WXlkbS9P6nm6PhddoI8pquURqx3103Q708,205
|
|
96
|
+
unrealon_driver/driver/communication/session.py,sha256=vRarQAUunmqltD1p2Z7Jms5xBK543XarfCUWAC_G8XQ,6936
|
|
97
|
+
unrealon_driver/driver/communication/websocket_client.py,sha256=Msgu7n42tBMPBLhEHxlLxlHrDP1OFfhGReRSUPZKPsw,7163
|
|
98
|
+
unrealon_driver/driver/core/__init__.py,sha256=ZvJQp1zO7pj6tBNYTJk2fj-0ZMiQTQEk-I9hXalNsfg,235
|
|
99
|
+
unrealon_driver/driver/core/config.py,sha256=YYvTlo6jNlNz-FKJ730nkhahlN4OSl7yz1txauC-NQ4,2848
|
|
100
|
+
unrealon_driver/driver/core/driver.py,sha256=NI-pdhnduRyHLsfFr8HmP2gp7pR1pWB4vBIJkMJ2cls,7886
|
|
101
|
+
unrealon_driver/driver/factory/__init__.py,sha256=XrjBhOaLvC3MIG5PAFIYS_xYXFDz5JizpFvmQcwA7mU,189
|
|
102
|
+
unrealon_driver/driver/factory/manager_factory.py,sha256=zJt63N8oWNJS0aNbLy7WjY4GCeUwLjvtWGdqdpucufU,4792
|
|
103
|
+
unrealon_driver/driver/lifecycle/__init__.py,sha256=KnkXklezAOIbXcCzEU_XSOt32z7tz1zIGclXYXTkO8k,286
|
|
104
|
+
unrealon_driver/driver/lifecycle/daemon.py,sha256=6cglmGsMLmMgqkXm0cquzcQiUNLRJ2abrj37bJysIUA,2508
|
|
105
|
+
unrealon_driver/driver/lifecycle/initialization.py,sha256=jwamdzG3IDKwYiTbMnGkBOJeWeTlPxIlQkOrsc22qCo,3649
|
|
106
|
+
unrealon_driver/driver/lifecycle/shutdown.py,sha256=h-6hKjDP30OjKiSgLe3UIfpS5wDbQFRaYWnEPosyTe0,1426
|
|
107
|
+
unrealon_driver/driver/monitoring/__init__.py,sha256=MJjLm4b5pzSpXGOq50e-MKUkyToiUbARzkGqNqN-iJg,162
|
|
108
|
+
unrealon_driver/driver/monitoring/health.py,sha256=rOH0wChDBTnDbV7MstB21JsJJUMGMeq3crb47RLL2ek,2164
|
|
109
|
+
unrealon_driver/driver/utilities/__init__.py,sha256=YCTR7CXu3wlynKNDJh4YsE1uhZ_QrtoQjLNArleMChM,232
|
|
110
|
+
unrealon_driver/driver/utilities/logging.py,sha256=2my2QnkAa6Hdw-TfO4oOQ94yGc-CjlRfnWsnbWIKb9o,1799
|
|
111
|
+
unrealon_driver/driver/utilities/serialization.py,sha256=wTCSVrEloykiGN4K1JXbk2aqNKm7W90aWXmzhcLyAZc,2123
|
|
112
|
+
unrealon_driver/managers/__init__.py,sha256=zJJsOb6Oodg7l00v4ncKUytnyeaZM887pHY8-eSuWdU,981
|
|
113
|
+
unrealon_driver/managers/base.py,sha256=GkuXillg9uqqnx6RL682fmKgK-7JyqYlH6DFUgyN4F8,5445
|
|
114
|
+
unrealon_driver/managers/browser.py,sha256=9kwdmWPxWFpNQ1KejtpzdN615V8PBJu8Y2nUOewQaeQ,3489
|
|
115
|
+
unrealon_driver/managers/cache.py,sha256=c0tPKQ5KFd_Un1U8mw3j1WPuycxg863MMWNMveVF_2I,3506
|
|
116
|
+
unrealon_driver/managers/http.py,sha256=EjlpoTRuhpsgzzrEARxRlbGczzua7hnKFVq06bvCgTM,3624
|
|
117
|
+
unrealon_driver/managers/logger.py,sha256=w-JiouSPN8YZKTgDshANv6EpiKEJ9r6R1vxQexQp32M,10243
|
|
118
|
+
unrealon_driver/managers/proxy.py,sha256=Y_3ok2iGefeYHcTtBQIEK3Rnr8qRnPsP90hOOYPUMz0,3449
|
|
119
|
+
unrealon_driver/managers/registry.py,sha256=--oNPU-65e8J21ubJufyEOc1TirnzJIvpvuY_j7rH7Q,2666
|
|
120
|
+
unrealon_driver/managers/threading.py,sha256=djw5cSC99dfBKmep3IJ_8IgxQceMXtNvCp5fIxHM0TY,1702
|
|
121
|
+
unrealon_driver/managers/update.py,sha256=-hohVxGXpj5bZ6ZTQN6NH1RK9Pd6GVzCMtu3GS2SdcQ,3582
|
|
122
|
+
unrealon_driver/utils/__init__.py,sha256=qxXVoQJVdLJhaLBXk_LZV_062AhrvBrMPXWAKfEc3C4,104
|
|
123
|
+
unrealon_driver/utils/time.py,sha256=Oxk1eicKeZl8ZWbf7gu1Ll716k6CpXmVj67FHSnPIsA,184
|
|
124
|
+
unrealon-2.0.4.dist-info/LICENSE,sha256=eEH8mWZW49YMpl4Sh5MtKqkZ8aVTzKQXiNPEnvL14ns,1070
|
|
125
|
+
unrealon-2.0.4.dist-info/METADATA,sha256=n8q2NabepEQ9LHwNHYyTsWWQ2njvdlWHC5Ry6mz9x9g,15688
|
|
126
|
+
unrealon-2.0.4.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
|
|
127
|
+
unrealon-2.0.4.dist-info/entry_points.txt,sha256=k0qM-eotpajkKUq-almJmxj9afhXprZ6IkvQkSdcKhI,104
|
|
128
|
+
unrealon-2.0.4.dist-info/top_level.txt,sha256=Gu8IeIfIVfUxdi-h-F0nKMQxo15pjhHZ0aTadXTpRE8,47
|
|
129
|
+
unrealon-2.0.4.dist-info/RECORD,,
|
unrealon_browser/__init__.py
CHANGED
|
@@ -4,13 +4,11 @@ Enterprise-grade browser automation with stealth capabilities and proxy integrat
|
|
|
4
4
|
|
|
5
5
|
Based on proven patterns from unrealparser with modular architecture.
|
|
6
6
|
"""
|
|
7
|
+
# Import unified version system
|
|
8
|
+
from unrealon_core.version import get_rpc_version, get_version_info
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
__version__ = version("unrealon-browser")
|
|
12
|
-
except Exception:
|
|
13
|
-
__version__ = "1.0.0-dev"
|
|
10
|
+
__version__ = get_rpc_version()
|
|
11
|
+
__author__ = "UnrealOn Team"
|
|
14
12
|
|
|
15
13
|
# Core browser management
|
|
16
14
|
from .core import BrowserManager
|
|
@@ -68,3 +66,4 @@ __all__ = [
|
|
|
68
66
|
"CaptchaStatus",
|
|
69
67
|
"CaptchaDetectionResult",
|
|
70
68
|
]
|
|
69
|
+
|