-
Notifications
You must be signed in to change notification settings - Fork 821
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
8,372 additions
and
871 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,16 @@ | ||
# -*- coding:utf-8 -*- | ||
""" | ||
@Author : g1879 | ||
@Contact : [email protected] | ||
""" | ||
|
||
from .drission import Drission | ||
from warnings import filterwarnings | ||
|
||
filterwarnings('ignore') | ||
from .mix_page import MixPage | ||
from .web_page import WebPage | ||
from .chromium_page import ChromiumPage | ||
from .session_page import SessionPage | ||
from .drission import Drission | ||
from .config import DriverOptions, SessionOptions | ||
from .action_chains import ActionChains |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
# -*- coding:utf-8 -*- | ||
""" | ||
@Author : g1879 | ||
@Contact : [email protected] | ||
""" | ||
from time import sleep | ||
|
||
from .common import _location_in_viewport | ||
from .keys import _modifierBit, _keyDescriptionForString | ||
|
||
|
||
class ActionChains: | ||
"""用于实现动作链的类""" | ||
|
||
def __init__(self, page): | ||
"""初始化 \n | ||
:param page: ChromiumPage对象 | ||
""" | ||
self.page = page | ||
self._dr = page.driver | ||
self.modifier = 0 # 修饰符,Alt=1, Ctrl=2, Meta/Command=4, Shift=8 | ||
self.curr_x = 0 # 视口坐标 | ||
self.curr_y = 0 | ||
|
||
def move_to(self, ele_or_loc, offset_x=0, offset_y=0): | ||
"""鼠标移动到元素中点,或页面上的某个绝对坐标。可设置偏移量 \n | ||
当带偏移量时,偏移量相对于元素左上角坐标 | ||
:param ele_or_loc: 元素对象、绝对坐标或文本定位符,坐标为tuple(int, int)形式 | ||
:param offset_x: 偏移量x | ||
:param offset_y: 偏移量y | ||
:return: self | ||
""" | ||
if isinstance(ele_or_loc, (tuple, list)): | ||
lx = ele_or_loc[0] + offset_x | ||
ly = ele_or_loc[1] + offset_y | ||
elif isinstance(ele_or_loc, str) or 'ChromiumElement' in str(type(ele_or_loc)): | ||
ele_or_loc = self.page(ele_or_loc) | ||
x, y = ele_or_loc.location if offset_x or offset_y else ele_or_loc.midpoint | ||
lx = x + offset_x | ||
ly = y + offset_y | ||
else: | ||
raise TypeError('ele_or_loc参数只能接受坐标(x, y)或ChromiumElement对象。') | ||
|
||
if not _location_in_viewport(self.page, lx, ly): | ||
self.page.scroll.to_location(lx, ly) | ||
|
||
cx, cy = location_to_client(self.page, lx, ly) | ||
self._dr.Input.dispatchMouseEvent(type='mouseMoved', x=cx, y=cy, modifiers=self.modifier) | ||
self.curr_x = cx | ||
self.curr_y = cy | ||
return self | ||
|
||
def move(self, offset_x=0, offset_y=0): | ||
"""鼠标相对当前位置移动若干位置 \n | ||
:param offset_x: 偏移量x | ||
:param offset_y: 偏移量y | ||
:return: self | ||
""" | ||
self.curr_x += offset_x | ||
self.curr_y += offset_y | ||
self._dr.Input.dispatchMouseEvent(type='mouseMoved', x=self.curr_x, y=self.curr_y, modifiers=self.modifier) | ||
return self | ||
|
||
def click(self, on_ele=None): | ||
"""点击鼠标左键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('left').wait(.05)._release('left') | ||
return self | ||
|
||
def r_click(self, on_ele=None): | ||
"""点击鼠标右键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('right').wait(.05)._release('right') | ||
return self | ||
|
||
def m_click(self, on_ele=None): | ||
"""点击鼠标中键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('middle').wait(.05)._release('middle') | ||
return self | ||
|
||
def hold(self, on_ele=None): | ||
"""按住鼠标左键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('left') | ||
return self | ||
|
||
def release(self, on_ele=None): | ||
"""释放鼠标左键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._release('left') | ||
return self | ||
|
||
def r_hold(self, on_ele=None): | ||
"""按住鼠标右键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('right') | ||
return self | ||
|
||
def r_release(self, on_ele=None): | ||
"""释放鼠标右键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._release('right') | ||
return self | ||
|
||
def m_hold(self, on_ele=None): | ||
"""按住鼠标中键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._hold('middle') | ||
return self | ||
|
||
def m_release(self, on_ele=None): | ||
"""释放鼠标中键,可先移动到元素上 \n | ||
:param on_ele: ChromiumElement元素或文本定位符 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._release('middle') | ||
return self | ||
|
||
def _hold(self, button): | ||
"""按下鼠标按键 \n | ||
:param button: 要按下的按键 | ||
:return: self | ||
""" | ||
self._dr.Input.dispatchMouseEvent(type='mousePressed', button=button, clickCount=1, | ||
x=self.curr_x, y=self.curr_y, modifiers=self.modifier) | ||
return self | ||
|
||
def _release(self, button): | ||
"""释放鼠标按键 \n | ||
:param button: 要释放的按键 | ||
:return: self | ||
""" | ||
self._dr.Input.dispatchMouseEvent(type='mouseReleased', button=button, clickCount=1, | ||
x=self.curr_x, y=self.curr_y, modifiers=self.modifier) | ||
return self | ||
|
||
def scroll(self, delta_x=0, delta_y=0, on_ele=None): | ||
"""滚动鼠标滚轮,可先移动到元素上 \n | ||
:param delta_x: 滚轮变化值x | ||
:param delta_y: 滚轮变化值y | ||
:param on_ele: ChromiumElement元素 | ||
:return: self | ||
""" | ||
if on_ele: | ||
self.move_to(on_ele) | ||
self._dr.Input.dispatchMouseEvent(type='mouseWheel', x=self.curr_x, y=self.curr_y, | ||
deltaX=delta_x, deltaY=delta_y, modifiers=self.modifier) | ||
return self | ||
|
||
def up(self, pixel): | ||
"""鼠标向上移动若干像素""" | ||
return self.move(0, -pixel) | ||
|
||
def down(self, pixel): | ||
"""鼠标向下移动若干像素""" | ||
return self.move(0, pixel) | ||
|
||
def left(self, pixel): | ||
"""鼠标向左移动若干像素""" | ||
return self.move(-pixel, 0) | ||
|
||
def right(self, pixel): | ||
"""鼠标向右移动若干像素""" | ||
return self.move(pixel, 0) | ||
|
||
def key_down(self, key): | ||
"""按下键盘上的按键 \n | ||
:param key: 按键,特殊字符见Keys | ||
:return: self | ||
""" | ||
if key in ('\ue009', '\ue008', '\ue00a', '\ue03d'): # 如果上修饰符,添加到变量 | ||
self.modifier |= _modifierBit.get(key, 0) | ||
return self | ||
|
||
data = self._get_key_data(key, 'keyDown') | ||
self.page.run_cdp('Input.dispatchKeyEvent', **data) | ||
return self | ||
|
||
def key_up(self, key): | ||
"""提起键盘上的按键 \n | ||
:param key: 按键,特殊字符见Keys | ||
:return: self | ||
""" | ||
if key in ('\ue009', '\ue008', '\ue00a', '\ue03d'): # 如果上修饰符,添加到变量 | ||
self.modifier ^= _modifierBit.get(key, 0) | ||
return self | ||
|
||
data = self._get_key_data(key, 'keyUp') | ||
self.page.run_cdp('Input.dispatchKeyEvent', **data) | ||
return self | ||
|
||
def type(self, text): | ||
"""输入文本 \n | ||
:param text: 要输入的文本 | ||
:return: self | ||
""" | ||
for i in text: | ||
self.key_down(i) | ||
sleep(.05) | ||
self.key_up(i) | ||
return self | ||
|
||
def wait(self, second): | ||
"""等待若干秒""" | ||
sleep(second) | ||
return self | ||
|
||
def _get_key_data(self, key, action): | ||
"""获取用于发送的按键信息 \n | ||
:param key: 按键 | ||
:param action: 'keyDown' 或 'keyUp' | ||
:return: 按键信息 | ||
""" | ||
description = _keyDescriptionForString(self.modifier, key) | ||
text = description['text'] | ||
if action != 'keyUp': | ||
action = 'keyDown' if text else 'rawKeyDown' | ||
return {'type': action, | ||
'modifiers': self.modifier, | ||
'windowsVirtualKeyCode': description['keyCode'], | ||
'code': description['code'], | ||
'key': description['key'], | ||
'text': text, | ||
'autoRepeat': False, | ||
'unmodifiedText': text, | ||
'location': description['location'], | ||
'isKeypad': description['location'] == 3} | ||
|
||
|
||
def location_to_client(page, lx, ly): | ||
"""绝对坐标转换为视口坐标""" | ||
scrool_x = page.run_script('return document.documentElement.scrollLeft;') | ||
scrool_y = page.run_script('return document.documentElement.scrollTop;') | ||
return lx + scrool_x, ly + scrool_y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# -*- coding:utf-8 -*- | ||
""" | ||
@Author : g1879 | ||
@Contact : [email protected] | ||
""" | ||
from typing import Union, Tuple | ||
|
||
from .chromium_base import ChromiumBase | ||
from .chromium_driver import ChromiumDriver | ||
from .chromium_element import ChromiumElement | ||
from .chromium_page import ChromiumPage | ||
|
||
|
||
class ActionChains: | ||
|
||
def __init__(self, page: ChromiumBase): | ||
self.page: ChromiumPage = ... | ||
self._dr: ChromiumDriver = ... | ||
self.curr_x: int = ... | ||
self.curr_y: int = ... | ||
self.modifier: int = ... | ||
|
||
def move_to(self, ele_or_loc: Union[ChromiumElement, Tuple[int, int], str], | ||
offset_x: int = ..., offset_y: int = ...) -> ActionChains: ... | ||
|
||
def move(self, offset_x: int = ..., offset_y: int = ...) -> ActionChains: ... | ||
|
||
def click(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def r_click(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def m_click(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def hold(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def release(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def r_hold(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def r_release(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def m_hold(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def m_release(self, on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def _hold(self, button: str) -> ActionChains: ... | ||
|
||
def _release(self, button: str) -> ActionChains: ... | ||
|
||
def scroll(self, delta_x: int = ..., delta_y: int = ..., on_ele: Union[ChromiumElement, str] = ...) -> ActionChains: ... | ||
|
||
def up(self, pixel: int) -> ActionChains: ... | ||
|
||
def down(self, pixel: int) -> ActionChains: ... | ||
|
||
def left(self, pixel: int) -> ActionChains: ... | ||
|
||
def right(self, pixel: int) -> ActionChains: ... | ||
|
||
def key_down(self, key: str) -> ActionChains: ... | ||
|
||
def key_up(self, key: str) -> ActionChains: ... | ||
|
||
def type(self, text: str) -> ActionChains: ... | ||
|
||
def wait(self, second: float) -> ActionChains: ... | ||
|
||
def _get_key_data(self, key: str, action: str) -> dict: ... | ||
|
||
|
||
def location_to_client(page, lx: int, ly: int) -> tuple: ... |
Oops, something went wrong.