pydoll-python 2.9.3__tar.gz → 2.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/PKG-INFO +22 -24
  2. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/README.md +21 -23
  3. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/tab.py +14 -0
  4. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/constants.py +88 -0
  5. pydoll_python-2.10.0/pydoll/interactions/__init__.py +3 -0
  6. pydoll_python-2.10.0/pydoll/interactions/scroll.py +121 -0
  7. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pyproject.toml +1 -1
  8. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/LICENSE +0 -0
  9. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/__init__.py +0 -0
  10. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/__init__.py +0 -0
  11. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/chromium/__init__.py +0 -0
  12. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/chromium/base.py +0 -0
  13. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/chromium/chrome.py +0 -0
  14. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/chromium/edge.py +0 -0
  15. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/interfaces.py +0 -0
  16. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/managers/__init__.py +0 -0
  17. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/managers/browser_options_manager.py +0 -0
  18. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/managers/browser_process_manager.py +0 -0
  19. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/managers/proxy_manager.py +0 -0
  20. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/managers/temp_dir_manager.py +0 -0
  21. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/options.py +0 -0
  22. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/requests/__init__.py +0 -0
  23. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/requests/request.py +0 -0
  24. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/browser/requests/response.py +0 -0
  25. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/__init__.py +0 -0
  26. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/browser_commands.py +0 -0
  27. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/dom_commands.py +0 -0
  28. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/fetch_commands.py +0 -0
  29. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/input_commands.py +0 -0
  30. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/network_commands.py +0 -0
  31. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/page_commands.py +0 -0
  32. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/runtime_commands.py +0 -0
  33. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/storage_commands.py +0 -0
  34. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/commands/target_commands.py +0 -0
  35. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/connection/__init__.py +0 -0
  36. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/connection/connection_handler.py +0 -0
  37. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/connection/managers/__init__.py +0 -0
  38. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/connection/managers/commands_manager.py +0 -0
  39. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/connection/managers/events_manager.py +0 -0
  40. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/elements/__init__.py +0 -0
  41. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/elements/mixins/__init__.py +0 -0
  42. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/elements/mixins/find_elements_mixin.py +0 -0
  43. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/elements/web_element.py +0 -0
  44. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/exceptions.py +0 -0
  45. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/__init__.py +0 -0
  46. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/base.py +0 -0
  47. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/browser/__init__.py +0 -0
  48. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/browser/events.py +0 -0
  49. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/browser/methods.py +0 -0
  50. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/browser/types.py +0 -0
  51. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/debugger/types.py +0 -0
  52. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/dom/__init__.py +0 -0
  53. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/dom/events.py +0 -0
  54. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/dom/methods.py +0 -0
  55. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/dom/types.py +0 -0
  56. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/emulation/types.py +0 -0
  57. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/fetch/__init__.py +0 -0
  58. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/fetch/events.py +0 -0
  59. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/fetch/methods.py +0 -0
  60. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/fetch/types.py +0 -0
  61. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/input/__init__.py +0 -0
  62. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/input/events.py +0 -0
  63. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/input/methods.py +0 -0
  64. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/input/types.py +0 -0
  65. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/io/types.py +0 -0
  66. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/network/__init__.py +0 -0
  67. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/network/events.py +0 -0
  68. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/network/methods.py +0 -0
  69. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/network/types.py +0 -0
  70. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/page/__init__.py +0 -0
  71. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/page/events.py +0 -0
  72. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/page/methods.py +0 -0
  73. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/page/types.py +0 -0
  74. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/runtime/__init__.py +0 -0
  75. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/runtime/events.py +0 -0
  76. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/runtime/methods.py +0 -0
  77. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/runtime/types.py +0 -0
  78. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/security/types.py +0 -0
  79. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/storage/__init__.py +0 -0
  80. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/storage/events.py +0 -0
  81. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/storage/methods.py +0 -0
  82. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/storage/types.py +0 -0
  83. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/target/__init__.py +0 -0
  84. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/target/events.py +0 -0
  85. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/target/methods.py +0 -0
  86. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/protocol/target/types.py +0 -0
  87. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/py.typed +0 -0
  88. {pydoll_python-2.9.3 → pydoll_python-2.10.0}/pydoll/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydoll-python
3
- Version: 2.9.3
3
+ Version: 2.10.0
4
4
  Summary: Pydoll is a library for automating chromium-based browsers without a WebDriver, offering realistic interactions.
5
5
  License-File: LICENSE
6
6
  Author: Thalison Fernandes
@@ -52,37 +52,35 @@ Built from scratch with a different philosophy, Pydoll connects directly to the
52
52
 
53
53
  We believe that powerful automation shouldn't require you to become an expert in configuration or constantly fight with bot protection systems. With Pydoll, you can focus on what really matters: your automation logic, not the underlying complexity or protection systems.
54
54
 
55
- ### 🚀 Major Update in Development: Enhanced Stealth and Humanization Capabilities
55
+ ## 🌟 What makes Pydoll special?
56
56
 
57
- Pydoll is undergoing a significant development phase focused on incorporating advanced techniques for bot detection evasion and more realistic user interaction simulation.
57
+ - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
58
+ - **Human-like Interaction Engine**: Capable of passing behavioral CAPTCHAs like reCAPTCHA v3 or Turnstile, depending on IP reputation and interaction patterns
59
+ - **Asynchronous Performance**: For high-speed automation and multiple simultaneous tasks
60
+ - **Humanized Interactions**: Mimic real user behavior
61
+ - **Simplicity**: With Pydoll, you install and you're ready to automate.
58
62
 
59
- This update is based on extensive technical research and will include both substantial documentation improvements and new library features.
63
+ ## 🆕 What's New
60
64
 
61
- **Highlights of the Upcoming Release:**
65
+ ### Human-Like Page Scrolling: Scroll Like a Real User!
62
66
 
63
- * **Integrated Humanization Features:** Native implementations for:
64
- * **Mouse Interaction:** Simulation of cursor paths using Bezier curves, variable speeds based on Fitts's Law principles, and randomized click offsets. Event sequences (`mousemove`, `mousedown`, `mouseup`, `click`) will be handled automatically.
65
- * **Keyboard Input:** Character-by-character typing with randomized `Dwell` (key press duration) and `Flight` (time between keys) times. Optional simulation of typing errors and corrections.
66
- * **Scroll Simulation:** Physics-based scrolling mimicking momentum and inertia.
67
- * **Timing Variations:** Introduction of randomized delays ("cognitive time") before and after actions to avoid predictable automation patterns.
68
- * **Comprehensive Documentation Overhaul:** A new series of in-depth technical guides ("Deep Dives") covering:
69
- * **Network Fingerprinting:** Analysis of TCP/IP, TLS/JA3, and HTTP/2 characteristics. Includes practical examples like **building custom HTTP and SOCKS5 proxy servers** and discussing proxy detection techniques.
70
- * **Browser Fingerprinting:** Detailed exploration of `navigator` properties, Client Hints, Canvas/WebGL rendering, font detection, and screen attributes.
71
- * **Behavioral Fingerprinting:** Analysis of mouse dynamics, keystroke patterns (including bigram timing), scroll physics, and event sequencing.
72
- * **Advanced Browser Control:** Extensive documentation on using `browser_preferences` to modify hundreds of internal Chromium settings for granular control over performance, privacy, and fingerprinting.
73
- * **Practical Examples:** Including configurations for **Docker environments** and common evasion scenarios.
67
+ Now you can control page scrolling with smooth animations and automatic completion waiting:
74
68
 
75
- The aim is to provide users with both the theoretical understanding and the practical tools within Pydoll to create automation flows that are significantly harder to detect.
69
+ ```python
70
+ from pydoll.constants import ScrollPosition
76
71
 
77
- **Follow the progress by starring the repository ⭐!**
72
+ # Scroll down with smooth animation (waits for completion)
73
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
78
74
 
79
- ## 🌟 What makes Pydoll special?
75
+ # Navigate to specific positions
76
+ await tab.scroll.to_bottom(smooth=True)
77
+ await tab.scroll.to_top(smooth=True)
80
78
 
81
- - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
82
- - **Human-like Interaction Engine**: Capable of passing behavioral CAPTCHAs like reCAPTCHA v3 or Turnstile, depending on IP reputation and interaction patterns
83
- - **Asynchronous Performance**: For high-speed automation and multiple simultaneous tasks
84
- - **Humanized Interactions**: Mimic real user behavior
85
- - **Simplicity**: With Pydoll, you install and you're ready to automate.
79
+ # Instant scroll for speed when realism isn't critical
80
+ await tab.scroll.by(ScrollPosition.UP, 300, smooth=False)
81
+ ```
82
+
83
+ Unlike `execute_script("window.scrollBy(...)")` which returns immediately, the scroll API uses CDP's `awaitPromise` to wait for the browser's `scrollend` event, ensuring your next actions only execute after scrolling completely finishes. Perfect for taking screenshots, loading lazy content, or creating realistic reading patterns.
86
84
 
87
85
  ## 📦 Installation
88
86
 
@@ -32,37 +32,35 @@ Built from scratch with a different philosophy, Pydoll connects directly to the
32
32
 
33
33
  We believe that powerful automation shouldn't require you to become an expert in configuration or constantly fight with bot protection systems. With Pydoll, you can focus on what really matters: your automation logic, not the underlying complexity or protection systems.
34
34
 
35
- ### 🚀 Major Update in Development: Enhanced Stealth and Humanization Capabilities
35
+ ## 🌟 What makes Pydoll special?
36
36
 
37
- Pydoll is undergoing a significant development phase focused on incorporating advanced techniques for bot detection evasion and more realistic user interaction simulation.
37
+ - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
38
+ - **Human-like Interaction Engine**: Capable of passing behavioral CAPTCHAs like reCAPTCHA v3 or Turnstile, depending on IP reputation and interaction patterns
39
+ - **Asynchronous Performance**: For high-speed automation and multiple simultaneous tasks
40
+ - **Humanized Interactions**: Mimic real user behavior
41
+ - **Simplicity**: With Pydoll, you install and you're ready to automate.
38
42
 
39
- This update is based on extensive technical research and will include both substantial documentation improvements and new library features.
43
+ ## 🆕 What's New
40
44
 
41
- **Highlights of the Upcoming Release:**
45
+ ### Human-Like Page Scrolling: Scroll Like a Real User!
42
46
 
43
- * **Integrated Humanization Features:** Native implementations for:
44
- * **Mouse Interaction:** Simulation of cursor paths using Bezier curves, variable speeds based on Fitts's Law principles, and randomized click offsets. Event sequences (`mousemove`, `mousedown`, `mouseup`, `click`) will be handled automatically.
45
- * **Keyboard Input:** Character-by-character typing with randomized `Dwell` (key press duration) and `Flight` (time between keys) times. Optional simulation of typing errors and corrections.
46
- * **Scroll Simulation:** Physics-based scrolling mimicking momentum and inertia.
47
- * **Timing Variations:** Introduction of randomized delays ("cognitive time") before and after actions to avoid predictable automation patterns.
48
- * **Comprehensive Documentation Overhaul:** A new series of in-depth technical guides ("Deep Dives") covering:
49
- * **Network Fingerprinting:** Analysis of TCP/IP, TLS/JA3, and HTTP/2 characteristics. Includes practical examples like **building custom HTTP and SOCKS5 proxy servers** and discussing proxy detection techniques.
50
- * **Browser Fingerprinting:** Detailed exploration of `navigator` properties, Client Hints, Canvas/WebGL rendering, font detection, and screen attributes.
51
- * **Behavioral Fingerprinting:** Analysis of mouse dynamics, keystroke patterns (including bigram timing), scroll physics, and event sequencing.
52
- * **Advanced Browser Control:** Extensive documentation on using `browser_preferences` to modify hundreds of internal Chromium settings for granular control over performance, privacy, and fingerprinting.
53
- * **Practical Examples:** Including configurations for **Docker environments** and common evasion scenarios.
47
+ Now you can control page scrolling with smooth animations and automatic completion waiting:
54
48
 
55
- The aim is to provide users with both the theoretical understanding and the practical tools within Pydoll to create automation flows that are significantly harder to detect.
49
+ ```python
50
+ from pydoll.constants import ScrollPosition
56
51
 
57
- **Follow the progress by starring the repository ⭐!**
52
+ # Scroll down with smooth animation (waits for completion)
53
+ await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
58
54
 
59
- ## 🌟 What makes Pydoll special?
55
+ # Navigate to specific positions
56
+ await tab.scroll.to_bottom(smooth=True)
57
+ await tab.scroll.to_top(smooth=True)
60
58
 
61
- - **Zero Webdrivers**: Say goodbye to webdriver compatibility issues
62
- - **Human-like Interaction Engine**: Capable of passing behavioral CAPTCHAs like reCAPTCHA v3 or Turnstile, depending on IP reputation and interaction patterns
63
- - **Asynchronous Performance**: For high-speed automation and multiple simultaneous tasks
64
- - **Humanized Interactions**: Mimic real user behavior
65
- - **Simplicity**: With Pydoll, you install and you're ready to automate.
59
+ # Instant scroll for speed when realism isn't critical
60
+ await tab.scroll.by(ScrollPosition.UP, 300, smooth=False)
61
+ ```
62
+
63
+ Unlike `execute_script("window.scrollBy(...)")` which returns immediately, the scroll API uses CDP's `awaitPromise` to wait for the browser's `scrollend` event, ensuring your next actions only execute after scrolling completely finishes. Perfect for taking screenshots, loading lazy content, or creating realistic reading patterns.
66
64
 
67
65
  ## 📦 Installation
68
66
 
@@ -50,6 +50,7 @@ from pydoll.exceptions import (
50
50
  TopLevelTargetRequired,
51
51
  WaitElementTimeout,
52
52
  )
53
+ from pydoll.interactions.scroll import ScrollAPI
53
54
  from pydoll.protocol.browser.types import DownloadBehavior, DownloadProgressState
54
55
  from pydoll.protocol.page.events import PageEvent
55
56
  from pydoll.protocol.page.types import ScreenshotFormat
@@ -131,6 +132,7 @@ class Tab(FindElementsMixin):
131
132
  self._intercept_file_chooser_dialog_enabled = False
132
133
  self._cloudflare_captcha_callback_id: Optional[int] = None
133
134
  self._request: Optional[Request] = None
135
+ self._scroll: Optional[ScrollAPI] = None
134
136
  logger.debug(
135
137
  (
136
138
  f'Tab initialized: target_id={self._target_id}, '
@@ -176,6 +178,18 @@ class Tab(FindElementsMixin):
176
178
  self._request = Request(self)
177
179
  return self._request
178
180
 
181
+ @property
182
+ def scroll(self) -> ScrollAPI:
183
+ """
184
+ Get the scroll API for controlling page scroll behavior.
185
+
186
+ Returns:
187
+ ScrollAPI: An instance of the ScrollAPI class for scroll operations.
188
+ """
189
+ if self._scroll is None:
190
+ self._scroll = ScrollAPI(self)
191
+ return self._scroll
192
+
179
193
  @property
180
194
  def intercept_file_chooser_dialog_enabled(self) -> bool:
181
195
  """Whether file chooser dialog interception is active."""
@@ -15,6 +15,13 @@ class PageLoadState(str, Enum):
15
15
  INTERACTIVE = 'interactive'
16
16
 
17
17
 
18
+ class ScrollPosition(str, Enum):
19
+ UP = 'up'
20
+ DOWN = 'down'
21
+ LEFT = 'left'
22
+ RIGHT = 'right'
23
+
24
+
18
25
  class Scripts:
19
26
  ELEMENT_VISIBLE = """
20
27
  function() {
@@ -268,6 +275,87 @@ class Scripts:
268
275
  }})();
269
276
  """
270
277
 
278
+ SCROLL_BY = """
279
+ new Promise((resolve) => {{
280
+ const behavior = '{behavior}';
281
+ if (behavior === 'auto') {{
282
+ window.scrollBy({{
283
+ {axis}: {distance},
284
+ behavior: 'auto'
285
+ }});
286
+ resolve();
287
+ }} else {{
288
+ const onScrollEnd = () => {{
289
+ window.removeEventListener('scrollend', onScrollEnd);
290
+ resolve();
291
+ }};
292
+ window.addEventListener('scrollend', onScrollEnd);
293
+ window.scrollBy({{
294
+ {axis}: {distance},
295
+ behavior: 'smooth'
296
+ }});
297
+ setTimeout(() => {{
298
+ window.removeEventListener('scrollend', onScrollEnd);
299
+ resolve();
300
+ }}, 2000);
301
+ }}
302
+ }});
303
+ """
304
+
305
+ SCROLL_TO_TOP = """
306
+ new Promise((resolve) => {{
307
+ const behavior = '{behavior}';
308
+ if (behavior === 'auto') {{
309
+ window.scrollTo({{
310
+ top: 0,
311
+ behavior: 'auto'
312
+ }});
313
+ resolve();
314
+ }} else {{
315
+ const onScrollEnd = () => {{
316
+ window.removeEventListener('scrollend', onScrollEnd);
317
+ resolve();
318
+ }};
319
+ window.addEventListener('scrollend', onScrollEnd);
320
+ window.scrollTo({{
321
+ top: 0,
322
+ behavior: 'smooth'
323
+ }});
324
+ setTimeout(() => {{
325
+ window.removeEventListener('scrollend', onScrollEnd);
326
+ resolve();
327
+ }}, 2000);
328
+ }}
329
+ }});
330
+ """
331
+
332
+ SCROLL_TO_BOTTOM = """
333
+ new Promise((resolve) => {{
334
+ const behavior = '{behavior}';
335
+ if (behavior === 'auto') {{
336
+ window.scrollTo({{
337
+ top: document.body.scrollHeight,
338
+ behavior: 'auto'
339
+ }});
340
+ resolve();
341
+ }} else {{
342
+ const onScrollEnd = () => {{
343
+ window.removeEventListener('scrollend', onScrollEnd);
344
+ resolve();
345
+ }};
346
+ window.addEventListener('scrollend', onScrollEnd);
347
+ window.scrollTo({{
348
+ top: document.body.scrollHeight,
349
+ behavior: 'smooth'
350
+ }});
351
+ setTimeout(() => {{
352
+ window.removeEventListener('scrollend', onScrollEnd);
353
+ resolve();
354
+ }}, 2000);
355
+ }}
356
+ }});
357
+ """
358
+
271
359
 
272
360
  class Key(tuple[str, int], Enum):
273
361
  BACKSPACE = ('Backspace', 8)
@@ -0,0 +1,3 @@
1
+ from pydoll.interactions.scroll import ScrollAPI
2
+
3
+ __all__ = ['ScrollAPI']
@@ -0,0 +1,121 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pydoll.commands import RuntimeCommands
6
+ from pydoll.constants import Scripts, ScrollPosition
7
+
8
+ if TYPE_CHECKING:
9
+ from pydoll.browser.tab import Tab
10
+
11
+
12
+ class ScrollAPI:
13
+ """
14
+ API for controlling page scroll behavior.
15
+
16
+ Provides methods for scrolling the page in different directions,
17
+ to specific positions, or by relative distances.
18
+ """
19
+
20
+ def __init__(self, tab: Tab):
21
+ """
22
+ Initialize the ScrollAPI with a tab instance.
23
+
24
+ Args:
25
+ tab: Tab instance to execute scroll commands on.
26
+ """
27
+ self._tab = tab
28
+
29
+ async def by(
30
+ self,
31
+ position: ScrollPosition,
32
+ distance: int | float,
33
+ smooth: bool = True,
34
+ ):
35
+ """
36
+ Scroll the page by a relative distance in the specified direction.
37
+
38
+ Args:
39
+ position: Direction to scroll (UP, DOWN, LEFT, RIGHT).
40
+ distance: Number of pixels to scroll.
41
+ smooth: Use smooth scrolling animation if True, instant if False.
42
+ """
43
+ axis, scroll_distance = self._get_axis_and_distance(position, distance)
44
+ behavior = self._get_behavior(smooth)
45
+
46
+ script = Scripts.SCROLL_BY.format(
47
+ axis=axis,
48
+ distance=scroll_distance,
49
+ behavior=behavior,
50
+ )
51
+
52
+ await self._execute_script_await_promise(script)
53
+
54
+ async def to_top(self, smooth: bool = True):
55
+ """
56
+ Scroll to the top of the page (Y=0).
57
+
58
+ Args:
59
+ smooth: Use smooth scrolling animation if True, instant if False.
60
+ """
61
+ behavior = self._get_behavior(smooth)
62
+ script = Scripts.SCROLL_TO_TOP.format(behavior=behavior)
63
+ await self._execute_script_await_promise(script)
64
+
65
+ async def to_bottom(self, smooth: bool = True):
66
+ """
67
+ Scroll to the bottom of the page (Y=document.body.scrollHeight).
68
+
69
+ Args:
70
+ smooth: Use smooth scrolling animation if True, instant if False.
71
+ """
72
+ behavior = self._get_behavior(smooth)
73
+ script = Scripts.SCROLL_TO_BOTTOM.format(behavior=behavior)
74
+ await self._execute_script_await_promise(script)
75
+
76
+ @staticmethod
77
+ def _get_axis_and_distance(
78
+ position: ScrollPosition, distance: int | float
79
+ ) -> tuple[str, int | float]:
80
+ """
81
+ Convert scroll position to axis and signed distance.
82
+
83
+ Args:
84
+ position: Direction to scroll.
85
+ distance: Absolute distance to scroll.
86
+
87
+ Returns:
88
+ Tuple of (axis, signed_distance) where axis is 'left' or 'top'
89
+ and signed_distance is positive or negative based on direction.
90
+ """
91
+ if position in {ScrollPosition.UP, ScrollPosition.DOWN}:
92
+ axis = 'top'
93
+ scroll_distance = -distance if position == ScrollPosition.UP else distance
94
+ return axis, scroll_distance * 10
95
+
96
+ axis = 'left'
97
+ scroll_distance = -distance if position == ScrollPosition.LEFT else distance
98
+ return axis, scroll_distance * 10
99
+
100
+ @staticmethod
101
+ def _get_behavior(smooth: bool) -> str:
102
+ """
103
+ Convert smooth boolean to CSS scroll behavior value.
104
+
105
+ Args:
106
+ smooth: Whether to use smooth scrolling.
107
+
108
+ Returns:
109
+ 'smooth' if smooth is True, 'auto' otherwise.
110
+ """
111
+ return 'smooth' if smooth else 'auto'
112
+
113
+ async def _execute_script_await_promise(self, script: str):
114
+ """
115
+ Execute JavaScript and await promise resolution.
116
+
117
+ Args:
118
+ script: JavaScript code that returns a Promise.
119
+ """
120
+ command = RuntimeCommands.evaluate(expression=script, await_promise=True)
121
+ return await self._tab._execute_command(command)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pydoll-python"
3
- version = "2.9.3"
3
+ version = "2.10.0"
4
4
  description = "Pydoll is a library for automating chromium-based browsers without a WebDriver, offering realistic interactions."
5
5
  authors = ["Thalison Fernandes <thalissfernandes99@gmail.com>"]
6
6
  readme = "README.md"
File without changes