diff --git a/DrissionPage/driver_element.py b/DrissionPage/driver_element.py index bcafd7e..8d5d43a 100644 --- a/DrissionPage/driver_element.py +++ b/DrissionPage/driver_element.py @@ -30,6 +30,7 @@ class DriverElement(DrissionElement): """ super().__init__(ele, page) self._select = None + self._scroll = None def __repr__(self) -> str: attrs = [f"{attr}='{self.attrs[attr]}'" for attr in self.attrs] @@ -240,6 +241,13 @@ class DriverElement(DrissionElement): return self._select + @property + def scroll(self) -> 'Scroll': + """用于滚动滚动条的对象""" + if self._scroll is None: + self._scroll = Scroll(self) + return self._scroll + def left(self, index: int = 1, filter_loc: Union[tuple, str] = '') -> 'DriverElement': """获取网页上显示在当前元素左边的某个元素,可设置选取条件,可指定结果中第几个 \n :param index: 获取第几个 @@ -483,34 +491,34 @@ class DriverElement(DrissionElement): :param pixel: 滚动的像素 :return: None """ + from warnings import warn + warn("此方法下个版本将停用,请用scroll属性代替。", DeprecationWarning, stacklevel=2) if mode == 'top': - self.run_script("arguments[0].scrollTo(arguments[0].scrollLeft,0);") + self.scroll.top() elif mode == 'bottom': - self.run_script("arguments[0].scrollTo(arguments[0].scrollLeft,arguments[0].scrollHeight);") + self.scroll.bottom() elif mode == 'half': - self.run_script("arguments[0].scrollTo(arguments[0].scrollLeft,arguments[0].scrollHeight/2);") + self.scroll.half() elif mode == 'rightmost': - self.run_script("arguments[0].scrollTo(arguments[0].scrollWidth,arguments[0].scrollTop);") + self.scroll.rightmost() elif mode == 'leftmost': - self.run_script("arguments[0].scrollTo(0,arguments[0].scrollTop);") + self.scroll.leftmost() elif mode == 'up': - pixel = pixel if pixel >= 0 else -pixel - self.run_script(f"arguments[0].scrollBy(0,{pixel});") + self.scroll.up(pixel) elif mode == 'down': - self.run_script(f"arguments[0].scrollBy(0,{pixel});") + self.scroll.down(pixel) elif mode == 'left': - pixel = pixel if pixel >= 0 else -pixel - self.run_script(f"arguments[0].scrollBy({pixel},0);") + self.scroll.left(pixel) elif mode == 'right': - self.run_script(f"arguments[0].scrollBy({pixel},0);") + self.scroll.right(pixel) else: raise ValueError("mode参数只能是'top', 'bottom', 'half', 'rightmost', " @@ -1125,3 +1133,78 @@ def _wait_ele(page_or_ele, except Exception: return False + + +class Scroll(object): + """用于滚动的对象""" + + def __init__(self, page_or_ele): + """ + :param page_or_ele: DriverPage或DriverElement + """ + self.driver = page_or_ele + if isinstance(page_or_ele, DriverElement): + self.t1 = self.t2 = 'arguments[0]' + else: + self.t1 = 'window' + self.t2 = 'document.documentElement' + + def top(self) -> None: + """滚动到顶端,水平位置不变""" + self.driver.run_script(f'{self.t1}.scrollTo({self.t2}.scrollLeft,0);') + + def bottom(self) -> None: + """滚动到底端,水平位置不变""" + self.driver.run_script(f'{self.t1}.scrollTo({self.t2}.scrollLeft,{self.t2}.scrollHeight);') + + def half(self) -> None: + """滚动到垂直中间位置,水平位置不变""" + self.driver.run_script(f'{self.t1}.scrollTo({self.t2}.scrollLeft,{self.t2}.scrollHeight/2);') + + def rightmost(self) -> None: + """滚动到最右边,垂直位置不变""" + self.driver.run_script(f'{self.t1}.scrollTo({self.t2}.scrollWidth,{self.t2}.scrollTop);') + + def leftmost(self) -> None: + """滚动到最左边,垂直位置不变""" + self.driver.run_script(f'{self.t1}.scrollTo(0,{self.t2}.scrollTop);') + + def up(self, pixel: int = 300) -> None: + """向上滚动若干像素,水平位置不变 \n + :param pixel: 滚动的像素 + :return: None + """ + if pixel < 0: + self.down(-pixel) + else: + self.driver.run_script(f'{self.t1}.scrollBy(0,-{pixel});') + + def down(self, pixel: int = 300) -> None: + """向下滚动若干像素,水平位置不变 \n + :param pixel: 滚动的像素 + :return: None + """ + if pixel < 0: + self.up(-pixel) + else: + self.driver.run_script(f'{self.t1}.scrollBy(0,{pixel});') + + def left(self, pixel: int = 300) -> None: + """向左滚动若干像素,水平位置不变 \n + :param pixel: 滚动的像素 + :return: None + """ + if pixel < 0: + self.right(-pixel) + else: + self.driver.run_script(f'{self.t1}.scrollBy(-{pixel},0);') + + def right(self, pixel: int = 300) -> None: + """向右滚动若干像素,水平位置不变 \n + :param pixel: 滚动的像素 + :return: None + """ + if pixel < 0: + self.left(-pixel) + else: + self.driver.run_script(f'{self.t1}.scrollBy({pixel},0);') diff --git a/DrissionPage/driver_page.py b/DrissionPage/driver_page.py index 3bb61ad..327c426 100644 --- a/DrissionPage/driver_page.py +++ b/DrissionPage/driver_page.py @@ -18,7 +18,7 @@ from selenium.webdriver.support.wait import WebDriverWait from .base import BasePage from .common import get_usable_path -from .driver_element import DriverElement, make_driver_ele, _wait_ele +from .driver_element import DriverElement, make_driver_ele, _wait_ele, Scroll from .session_element import make_session_ele @@ -30,6 +30,7 @@ class DriverPage(BasePage): super().__init__(timeout) self._driver = driver self._wait_object = None + self._scroll = None def __call__(self, loc_or_str: Union[Tuple[str, str], str, DriverElement, WebElement], timeout: float = None) -> Union[DriverElement, List[DriverElement], str]: @@ -61,6 +62,13 @@ class DriverPage(BasePage): from json import loads return loads(self('t:pre').text) + @property + def scroll(self) -> Scroll: + """用于滚动滚动条的对象""" + if self._scroll is None: + self._scroll = Scroll(self) + return self._scroll + def get(self, url: str, go_anyway: bool = False, @@ -442,36 +450,34 @@ class DriverPage(BasePage): :param pixel: 滚动的像素 :return: None """ + from warnings import warn + warn("此方法下个版本将停用,请用scroll属性代替。", DeprecationWarning, stacklevel=2) if mode == 'top': - self.driver.execute_script("window.scrollTo(document.documentElement.scrollLeft,0);") + self.scroll.top() elif mode == 'bottom': - self.driver.execute_script( - "window.scrollTo(document.documentElement.scrollLeft,document.body.scrollHeight);") + self.scroll.bottom() elif mode == 'half': - self.driver.execute_script( - "window.scrollTo(document.documentElement.scrollLeft,document.body.scrollHeight/2);") + self.scroll.half() elif mode == 'rightmost': - self.driver.execute_script("window.scrollTo(document.body.scrollWidth,document.documentElement.scrollTop);") + self.scroll.rightmost() elif mode == 'leftmost': - self.driver.execute_script("window.scrollTo(0,document.documentElement.scrollTop);") + self.scroll.leftmost() elif mode == 'up': - pixel = pixel if pixel >= 0 else -pixel - self.driver.execute_script(f"window.scrollBy(0,{pixel});") + self.scroll.up(pixel) elif mode == 'down': - self.driver.execute_script(f"window.scrollBy(0,{pixel});") + self.scroll.down(pixel) elif mode == 'left': - pixel = pixel if pixel >= 0 else -pixel - self.driver.execute_script(f"window.scrollBy({pixel},0);") + self.scroll.left(pixel) elif mode == 'right': - self.driver.execute_script(f"window.scrollBy({pixel},0);") + self.scroll.right(pixel) else: raise ValueError("mode参数只能是'top', 'bottom', 'half', 'rightmost', " diff --git a/DrissionPage/mix_page.py b/DrissionPage/mix_page.py index 6512726..c87a916 100644 --- a/DrissionPage/mix_page.py +++ b/DrissionPage/mix_page.py @@ -51,6 +51,7 @@ class MixPage(SessionPage, DriverPage, BasePage): self._drission = drission or Drission(driver_options, session_options) self._wait_object = None self._response = None + self._scroll = None if self._mode == 'd': try: