browser-stealth 0.1.0__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.
- browser_stealth/__init__.py +127 -0
- browser_stealth/antidetect/__init__.py +43 -0
- browser_stealth/antidetect/_mobile_scripts.py +3 -0
- browser_stealth/antidetect/antidetect.py +3 -0
- browser_stealth/antidetect/antidetect_scripts.py +3 -0
- browser_stealth/antidetect/config.py +495 -0
- browser_stealth/antidetect/core.py +527 -0
- browser_stealth/antidetect/mobile.py +177 -0
- browser_stealth/antidetect/scripts.py +594 -0
- browser_stealth/bidi/__init__.py +25 -0
- browser_stealth/bidi/antidetect.py +78 -0
- browser_stealth/bidi/client.py +481 -0
- browser_stealth/bidi/exceptions.py +43 -0
- browser_stealth/bidi/session.py +304 -0
- browser_stealth/concurrency/__init__.py +29 -0
- browser_stealth/concurrency/base.py +63 -0
- browser_stealth/concurrency/limiter.py +118 -0
- browser_stealth/concurrency/metrics.py +67 -0
- browser_stealth/concurrency/models.py +41 -0
- browser_stealth/concurrency/pool.py +142 -0
- browser_stealth/concurrency/queues.py +422 -0
- browser_stealth/concurrency/reaper.py +395 -0
- browser_stealth/crypto.py +64 -0
- browser_stealth/exceptions.py +41 -0
- browser_stealth/fingerprint/__init__.py +23 -0
- browser_stealth/fingerprint/database.py +155 -0
- browser_stealth/fingerprint/external.py +131 -0
- browser_stealth/fingerprint/models.py +226 -0
- browser_stealth/fingerprint/procedural.py +190 -0
- browser_stealth/fingerprint/synthesizer.py +145 -0
- browser_stealth/fs.py +91 -0
- browser_stealth/humanize/__init__.py +81 -0
- browser_stealth/humanize/_actions_helpers.py +625 -0
- browser_stealth/humanize/_mobile_scripts.py +177 -0
- browser_stealth/humanize/actions.py +550 -0
- browser_stealth/humanize/antidetect.py +20 -0
- browser_stealth/humanize/antidetect_scripts.py +18 -0
- browser_stealth/humanize/behavior.py +300 -0
- browser_stealth/humanize/config.py +6 -0
- browser_stealth/humanize/consent.py +97 -0
- browser_stealth/humanize/math_utils.py +685 -0
- browser_stealth/humanize/search.py +176 -0
- browser_stealth/humanize/touch.py +336 -0
- browser_stealth/humanize/turnstile.py +411 -0
- browser_stealth/humanize/warmer.py +606 -0
- browser_stealth/launchers/__init__.py +7 -0
- browser_stealth/launchers/camoufox.py +61 -0
- browser_stealth/launchers/nodriver.py +259 -0
- browser_stealth/lifecycle.py +66 -0
- browser_stealth/logging.py +23 -0
- browser_stealth/plugin.py +69 -0
- browser_stealth/profiles/__init__.py +31 -0
- browser_stealth/profiles/adapters/__init__.py +23 -0
- browser_stealth/profiles/adapters/nodriver.py +150 -0
- browser_stealth/profiles/adapters/playwright.py +105 -0
- browser_stealth/profiles/adapters/selenium.py +86 -0
- browser_stealth/profiles/hygiene.py +254 -0
- browser_stealth/profiles/manager.py +233 -0
- browser_stealth/profiles/models.py +46 -0
- browser_stealth/profiles/storage.py +83 -0
- browser_stealth/proxy/__init__.py +79 -0
- browser_stealth/proxy/adapters.py +116 -0
- browser_stealth/proxy/cache.py +172 -0
- browser_stealth/proxy/extension.py +212 -0
- browser_stealth/proxy/models.py +108 -0
- browser_stealth/proxy/parser.py +130 -0
- browser_stealth/proxy/pool.py +287 -0
- browser_stealth/proxy/resolver.py +606 -0
- browser_stealth/proxy/storage.py +249 -0
- browser_stealth/proxy/tunnel.py +383 -0
- browser_stealth/py.typed +0 -0
- browser_stealth/testing/__init__.py +198 -0
- browser_stealth/testing/assertions.py +178 -0
- browser_stealth/testing/dom_models.py +162 -0
- browser_stealth/testing/dom_scripts.py +929 -0
- browser_stealth/testing/fixtures.py +126 -0
- browser_stealth/testing/mocks/__init__.py +26 -0
- browser_stealth/testing/mocks/dom.py +245 -0
- browser_stealth/testing/mocks/nodriver.py +154 -0
- browser_stealth/testing/mocks/playwright.py +197 -0
- browser_stealth/testing/mocks/selenium.py +199 -0
- browser_stealth/testing/recorder.py +443 -0
- browser_stealth/testing/server.py +318 -0
- browser_stealth/testing/session.py +201 -0
- browser_stealth/testing/snapshot.py +281 -0
- browser_stealth-0.1.0.dist-info/METADATA +151 -0
- browser_stealth-0.1.0.dist-info/RECORD +89 -0
- browser_stealth-0.1.0.dist-info/WHEEL +4 -0
- browser_stealth-0.1.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Next-generation browser antidetect, human-like behavior emulation, and profile warmer.
|
|
2
|
+
|
|
3
|
+
Библиотека глубокой маскировки и эмуляции поведения человека для nodriver, Playwright, Selenium и WebDriver BiDi.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from . import (
|
|
9
|
+
antidetect,
|
|
10
|
+
bidi,
|
|
11
|
+
concurrency,
|
|
12
|
+
fingerprint,
|
|
13
|
+
humanize,
|
|
14
|
+
launchers,
|
|
15
|
+
profiles,
|
|
16
|
+
proxy,
|
|
17
|
+
testing,
|
|
18
|
+
)
|
|
19
|
+
from .antidetect.config import AntidetectConfig
|
|
20
|
+
from .antidetect.core import (
|
|
21
|
+
ANTIDETECT_JS_SCRIPT,
|
|
22
|
+
apply_antidetect_nodriver,
|
|
23
|
+
apply_antidetect_playwright,
|
|
24
|
+
apply_antidetect_selenium,
|
|
25
|
+
get_browser_launch_args,
|
|
26
|
+
get_client_hints,
|
|
27
|
+
)
|
|
28
|
+
from .bidi.client import BiDiClient
|
|
29
|
+
from .bidi.session import BiDiSession, bidi_session
|
|
30
|
+
from .exceptions import BrowserStealthError, OptionalDependencyError
|
|
31
|
+
from .humanize.actions import (
|
|
32
|
+
TouchGestureGenerator,
|
|
33
|
+
TouchPoint,
|
|
34
|
+
async_click,
|
|
35
|
+
async_human_sleep,
|
|
36
|
+
async_move_mouse,
|
|
37
|
+
async_scroll_to,
|
|
38
|
+
async_touch_swipe,
|
|
39
|
+
async_touch_tap,
|
|
40
|
+
async_type_text,
|
|
41
|
+
click,
|
|
42
|
+
human_sleep,
|
|
43
|
+
move_mouse,
|
|
44
|
+
scroll_to,
|
|
45
|
+
type_text,
|
|
46
|
+
)
|
|
47
|
+
from .humanize.behavior import BehavioralProfile
|
|
48
|
+
from .humanize.math_utils import (
|
|
49
|
+
BezierCurveGenerator,
|
|
50
|
+
JitterDelayGenerator,
|
|
51
|
+
KeyboardTypoGenerator,
|
|
52
|
+
WindMouseGenerator,
|
|
53
|
+
)
|
|
54
|
+
from .humanize.turnstile import (
|
|
55
|
+
detect_cf_turnstile,
|
|
56
|
+
is_cf_turnstile_solved,
|
|
57
|
+
solve_cf_turnstile,
|
|
58
|
+
)
|
|
59
|
+
from .humanize.warmer import ProfileWarmer, SyncProfileWarmer
|
|
60
|
+
from .launchers import camoufox, nodriver
|
|
61
|
+
from .launchers.nodriver import close_tab, launch_nodriver, nodriver_session
|
|
62
|
+
from .profiles.manager import ProfileManager
|
|
63
|
+
from .profiles.models import BrowserProfile
|
|
64
|
+
from .proxy.models import ProxyConfig, ProxyHealthResult
|
|
65
|
+
from .proxy.parser import parse_proxy
|
|
66
|
+
from .proxy.pool import ProxyPool
|
|
67
|
+
|
|
68
|
+
__version__ = "0.1.0"
|
|
69
|
+
|
|
70
|
+
__all__ = [
|
|
71
|
+
"ANTIDETECT_JS_SCRIPT",
|
|
72
|
+
"AntidetectConfig",
|
|
73
|
+
"BehavioralProfile",
|
|
74
|
+
"BezierCurveGenerator",
|
|
75
|
+
"BiDiClient",
|
|
76
|
+
"BiDiSession",
|
|
77
|
+
"BrowserProfile",
|
|
78
|
+
"BrowserStealthError",
|
|
79
|
+
"JitterDelayGenerator",
|
|
80
|
+
"KeyboardTypoGenerator",
|
|
81
|
+
"OptionalDependencyError",
|
|
82
|
+
"ProfileManager",
|
|
83
|
+
"ProfileWarmer",
|
|
84
|
+
"ProxyConfig",
|
|
85
|
+
"ProxyHealthResult",
|
|
86
|
+
"ProxyPool",
|
|
87
|
+
"SyncProfileWarmer",
|
|
88
|
+
"TouchGestureGenerator",
|
|
89
|
+
"TouchPoint",
|
|
90
|
+
"WindMouseGenerator",
|
|
91
|
+
"antidetect",
|
|
92
|
+
"apply_antidetect_nodriver",
|
|
93
|
+
"apply_antidetect_playwright",
|
|
94
|
+
"apply_antidetect_selenium",
|
|
95
|
+
"async_click",
|
|
96
|
+
"async_human_sleep",
|
|
97
|
+
"async_move_mouse",
|
|
98
|
+
"async_scroll_to",
|
|
99
|
+
"async_touch_swipe",
|
|
100
|
+
"async_touch_tap",
|
|
101
|
+
"async_type_text",
|
|
102
|
+
"bidi",
|
|
103
|
+
"bidi_session",
|
|
104
|
+
"camoufox",
|
|
105
|
+
"click",
|
|
106
|
+
"close_tab",
|
|
107
|
+
"concurrency",
|
|
108
|
+
"detect_cf_turnstile",
|
|
109
|
+
"fingerprint",
|
|
110
|
+
"get_browser_launch_args",
|
|
111
|
+
"get_client_hints",
|
|
112
|
+
"human_sleep",
|
|
113
|
+
"humanize",
|
|
114
|
+
"is_cf_turnstile_solved",
|
|
115
|
+
"launch_nodriver",
|
|
116
|
+
"launchers",
|
|
117
|
+
"move_mouse",
|
|
118
|
+
"nodriver",
|
|
119
|
+
"nodriver_session",
|
|
120
|
+
"parse_proxy",
|
|
121
|
+
"profiles",
|
|
122
|
+
"proxy",
|
|
123
|
+
"scroll_to",
|
|
124
|
+
"solve_cf_turnstile",
|
|
125
|
+
"testing",
|
|
126
|
+
"type_text",
|
|
127
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Подсистема антидетекта и маскировки браузерных сред."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .config import AntidetectConfig
|
|
6
|
+
from .core import (
|
|
7
|
+
ANTIDETECT_JS_SCRIPT,
|
|
8
|
+
_ensure_nodriver,
|
|
9
|
+
_ensure_playwright,
|
|
10
|
+
_ensure_selenium,
|
|
11
|
+
apply_antidetect_nodriver,
|
|
12
|
+
apply_antidetect_playwright,
|
|
13
|
+
apply_antidetect_selenium,
|
|
14
|
+
extract_clearance_cookies,
|
|
15
|
+
get_browser_launch_args,
|
|
16
|
+
get_client_hints,
|
|
17
|
+
)
|
|
18
|
+
from .scripts import (
|
|
19
|
+
DEFAULT_DEVICE_MEMORY,
|
|
20
|
+
DEFAULT_HARDWARE_CONCURRENCY,
|
|
21
|
+
DEFAULT_WEBGL_RENDERER,
|
|
22
|
+
DEFAULT_WEBGL_VENDOR,
|
|
23
|
+
_get_antidetect_js,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"ANTIDETECT_JS_SCRIPT",
|
|
28
|
+
"DEFAULT_DEVICE_MEMORY",
|
|
29
|
+
"DEFAULT_HARDWARE_CONCURRENCY",
|
|
30
|
+
"DEFAULT_WEBGL_RENDERER",
|
|
31
|
+
"DEFAULT_WEBGL_VENDOR",
|
|
32
|
+
"AntidetectConfig",
|
|
33
|
+
"_ensure_nodriver",
|
|
34
|
+
"_ensure_playwright",
|
|
35
|
+
"_ensure_selenium",
|
|
36
|
+
"_get_antidetect_js",
|
|
37
|
+
"apply_antidetect_nodriver",
|
|
38
|
+
"apply_antidetect_playwright",
|
|
39
|
+
"apply_antidetect_selenium",
|
|
40
|
+
"extract_clearance_cookies",
|
|
41
|
+
"get_browser_launch_args",
|
|
42
|
+
"get_client_hints",
|
|
43
|
+
]
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
"""Декларативная конфигурация антидетекта для браузерных движков."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from browser_stealth.fingerprint.models import FingerprintProfile
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
11
|
+
|
|
12
|
+
from .scripts import (
|
|
13
|
+
DEFAULT_DEVICE_MEMORY,
|
|
14
|
+
DEFAULT_HARDWARE_CONCURRENCY,
|
|
15
|
+
DEFAULT_WEBGL_RENDERER,
|
|
16
|
+
DEFAULT_WEBGL_VENDOR,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AntidetectConfig(BaseModel):
|
|
21
|
+
"""Конфигурация параметров маскировки браузера (антидетект)."""
|
|
22
|
+
|
|
23
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, validate_assignment=True)
|
|
24
|
+
|
|
25
|
+
webgl_vendor: str = Field(
|
|
26
|
+
default=DEFAULT_WEBGL_VENDOR,
|
|
27
|
+
description="Эмулируемый производитель WebGL.",
|
|
28
|
+
)
|
|
29
|
+
webgl_renderer: str = Field(
|
|
30
|
+
default=DEFAULT_WEBGL_RENDERER,
|
|
31
|
+
description="Эмулируемая видеокарта WebGL.",
|
|
32
|
+
)
|
|
33
|
+
hardware_concurrency: int = Field(
|
|
34
|
+
default=DEFAULT_HARDWARE_CONCURRENCY,
|
|
35
|
+
ge=1,
|
|
36
|
+
le=128,
|
|
37
|
+
description="Количество виртуальных ядер процессора.",
|
|
38
|
+
)
|
|
39
|
+
device_memory: int = Field(
|
|
40
|
+
default=DEFAULT_DEVICE_MEMORY,
|
|
41
|
+
ge=1,
|
|
42
|
+
le=128,
|
|
43
|
+
description="Объем оперативной памяти устройства в ГБ.",
|
|
44
|
+
)
|
|
45
|
+
stealth_minimal: bool = Field(
|
|
46
|
+
default=True,
|
|
47
|
+
description=(
|
|
48
|
+
"Если True, не накладывать синтетический шум на Canvas и не подменять WebGL, "
|
|
49
|
+
"сохраняя 100% консистентный отпечаток реального Chromium (рекомендуется для nodriver)."
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
session_seed: str | int = Field(
|
|
53
|
+
default=1337,
|
|
54
|
+
description="Сид для детерминированного шума Canvas и AudioContext.",
|
|
55
|
+
)
|
|
56
|
+
client_hints: dict[str, Any] | None = Field(
|
|
57
|
+
default=None,
|
|
58
|
+
description="Параметры navigator.userAgentData (brands, platform, mobile).",
|
|
59
|
+
)
|
|
60
|
+
user_agent: str | None = Field(
|
|
61
|
+
default=None,
|
|
62
|
+
description="Пользовательская строка User-Agent для переопределения через CDP/HTTP.",
|
|
63
|
+
)
|
|
64
|
+
screen_width: int | None = Field(
|
|
65
|
+
default=None,
|
|
66
|
+
description="Эмулируемая ширина экрана (screen.width).",
|
|
67
|
+
)
|
|
68
|
+
screen_height: int | None = Field(
|
|
69
|
+
default=None,
|
|
70
|
+
description="Эмулируемая высота экрана (screen.height).",
|
|
71
|
+
)
|
|
72
|
+
screen_avail_height: int | None = Field(
|
|
73
|
+
default=None,
|
|
74
|
+
description="Эмулируемая доступная высота экрана за вычетом панели задач (screen.availHeight).",
|
|
75
|
+
)
|
|
76
|
+
device_pixel_ratio: float | None = Field(
|
|
77
|
+
default=None,
|
|
78
|
+
description="Эмулируемый коэффициент масштабирования (window.devicePixelRatio).",
|
|
79
|
+
)
|
|
80
|
+
media_devices: list[dict[str, Any]] | None = Field(
|
|
81
|
+
default=None,
|
|
82
|
+
description="Список эмулируемых медиа-устройств (микрофоны, динамики, веб-камеры).",
|
|
83
|
+
)
|
|
84
|
+
is_mobile: bool = Field(
|
|
85
|
+
default=False,
|
|
86
|
+
description="Флаг эмуляции мобильного устройства.",
|
|
87
|
+
)
|
|
88
|
+
has_touch: bool = Field(
|
|
89
|
+
default=False,
|
|
90
|
+
description="Флаг поддержки сенсорного ввода (Touch Events).",
|
|
91
|
+
)
|
|
92
|
+
max_touch_points: int = Field(
|
|
93
|
+
default=0,
|
|
94
|
+
ge=0,
|
|
95
|
+
le=20,
|
|
96
|
+
description="Максимальное количество точек касания (navigator.maxTouchPoints).",
|
|
97
|
+
)
|
|
98
|
+
is_ios: bool = Field(
|
|
99
|
+
default=False,
|
|
100
|
+
description="Флаг эмуляции iOS Safari (специфичные объекты window.safari, ApplePaySession).",
|
|
101
|
+
)
|
|
102
|
+
orientation: dict[str, Any] | None = Field(
|
|
103
|
+
default=None,
|
|
104
|
+
description="Параметры ориентации экрана (type, angle).",
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
@classmethod
|
|
108
|
+
def preset_stealth_nodriver(
|
|
109
|
+
cls,
|
|
110
|
+
*,
|
|
111
|
+
session_seed: str | int = 1337,
|
|
112
|
+
client_hints: dict[str, Any] | None = None,
|
|
113
|
+
user_agent: str | None = None,
|
|
114
|
+
) -> AntidetectConfig:
|
|
115
|
+
"""Рекомендуемый пресет для nodriver: zero-footprint (без синтетического шума Canvas/WebGL).
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
session_seed: Сид для детерминированного генератора псевдослучайных чисел.
|
|
119
|
+
client_hints: Опциональный словарь с параметрами Client Hints.
|
|
120
|
+
user_agent: Опциональная строка User-Agent.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Экземпляр AntidetectConfig с конфигурацией zero-footprint.
|
|
124
|
+
"""
|
|
125
|
+
return cls(
|
|
126
|
+
stealth_minimal=True,
|
|
127
|
+
session_seed=session_seed,
|
|
128
|
+
client_hints=client_hints,
|
|
129
|
+
user_agent=user_agent,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def preset_aggressive(
|
|
134
|
+
cls,
|
|
135
|
+
*,
|
|
136
|
+
webgl_vendor: str = DEFAULT_WEBGL_VENDOR,
|
|
137
|
+
webgl_renderer: str = DEFAULT_WEBGL_RENDERER,
|
|
138
|
+
hardware_concurrency: int = DEFAULT_HARDWARE_CONCURRENCY,
|
|
139
|
+
device_memory: int = DEFAULT_DEVICE_MEMORY,
|
|
140
|
+
session_seed: str | int = 1337,
|
|
141
|
+
client_hints: dict[str, Any] | None = None,
|
|
142
|
+
user_agent: str | None = None,
|
|
143
|
+
) -> AntidetectConfig:
|
|
144
|
+
"""Агрессивный пресет с рандомизацией Canvas/WebGL/Audio (для Playwright/Selenium в headless).
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
webgl_vendor: Эмулируемый производитель WebGL.
|
|
148
|
+
webgl_renderer: Эмулируемая видеокарта WebGL.
|
|
149
|
+
hardware_concurrency: Эмулируемое количество ядер CPU.
|
|
150
|
+
device_memory: Эмулируемый объем оперативной памяти в ГБ.
|
|
151
|
+
session_seed: Сид для рандомизации шума Canvas/Audio.
|
|
152
|
+
client_hints: Дополнительные параметры Client Hints.
|
|
153
|
+
user_agent: Опциональная строка User-Agent.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Экземпляр AntidetectConfig с агрессивной рандомизацией.
|
|
157
|
+
"""
|
|
158
|
+
return cls(
|
|
159
|
+
webgl_vendor=webgl_vendor,
|
|
160
|
+
webgl_renderer=webgl_renderer,
|
|
161
|
+
hardware_concurrency=hardware_concurrency,
|
|
162
|
+
device_memory=device_memory,
|
|
163
|
+
stealth_minimal=False,
|
|
164
|
+
session_seed=session_seed,
|
|
165
|
+
client_hints=client_hints,
|
|
166
|
+
user_agent=user_agent,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
@classmethod
|
|
170
|
+
def preset_minimal(
|
|
171
|
+
cls,
|
|
172
|
+
*,
|
|
173
|
+
session_seed: str | int = 1337,
|
|
174
|
+
user_agent: str | None = None,
|
|
175
|
+
) -> AntidetectConfig:
|
|
176
|
+
"""Минимальный пресет: отключен шум, только базовая защита от утечек и скрытие webdriver.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
session_seed: Сид для инициализации сессии.
|
|
180
|
+
user_agent: Опциональная строка User-Agent.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Экземпляр AntidetectConfig с минимальной модификацией.
|
|
184
|
+
"""
|
|
185
|
+
return cls(
|
|
186
|
+
stealth_minimal=True,
|
|
187
|
+
session_seed=session_seed,
|
|
188
|
+
user_agent=user_agent,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def preset_mobile_android(
|
|
193
|
+
cls,
|
|
194
|
+
*,
|
|
195
|
+
device: str = "pixel_8",
|
|
196
|
+
session_seed: str | int = 1337,
|
|
197
|
+
stealth_minimal: bool = True,
|
|
198
|
+
) -> AntidetectConfig:
|
|
199
|
+
"""Мобильный пресет для Android Chrome (Pixel 8, Pixel 7, Galaxy S24).
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
device: Идентификатор устройства ('pixel_8', 'pixel_7', 'galaxy_s24').
|
|
203
|
+
session_seed: Сид для детерминированного шума и генератора поведения.
|
|
204
|
+
stealth_minimal: Режим маскировки.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Экземпляр AntidetectConfig для Android устройства.
|
|
208
|
+
"""
|
|
209
|
+
device_lower = device.lower()
|
|
210
|
+
if device_lower == "pixel_7":
|
|
211
|
+
width, height = 412, 915
|
|
212
|
+
dpr = 2.625
|
|
213
|
+
ua = (
|
|
214
|
+
"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 "
|
|
215
|
+
"(KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36"
|
|
216
|
+
)
|
|
217
|
+
vendor = "ARM"
|
|
218
|
+
renderer = "Mali-G710"
|
|
219
|
+
elif device_lower in ("galaxy_s24", "s24"):
|
|
220
|
+
width, height = 360, 780
|
|
221
|
+
dpr = 3.0
|
|
222
|
+
ua = (
|
|
223
|
+
"Mozilla/5.0 (Linux; Android 14; SM-S921B) AppleWebKit/537.36 "
|
|
224
|
+
"(KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36"
|
|
225
|
+
)
|
|
226
|
+
vendor = "Qualcomm"
|
|
227
|
+
renderer = "Adreno (TM) 750"
|
|
228
|
+
else: # pixel_8 по умолчанию или generic
|
|
229
|
+
width, height = 412, 915
|
|
230
|
+
dpr = 2.625
|
|
231
|
+
ua = (
|
|
232
|
+
f"Mozilla/5.0 (Linux; Android 14; {'Pixel 8' if device_lower == 'pixel_8' else device}) "
|
|
233
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36"
|
|
234
|
+
)
|
|
235
|
+
vendor = "ARM"
|
|
236
|
+
renderer = "Mali-G715 Immortalis MC11"
|
|
237
|
+
|
|
238
|
+
client_hints = {
|
|
239
|
+
"platform": "Android",
|
|
240
|
+
"mobile": True,
|
|
241
|
+
"brands": [
|
|
242
|
+
{"brand": "Chromium", "version": "128"},
|
|
243
|
+
{"brand": "Google Chrome", "version": "128"},
|
|
244
|
+
{"brand": "Not;A=Brand", "version": "24"},
|
|
245
|
+
],
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return cls(
|
|
249
|
+
user_agent=ua,
|
|
250
|
+
webgl_vendor=vendor,
|
|
251
|
+
webgl_renderer=renderer,
|
|
252
|
+
hardware_concurrency=8,
|
|
253
|
+
device_memory=8,
|
|
254
|
+
screen_width=width,
|
|
255
|
+
screen_height=height,
|
|
256
|
+
screen_avail_height=height,
|
|
257
|
+
device_pixel_ratio=dpr,
|
|
258
|
+
is_mobile=True,
|
|
259
|
+
has_touch=True,
|
|
260
|
+
max_touch_points=5,
|
|
261
|
+
is_ios=False,
|
|
262
|
+
orientation={"type": "portrait-primary", "angle": 0},
|
|
263
|
+
client_hints=client_hints,
|
|
264
|
+
stealth_minimal=stealth_minimal,
|
|
265
|
+
session_seed=session_seed,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
@classmethod
|
|
269
|
+
def preset_mobile_ios(
|
|
270
|
+
cls,
|
|
271
|
+
*,
|
|
272
|
+
device: str = "iphone_15",
|
|
273
|
+
session_seed: str | int = 1337,
|
|
274
|
+
stealth_minimal: bool = True,
|
|
275
|
+
) -> AntidetectConfig:
|
|
276
|
+
"""Мобильный пресет для iOS Safari (iPhone 15, iPhone 14).
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
device: Идентификатор устройства ('iphone_15', 'iphone_14').
|
|
280
|
+
session_seed: Сид для детерминированного шума и генератора поведения.
|
|
281
|
+
stealth_minimal: Режим маскировки.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Экземпляр AntidetectConfig для iOS Safari.
|
|
285
|
+
"""
|
|
286
|
+
device_lower = device.lower()
|
|
287
|
+
if device_lower in ("iphone_14", "iphone14"):
|
|
288
|
+
width, height = 390, 844
|
|
289
|
+
dpr = 3.0
|
|
290
|
+
ua = (
|
|
291
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) "
|
|
292
|
+
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
|
|
293
|
+
)
|
|
294
|
+
else: # iphone_15 по умолчанию или generic
|
|
295
|
+
width, height = 393, 852
|
|
296
|
+
dpr = 3.0
|
|
297
|
+
ua = (
|
|
298
|
+
f"Mozilla/5.0 ({'iPhone' if 'iphone' in device_lower else device}; CPU iPhone OS 17_5 like Mac OS X) "
|
|
299
|
+
"AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1"
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
client_hints = {
|
|
303
|
+
"platform": "iOS",
|
|
304
|
+
"mobile": True,
|
|
305
|
+
"brands": [],
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return cls(
|
|
309
|
+
user_agent=ua,
|
|
310
|
+
webgl_vendor="Apple Inc.",
|
|
311
|
+
webgl_renderer="Apple GPU",
|
|
312
|
+
hardware_concurrency=6,
|
|
313
|
+
device_memory=6,
|
|
314
|
+
screen_width=width,
|
|
315
|
+
screen_height=height,
|
|
316
|
+
screen_avail_height=height,
|
|
317
|
+
device_pixel_ratio=dpr,
|
|
318
|
+
is_mobile=True,
|
|
319
|
+
has_touch=True,
|
|
320
|
+
max_touch_points=5,
|
|
321
|
+
is_ios=True,
|
|
322
|
+
orientation={"type": "portrait-primary", "angle": 0},
|
|
323
|
+
client_hints=client_hints,
|
|
324
|
+
stealth_minimal=stealth_minimal,
|
|
325
|
+
session_seed=session_seed,
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
@classmethod
|
|
329
|
+
def from_fingerprint(
|
|
330
|
+
cls,
|
|
331
|
+
profile: FingerprintProfile | Any,
|
|
332
|
+
*,
|
|
333
|
+
stealth_minimal: bool = True,
|
|
334
|
+
) -> AntidetectConfig:
|
|
335
|
+
"""Создает AntidetectConfig на основе объекта FingerprintProfile.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
profile: Экземпляр FingerprintProfile.
|
|
339
|
+
stealth_minimal: Если True, не накладывать синтетический шум на Canvas.
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
Сконфигурированный экземпляр AntidetectConfig.
|
|
343
|
+
"""
|
|
344
|
+
res = profile.to_antidetect_config(stealth_minimal=stealth_minimal)
|
|
345
|
+
return cast(AntidetectConfig, res)
|
|
346
|
+
|
|
347
|
+
@classmethod
|
|
348
|
+
def from_seed(
|
|
349
|
+
cls,
|
|
350
|
+
seed: int | str,
|
|
351
|
+
*,
|
|
352
|
+
stealth_minimal: bool = True,
|
|
353
|
+
os_target: str = "windows",
|
|
354
|
+
locale: str = "ru-RU",
|
|
355
|
+
) -> AntidetectConfig:
|
|
356
|
+
"""Синтезирует детерминированную цифровую личность по сиду и возвращает AntidetectConfig.
|
|
357
|
+
|
|
358
|
+
Один и тот же сид всегда дает абсолютно идентичный и физически согласованный
|
|
359
|
+
отпечаток (видеокарта, процессор, память, геометрия экрана, панель задач).
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
seed: Сид профиля или имя учетной записи.
|
|
363
|
+
stealth_minimal: Если True, сохраняет чистый отпечаток без искажения Canvas.
|
|
364
|
+
os_target: Целевая ОС ('windows').
|
|
365
|
+
locale: Локаль ('ru-RU', 'en-US').
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Экземпляр AntidetectConfig.
|
|
369
|
+
"""
|
|
370
|
+
from browser_stealth.fingerprint import FingerprintSynthesizer
|
|
371
|
+
|
|
372
|
+
fp = FingerprintSynthesizer(
|
|
373
|
+
mode="procedural", os_target=os_target, locale=locale
|
|
374
|
+
).synthesize(seed)
|
|
375
|
+
return fp.to_antidetect_config(stealth_minimal=stealth_minimal)
|
|
376
|
+
|
|
377
|
+
@classmethod
|
|
378
|
+
def from_browserforge(
|
|
379
|
+
cls,
|
|
380
|
+
seed: int | str | None = None,
|
|
381
|
+
*,
|
|
382
|
+
browser: str = "chrome",
|
|
383
|
+
os: str = "windows",
|
|
384
|
+
stealth_minimal: bool = True,
|
|
385
|
+
) -> AntidetectConfig:
|
|
386
|
+
"""Генерирует отпечаток через байесовскую сеть browserforge (при наличии пакета).
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
seed: Опциональный сид для воспроизводимой детерминированной генерации.
|
|
390
|
+
browser: Эмулируемый браузер ('chrome').
|
|
391
|
+
os: Целевая ОС ('windows').
|
|
392
|
+
stealth_minimal: Режим маскировки.
|
|
393
|
+
|
|
394
|
+
Returns:
|
|
395
|
+
Экземпляр AntidetectConfig.
|
|
396
|
+
"""
|
|
397
|
+
from browser_stealth.fingerprint import FingerprintSynthesizer
|
|
398
|
+
|
|
399
|
+
fp = FingerprintSynthesizer(mode="browserforge", os_target=os).synthesize(seed)
|
|
400
|
+
return fp.to_antidetect_config(stealth_minimal=stealth_minimal)
|
|
401
|
+
|
|
402
|
+
@classmethod
|
|
403
|
+
def from_procedural(
|
|
404
|
+
cls,
|
|
405
|
+
seed: int | str | None = None,
|
|
406
|
+
*,
|
|
407
|
+
stealth_minimal: bool = True,
|
|
408
|
+
os_target: str = "windows",
|
|
409
|
+
locale: str = "ru-RU",
|
|
410
|
+
) -> AntidetectConfig:
|
|
411
|
+
"""Синтезирует отпечаток через встроенный процедурный генератор.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
seed: Опциональный сид.
|
|
415
|
+
stealth_minimal: Режим маскировки.
|
|
416
|
+
os_target: Целевая ОС.
|
|
417
|
+
locale: Локаль.
|
|
418
|
+
|
|
419
|
+
Returns:
|
|
420
|
+
Экземпляр AntidetectConfig.
|
|
421
|
+
"""
|
|
422
|
+
from browser_stealth.fingerprint import FingerprintSynthesizer
|
|
423
|
+
|
|
424
|
+
fp = FingerprintSynthesizer(
|
|
425
|
+
mode="procedural", os_target=os_target, locale=locale
|
|
426
|
+
).synthesize(seed)
|
|
427
|
+
return fp.to_antidetect_config(stealth_minimal=stealth_minimal)
|
|
428
|
+
|
|
429
|
+
def get_behavioral_profile(self) -> Any:
|
|
430
|
+
"""Возвращает детерминированный биометрический профиль моторики на основе session_seed.
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
Экземпляр BehavioralProfile.
|
|
434
|
+
"""
|
|
435
|
+
from browser_stealth.humanize.behavior import BehavioralProfile
|
|
436
|
+
|
|
437
|
+
return BehavioralProfile.from_seed(self.session_seed)
|
|
438
|
+
|
|
439
|
+
def get_init_script(self) -> str:
|
|
440
|
+
"""Генерирует JavaScript-скрипт антидетекта на основе настроек конфигурации.
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Строка исполняемого JavaScript-кода для инъекции в браузер.
|
|
444
|
+
"""
|
|
445
|
+
from .scripts import _get_antidetect_js
|
|
446
|
+
|
|
447
|
+
return _get_antidetect_js(
|
|
448
|
+
webgl_vendor=self.webgl_vendor,
|
|
449
|
+
webgl_renderer=self.webgl_renderer,
|
|
450
|
+
hardware_concurrency=self.hardware_concurrency,
|
|
451
|
+
device_memory=self.device_memory,
|
|
452
|
+
stealth_minimal=self.stealth_minimal,
|
|
453
|
+
session_seed=self.session_seed,
|
|
454
|
+
client_hints=self.client_hints,
|
|
455
|
+
screen_width=self.screen_width,
|
|
456
|
+
screen_height=self.screen_height,
|
|
457
|
+
screen_avail_height=self.screen_avail_height,
|
|
458
|
+
device_pixel_ratio=self.device_pixel_ratio,
|
|
459
|
+
media_devices=self.media_devices,
|
|
460
|
+
is_mobile=self.is_mobile,
|
|
461
|
+
has_touch=self.has_touch,
|
|
462
|
+
max_touch_points=self.max_touch_points,
|
|
463
|
+
is_ios=self.is_ios,
|
|
464
|
+
orientation=self.orientation,
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
async def apply_to_nodriver(self, tab: Any) -> None:
|
|
468
|
+
"""Применяет данную конфигурацию антидетекта к вкладке nodriver Tab.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
tab: Экземпляр вкладки nodriver Tab.
|
|
472
|
+
"""
|
|
473
|
+
from .core import apply_antidetect_nodriver
|
|
474
|
+
|
|
475
|
+
await apply_antidetect_nodriver(tab, config=self)
|
|
476
|
+
|
|
477
|
+
async def apply_to_playwright(self, target: Any) -> None:
|
|
478
|
+
"""Применяет данную конфигурацию антидетекта к Playwright Page или BrowserContext.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
target: Экземпляр Playwright BrowserContext или Page.
|
|
482
|
+
"""
|
|
483
|
+
from .core import apply_antidetect_playwright
|
|
484
|
+
|
|
485
|
+
await apply_antidetect_playwright(target, config=self)
|
|
486
|
+
|
|
487
|
+
def apply_to_selenium(self, driver: Any) -> None:
|
|
488
|
+
"""Применяет данную конфигурацию антидетекта к Selenium WebDriver.
|
|
489
|
+
|
|
490
|
+
Args:
|
|
491
|
+
driver: Экземпляр Selenium WebDriver.
|
|
492
|
+
"""
|
|
493
|
+
from .core import apply_antidetect_selenium
|
|
494
|
+
|
|
495
|
+
apply_antidetect_selenium(driver, config=self)
|