pydoll-python 2.12.4__tar.gz → 2.13.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.
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/PKG-INFO +51 -1
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/README.md +50 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/constants.py +79 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/elements/mixins/find_elements_mixin.py +33 -2
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/elements/web_element.py +122 -601
- pydoll_python-2.13.0/pydoll/interactions/__init__.py +25 -0
- pydoll_python-2.13.0/pydoll/interactions/iframe.py +359 -0
- pydoll_python-2.13.0/pydoll/interactions/keyboard.py +463 -0
- pydoll_python-2.13.0/pydoll/interactions/scroll.py +437 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pyproject.toml +1 -1
- pydoll_python-2.12.4/pydoll/interactions/__init__.py +0 -4
- pydoll_python-2.12.4/pydoll/interactions/keyboard.py +0 -178
- pydoll_python-2.12.4/pydoll/interactions/scroll.py +0 -121
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/LICENSE +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/chromium/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/chromium/base.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/chromium/chrome.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/chromium/edge.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/interfaces.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/managers/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/managers/browser_options_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/managers/browser_process_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/managers/proxy_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/managers/temp_dir_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/options.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/requests/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/requests/request.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/requests/response.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/browser/tab.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/browser_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/dom_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/fetch_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/input_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/network_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/page_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/runtime_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/storage_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/commands/target_commands.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/connection/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/connection/connection_handler.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/connection/managers/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/connection/managers/commands_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/connection/managers/events_manager.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/decorators.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/elements/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/elements/mixins/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/exceptions.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/base.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/browser/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/browser/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/browser/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/browser/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/debugger/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/dom/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/dom/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/dom/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/dom/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/emulation/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/fetch/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/fetch/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/fetch/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/fetch/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/input/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/input/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/input/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/input/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/io/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/network/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/network/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/network/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/network/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/page/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/page/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/page/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/page/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/runtime/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/runtime/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/runtime/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/runtime/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/security/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/storage/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/storage/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/storage/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/storage/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/target/__init__.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/target/events.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/target/methods.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/protocol/target/types.py +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/py.typed +0 -0
- {pydoll_python-2.12.4 → pydoll_python-2.13.0}/pydoll/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydoll-python
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.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
|
|
@@ -59,6 +59,56 @@ pip install pydoll-python
|
|
|
59
59
|
```
|
|
60
60
|
That's it. No `webdrivers`. No external dependencies.
|
|
61
61
|
|
|
62
|
+
<details>
|
|
63
|
+
<summary><b>🆕 What's New</b></summary>
|
|
64
|
+
<br>
|
|
65
|
+
|
|
66
|
+
### Humanized Keyboard Input (`humanize=True`)
|
|
67
|
+
|
|
68
|
+
Pydoll now includes a **humanized typing engine** that simulates realistic human typing behavior:
|
|
69
|
+
|
|
70
|
+
- **Variable keystroke timing**: 30-120ms between keys (not fixed intervals)
|
|
71
|
+
- **Realistic typos**: ~2% error rate with automatic correction behavior
|
|
72
|
+
- **No more `interval` parameter**: Just use `humanize=True` for anti-bot evasion
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
# Old way (detectable)
|
|
76
|
+
await element.type_text("hello", interval=0.1)
|
|
77
|
+
|
|
78
|
+
# New way (human-like, anti-bot)
|
|
79
|
+
await element.type_text("hello", humanize=True)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### Humanized Scroll with Physics Engine (`humanize=True`)
|
|
85
|
+
|
|
86
|
+
The scroll API now features a **Cubic Bezier curve physics engine** for realistic scrolling:
|
|
87
|
+
|
|
88
|
+
- **Momentum & friction**: Natural acceleration and deceleration
|
|
89
|
+
- **Micro-pauses**: Brief stops during long scrolls (simulates reading)
|
|
90
|
+
- **Jitter injection**: Small random variations in scroll path
|
|
91
|
+
- **Overshoot correction**: Occasionally scrolls past target and corrects back
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Smooth scroll (CSS animation, predictable timing)
|
|
95
|
+
await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
|
|
96
|
+
|
|
97
|
+
# Humanized scroll (physics engine, anti-bot)
|
|
98
|
+
await tab.scroll.by(ScrollPosition.DOWN, 500, humanize=True)
|
|
99
|
+
await tab.scroll.to_bottom(humanize=True)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| Mode | Parameter | Use Case |
|
|
103
|
+
|------|-----------|----------|
|
|
104
|
+
| **Instant** | `smooth=False` | Speed-critical operations |
|
|
105
|
+
| **Smooth** | `smooth=True` | General browsing simulation |
|
|
106
|
+
| **Humanized** | `humanize=True` | **Anti-bot evasion** |
|
|
107
|
+
|
|
108
|
+
[**📖 Human-Like Interactions Docs**](https://pydoll.tech/docs/features/automation/human-interactions/)
|
|
109
|
+
|
|
110
|
+
</details>
|
|
111
|
+
|
|
62
112
|
## 🚀 Getting Started in 60 Seconds
|
|
63
113
|
|
|
64
114
|
Thanks to its `async` architecture and context managers, Pydoll is clean and efficient.
|
|
@@ -39,6 +39,56 @@ pip install pydoll-python
|
|
|
39
39
|
```
|
|
40
40
|
That's it. No `webdrivers`. No external dependencies.
|
|
41
41
|
|
|
42
|
+
<details>
|
|
43
|
+
<summary><b>🆕 What's New</b></summary>
|
|
44
|
+
<br>
|
|
45
|
+
|
|
46
|
+
### Humanized Keyboard Input (`humanize=True`)
|
|
47
|
+
|
|
48
|
+
Pydoll now includes a **humanized typing engine** that simulates realistic human typing behavior:
|
|
49
|
+
|
|
50
|
+
- **Variable keystroke timing**: 30-120ms between keys (not fixed intervals)
|
|
51
|
+
- **Realistic typos**: ~2% error rate with automatic correction behavior
|
|
52
|
+
- **No more `interval` parameter**: Just use `humanize=True` for anti-bot evasion
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
# Old way (detectable)
|
|
56
|
+
await element.type_text("hello", interval=0.1)
|
|
57
|
+
|
|
58
|
+
# New way (human-like, anti-bot)
|
|
59
|
+
await element.type_text("hello", humanize=True)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### Humanized Scroll with Physics Engine (`humanize=True`)
|
|
65
|
+
|
|
66
|
+
The scroll API now features a **Cubic Bezier curve physics engine** for realistic scrolling:
|
|
67
|
+
|
|
68
|
+
- **Momentum & friction**: Natural acceleration and deceleration
|
|
69
|
+
- **Micro-pauses**: Brief stops during long scrolls (simulates reading)
|
|
70
|
+
- **Jitter injection**: Small random variations in scroll path
|
|
71
|
+
- **Overshoot correction**: Occasionally scrolls past target and corrects back
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Smooth scroll (CSS animation, predictable timing)
|
|
75
|
+
await tab.scroll.by(ScrollPosition.DOWN, 500, smooth=True)
|
|
76
|
+
|
|
77
|
+
# Humanized scroll (physics engine, anti-bot)
|
|
78
|
+
await tab.scroll.by(ScrollPosition.DOWN, 500, humanize=True)
|
|
79
|
+
await tab.scroll.to_bottom(humanize=True)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Mode | Parameter | Use Case |
|
|
83
|
+
|------|-----------|----------|
|
|
84
|
+
| **Instant** | `smooth=False` | Speed-critical operations |
|
|
85
|
+
| **Smooth** | `smooth=True` | General browsing simulation |
|
|
86
|
+
| **Humanized** | `humanize=True` | **Anti-bot evasion** |
|
|
87
|
+
|
|
88
|
+
[**📖 Human-Like Interactions Docs**](https://pydoll.tech/docs/features/automation/human-interactions/)
|
|
89
|
+
|
|
90
|
+
</details>
|
|
91
|
+
|
|
42
92
|
## 🚀 Getting Started in 60 Seconds
|
|
43
93
|
|
|
44
94
|
Thanks to its `async` architecture and context managers, Pydoll is clean and efficient.
|
|
@@ -382,6 +382,22 @@ new Promise((resolve) => {{
|
|
|
382
382
|
}});
|
|
383
383
|
"""
|
|
384
384
|
|
|
385
|
+
GET_SCROLL_Y = 'window.scrollY || window.pageYOffset || 0'
|
|
386
|
+
|
|
387
|
+
GET_REMAINING_SCROLL_TO_BOTTOM = """
|
|
388
|
+
(function() {
|
|
389
|
+
const scrollHeight = Math.max(
|
|
390
|
+
document.body.scrollHeight,
|
|
391
|
+
document.documentElement.scrollHeight
|
|
392
|
+
);
|
|
393
|
+
const clientHeight = window.innerHeight;
|
|
394
|
+
const scrollTop = window.scrollY || window.pageYOffset || 0;
|
|
395
|
+
return Math.max(0, scrollHeight - clientHeight - scrollTop);
|
|
396
|
+
})()
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
GET_VIEWPORT_CENTER = 'JSON.stringify([window.innerWidth / 2, window.innerHeight / 2])'
|
|
400
|
+
|
|
385
401
|
INSERT_TEXT = """
|
|
386
402
|
function() {
|
|
387
403
|
const el = this;
|
|
@@ -562,3 +578,66 @@ class Key(tuple[str, int], Enum):
|
|
|
562
578
|
class BrowserType(Enum):
|
|
563
579
|
CHROME = auto()
|
|
564
580
|
EDGE = auto()
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
class TypoType(str, Enum):
|
|
584
|
+
"""Types of realistic typing errors."""
|
|
585
|
+
|
|
586
|
+
ADJACENT = 'adjacent'
|
|
587
|
+
TRANSPOSE = 'transpose'
|
|
588
|
+
DOUBLE = 'double'
|
|
589
|
+
SKIP = 'skip'
|
|
590
|
+
MISSED_SPACE = 'missed_space'
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
DEFAULT_TYPO_PROBABILITY = 0.02
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
QWERTY_NEIGHBORS: dict[str, list[str]] = {
|
|
597
|
+
'1': ['2', 'q'],
|
|
598
|
+
'2': ['1', '3', 'q', 'w'],
|
|
599
|
+
'3': ['2', '4', 'w', 'e'],
|
|
600
|
+
'4': ['3', '5', 'e', 'r'],
|
|
601
|
+
'5': ['4', '6', 'r', 't'],
|
|
602
|
+
'6': ['5', '7', 't', 'y'],
|
|
603
|
+
'7': ['6', '8', 'y', 'u'],
|
|
604
|
+
'8': ['7', '9', 'u', 'i'],
|
|
605
|
+
'9': ['8', '0', 'i', 'o'],
|
|
606
|
+
'0': ['9', '-', 'o', 'p'],
|
|
607
|
+
'-': ['0', '=', 'p', '['],
|
|
608
|
+
'=': ['-', '[', ']'],
|
|
609
|
+
'q': ['1', '2', 'w', 'a', 's'],
|
|
610
|
+
'w': ['q', '2', '3', 'e', 'a', 's', 'd'],
|
|
611
|
+
'e': ['w', '3', '4', 'r', 's', 'd', 'f'],
|
|
612
|
+
'r': ['e', '4', '5', 't', 'd', 'f', 'g'],
|
|
613
|
+
't': ['r', '5', '6', 'y', 'f', 'g', 'h'],
|
|
614
|
+
'y': ['t', '6', '7', 'u', 'g', 'h', 'j'],
|
|
615
|
+
'u': ['y', '7', '8', 'i', 'h', 'j', 'k'],
|
|
616
|
+
'i': ['u', '8', '9', 'o', 'j', 'k', 'l'],
|
|
617
|
+
'o': ['i', '9', '0', 'p', 'k', 'l', ';'],
|
|
618
|
+
'p': ['o', '0', '-', '[', 'l', ';', "'"],
|
|
619
|
+
'[': ['p', '-', '=', ']', ';', "'"],
|
|
620
|
+
']': ['[', '=', "'"],
|
|
621
|
+
'a': ['q', 'w', 's', 'z', 'x'],
|
|
622
|
+
's': ['q', 'w', 'e', 'a', 'd', 'z', 'x', 'c'],
|
|
623
|
+
'd': ['w', 'e', 'r', 's', 'f', 'x', 'c', 'v'],
|
|
624
|
+
'f': ['e', 'r', 't', 'd', 'g', 'c', 'v', 'b'],
|
|
625
|
+
'g': ['r', 't', 'y', 'f', 'h', 'v', 'b', 'n'],
|
|
626
|
+
'h': ['t', 'y', 'u', 'g', 'j', 'b', 'n', 'm'],
|
|
627
|
+
'j': ['y', 'u', 'i', 'h', 'k', 'n', 'm', ','],
|
|
628
|
+
'k': ['u', 'i', 'o', 'j', 'l', 'm', ',', '.'],
|
|
629
|
+
'l': ['i', 'o', 'p', 'k', ';', ',', '.', '/'],
|
|
630
|
+
';': ['o', 'p', '[', 'l', "'", '.', '/'],
|
|
631
|
+
"'": ['p', '[', ']', ';', '/'],
|
|
632
|
+
'z': ['a', 's', 'x'],
|
|
633
|
+
'x': ['z', 'a', 's', 'd', 'c'],
|
|
634
|
+
'c': ['x', 's', 'd', 'f', 'v'],
|
|
635
|
+
'v': ['c', 'd', 'f', 'g', 'b'],
|
|
636
|
+
'b': ['v', 'f', 'g', 'h', 'n'],
|
|
637
|
+
'n': ['b', 'g', 'h', 'j', 'm'],
|
|
638
|
+
'm': ['n', 'h', 'j', 'k', ','],
|
|
639
|
+
',': ['m', 'j', 'k', 'l', '.'],
|
|
640
|
+
'.': [',', 'k', 'l', ';', '/'],
|
|
641
|
+
'/': ['.', 'l', ';', "'"],
|
|
642
|
+
' ': ['c', 'v', 'b', 'n', 'm'],
|
|
643
|
+
}
|
|
@@ -11,11 +11,13 @@ from pydoll.commands import (
|
|
|
11
11
|
from pydoll.connection.connection_handler import ConnectionHandler
|
|
12
12
|
from pydoll.constants import By, Scripts
|
|
13
13
|
from pydoll.exceptions import ElementNotFound, WaitElementTimeout
|
|
14
|
+
from pydoll.utils import normalize_synthetic_xpath
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from typing import Literal, Optional, Union
|
|
17
18
|
|
|
18
|
-
from pydoll.elements.web_element import WebElement
|
|
19
|
+
from pydoll.elements.web_element import WebElement
|
|
20
|
+
from pydoll.interactions.iframe import IFrameContext
|
|
19
21
|
from pydoll.protocol.base import Command, T_CommandParams, T_CommandResponse
|
|
20
22
|
from pydoll.protocol.dom.methods import DescribeNodeResponse
|
|
21
23
|
from pydoll.protocol.dom.types import Node
|
|
@@ -56,6 +58,35 @@ class FindElementsMixin:
|
|
|
56
58
|
if TYPE_CHECKING:
|
|
57
59
|
_connection_handler: ConnectionHandler
|
|
58
60
|
|
|
61
|
+
@staticmethod
|
|
62
|
+
def _build_text_expression(selector: str, method: str) -> Optional[str]:
|
|
63
|
+
"""
|
|
64
|
+
Build JS expression using Scripts to extract textContent based on selector type.
|
|
65
|
+
"""
|
|
66
|
+
raw = str(selector)
|
|
67
|
+
method_lc = (method or '').lower()
|
|
68
|
+
|
|
69
|
+
if 'xpath' in method_lc:
|
|
70
|
+
normalized_xpath = normalize_synthetic_xpath(raw)
|
|
71
|
+
escaped_xpath = normalized_xpath.replace('"', '\\"')
|
|
72
|
+
return Scripts.GET_TEXT_BY_XPATH.replace('{escaped_value}', escaped_xpath)
|
|
73
|
+
|
|
74
|
+
if method_lc == 'name':
|
|
75
|
+
escaped_name = raw.replace('"', '\\"')
|
|
76
|
+
xpath = f'//*[@name="{escaped_name}"]'
|
|
77
|
+
return Scripts.GET_TEXT_BY_XPATH.replace('{escaped_value}', xpath)
|
|
78
|
+
|
|
79
|
+
escaped = raw.replace('\\', '\\\\').replace('"', '\\"')
|
|
80
|
+
if method_lc == 'id':
|
|
81
|
+
css = f'#{escaped}'
|
|
82
|
+
elif method_lc == 'class_name':
|
|
83
|
+
css = f'.{escaped}'
|
|
84
|
+
elif method_lc == 'tag_name':
|
|
85
|
+
css = escaped
|
|
86
|
+
else:
|
|
87
|
+
css = escaped
|
|
88
|
+
return Scripts.GET_TEXT_BY_CSS.replace('{selector}', css)
|
|
89
|
+
|
|
59
90
|
@overload
|
|
60
91
|
async def find(
|
|
61
92
|
self,
|
|
@@ -583,7 +614,7 @@ class FindElementsMixin:
|
|
|
583
614
|
return response.get('result', {}).get('node', {})
|
|
584
615
|
|
|
585
616
|
def _apply_iframe_context_to_element(
|
|
586
|
-
self, element: WebElement, iframe_context:
|
|
617
|
+
self, element: WebElement, iframe_context: IFrameContext | None
|
|
587
618
|
) -> None:
|
|
588
619
|
"""
|
|
589
620
|
Propagate iframe context to the newly created element.
|