diff --git a/DrissionPage/driver_element.py b/DrissionPage/driver_element.py index b07bf24..0d2b748 100644 --- a/DrissionPage/driver_element.py +++ b/DrissionPage/driver_element.py @@ -4,8 +4,9 @@ @Contact : g1879@qq.com @File : driver_element.py """ -import re + from pathlib import Path +from re import sub from time import sleep from typing import Union, List, Any, Tuple @@ -82,8 +83,8 @@ class DriverElement(DrissionElement): """返回元素内所有文本""" # return format_html(self.inner_ele.get_attribute('innerText'), False) re_str = self.inner_ele.get_attribute('innerText') - re_str = re.sub(r'\n{2,}', '\n', re_str) - re_str = re.sub(r' {2,}', ' ', re_str) + re_str = sub(r'\n{2,}', '\n', re_str) + re_str = sub(r' {2,}', ' ', re_str) return format_html(re_str.strip('\n '), False) @@ -104,6 +105,7 @@ class DriverElement(DrissionElement): @property def xpath(self) -> str: + """返回xpath路径""" return self._get_ele_path('xpath') @property @@ -114,12 +116,12 @@ class DriverElement(DrissionElement): @property def next(self): """返回后一个兄弟元素""" - return self._get_brother(1, 'ele', 'next') + return self.nexts() @property def prev(self): """返回前一个兄弟元素""" - return self._get_brother(1, 'ele', 'prev') + return self.prevs() @property def comments(self) -> list: @@ -385,22 +387,56 @@ class DriverElement(DrissionElement): from selenium.webdriver import ActionChains ActionChains(self.page.driver).move_to_element_with_offset(self.inner_ele, x, y).click().perform() - def input(self, value: Union[str, tuple], clear: bool = True) -> bool: - """输入文本或组合键 \n + def r_click(self) -> None: + """右键单击""" + from selenium.webdriver import ActionChains + ActionChains(self.page.driver).context_click(self.inner_ele).perform() + + def r_click_at(self, x: Union[int, str] = None, y: Union[int, str] = None) -> None: + """带偏移量右键单击本元素,相对于左上角坐标。不传入x或y值时点击元素中点 \n + :param x: 相对元素左上角坐标的x轴偏移量 + :param y: 相对元素左上角坐标的y轴偏移量 + :return: None + """ + x = int(x) if x is not None else self.size['width'] // 2 + y = int(y) if y is not None else self.size['height'] // 2 + from selenium.webdriver import ActionChains + ActionChains(self.page.driver).move_to_element_with_offset(self.inner_ele, x, y).context_click().perform() + + def input(self, value: Union[str, tuple], clear: bool = True) -> None: + """输入文本或组合键,可用于所有场合 \n :param value: 文本值或按键组合 :param clear: 输入前是否清空文本框 :return: 是否输入成功 """ - try: + if clear: + self.clear() + + self.inner_ele.send_keys(*value) + + def input_txt(self, txt: Union[str, tuple], clear: bool = True) -> None: + """专门用于输入文本框,解决文本框有时输入失效的问题 \n + :param txt: 文本值 + :param clear: 输入前是否清空文本框 + :return: 是否输入成功 + """ + enter = '\n' if txt.endswith('\n') else None + full_txt = txt if clear else f'{self.attr("value")}{txt}' + full_txt = full_txt.rstrip('\n') + from time import perf_counter + + t1 = perf_counter() + while True: + if self.attr('value') == full_txt or perf_counter() - t1 > self.page.timeout: + break + if clear: self.clear() - self.inner_ele.send_keys(*value) - return True + self.inner_ele.send_keys(txt) - except Exception as e: - print(e) - return False + if enter: + self.inner_ele.send_keys(enter) def run_script(self, script: str, *args) -> Any: """执行js代码,传入自己为第一个参数 \n @@ -416,8 +452,7 @@ class DriverElement(DrissionElement): def clear(self) -> None: """清空元素文本""" - self.run_script("arguments[0].value=''") - # self.inner_ele.clear() + self.inner_ele.clear() def is_selected(self) -> bool: """是否选中""" @@ -463,7 +498,14 @@ class DriverElement(DrissionElement): return img_path - def set_property(self, prop: str, value: str) -> bool: + def prop(self, prop: str) -> str: + """获取property属性值 \n + :param prop: 属性名 + :return: 属性值文本 + """ + return format_html(self.inner_ele.get_property(prop)) + + def set_prop(self, prop: str, value: str) -> bool: """设置元素property属性 \n :param prop: 属性名 :param value: 属性值 @@ -669,8 +711,8 @@ def execute_driver_find(page_or_ele, if timeout is not None and timeout != page.timeout: wait = WebDriverWait(driver, timeout=timeout) else: - page.wait._driver = driver - wait = page.wait + page.wait_object._driver = driver + wait = page.wait_object try: # 使用xpath查找 diff --git a/DrissionPage/driver_page.py b/DrissionPage/driver_page.py index e8dee6f..083b96e 100644 --- a/DrissionPage/driver_page.py +++ b/DrissionPage/driver_page.py @@ -5,15 +5,15 @@ @File : driver_page.py """ from glob import glob - from pathlib import Path +from time import time, sleep +from typing import Union, List, Any, Tuple +from urllib.parse import quote + from selenium.common.exceptions import NoAlertPresentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.wait import WebDriverWait -from time import time, sleep -from typing import Union, List, Any, Tuple -from urllib.parse import quote from .common import str_to_loc, get_available_file_name, translate_loc, format_html from .driver_element import DriverElement, execute_driver_find @@ -33,6 +33,12 @@ class DriverPage(object): self.retry_times = 3 self.retry_interval = 2 + def __call__(self, + loc_or_str: Union[Tuple[str, str], str, DriverElement, WebElement], + mode: str = 'single', + timeout: float = None): + return self.ele(loc_or_str, mode, timeout) + @property def driver(self) -> WebDriver: return self._driver @@ -67,15 +73,18 @@ class DriverPage(object): @property def timeout(self) -> float: + """返回查找元素时等待的秒数""" return self._timeout @timeout.setter def timeout(self, second: float) -> None: + """设置查找元素时等待的秒数""" self._timeout = second self._wait = None @property - def wait(self) -> WebDriverWait: + def wait_object(self) -> WebDriverWait: + """返回WebDriverWait对象,重用避免每次新建对象""" if self._wait is None: self._wait = WebDriverWait(self.driver, timeout=self.timeout) diff --git a/DrissionPage/session_element.py b/DrissionPage/session_element.py index 0bcf345..6589a25 100644 --- a/DrissionPage/session_element.py +++ b/DrissionPage/session_element.py @@ -4,7 +4,7 @@ @Contact : g1879@qq.com @File : session_element.py """ -import re +from re import match, DOTALL, sub from typing import Union, List, Tuple from urllib.parse import urlparse, urljoin, urlunparse @@ -42,7 +42,7 @@ class SessionElement(DrissionElement): @property def inner_html(self) -> str: """返回元素innerHTML文本""" - r = re.match(r'<.*?>(.*)', self.html, flags=re.DOTALL) + r = match(r'<.*?>(.*)', self.html, flags=DOTALL) return '' if not r else r.group(1) @property @@ -79,7 +79,7 @@ class SessionElement(DrissionElement): return str_list re_str = ''.join(get_node(self)) - re_str = re.sub(r' {2,}', ' ', re_str) + re_str = sub(r' {2,}', ' ', re_str) return format_html(re_str, False) @property @@ -120,15 +120,16 @@ class SessionElement(DrissionElement): @property def next(self): """返回后一个兄弟元素""" - return self._get_brother(1, 'ele', 'next') + return self.nexts() @property def prev(self): """返回前一个兄弟元素""" - return self._get_brother(1, 'ele', 'prev') + return self.prevs() @property - def comments(self): + def comments(self) -> list: + """返回元素注释文本组成的列表""" return self.eles('xpath:.//comment()') def texts(self, text_node_only: bool = False) -> list: diff --git a/DrissionPage/session_page.py b/DrissionPage/session_page.py index 3df02b2..669acd8 100644 --- a/DrissionPage/session_page.py +++ b/DrissionPage/session_page.py @@ -4,17 +4,15 @@ @Contact : g1879@qq.com @File : session_page.py """ -import re from os import path as os_PATH from pathlib import Path from random import randint -from re import search as re_SEARCH -from re import sub as re_SUB +from re import search as re_SEARCH, sub as re_SUB +from time import time, sleep from typing import Union, List, Tuple from urllib.parse import urlparse, quote, unquote from requests import Session, Response -from time import time, sleep from tldextract import extract from .common import str_to_loc, translate_loc, get_available_file_name, format_html @@ -36,6 +34,12 @@ class SessionPage(object): self.retry_times = 3 self.retry_interval = 2 + def __call__(self, + loc_or_str: Union[Tuple[str, str], str, SessionElement], + mode: str = 'single', + timeout: float = None): + return self.ele(loc_or_str, mode) + @property def session(self) -> Session: """返回session对象""" @@ -368,7 +372,7 @@ class SessionPage(object): # 使用header里的文件名 if content_disposition: file_name = content_disposition.encode('ISO-8859-1').decode('utf-8') - file_name = re.search(r'filename *= *"?([^";]+)', file_name) + file_name = re_SEARCH(r'filename *= *"?([^";]+)', file_name) if file_name: file_name = file_name.group(1) @@ -569,7 +573,7 @@ class SessionPage(object): # ----------------获取并设置编码开始----------------- # 在headers中获取编码 content_type = r.headers.get('content-type', '').lower() - charset = re.search(r'charset[=: ]*(.*)?[;]', content_type) + charset = re_SEARCH(r'charset[=: ]*(.*)?[;]', content_type) if charset: r.encoding = charset.group(1) diff --git a/DrissionPage/shadow_root_element.py b/DrissionPage/shadow_root_element.py index f60cc84..fe00b0d 100644 --- a/DrissionPage/shadow_root_element.py +++ b/DrissionPage/shadow_root_element.py @@ -36,7 +36,7 @@ class ShadowRootElement(DrissionElement): return 'shadow-root' @property - def html(self): + def html(self) -> str: """内部html文本""" return format_html(self.inner_ele.get_attribute('innerHTML'))