# -*- coding: utf-8 -*-## file: BasePage# Author: ShunZhe# Date: 2021/1/9import osimport shutilimport timefrom datetime import datetimefrom func_timeout.exceptions import FunctionTimedOutfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWaitfrom common import loggerDelayTime = 1class BasePage: def __init__(self, driver): self.driver = driver # ---------------------------------------------------- def get_element(self, style, delay=DelayTime, describe=''): """ :param style: 元素定位 :param delay: :param describe: 描述用例执行,主要用于日志调试记录,非必填 :return: """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] for i in range(5): try: if by == "id": element = self.driver.find_element_by_id(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "name": element = self.driver.find_element_by_name(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "class": element = self.driver.find_element_by_class_name(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "link_text": element = self.driver.find_element_by_link_text(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "xpath": element = self.driver.find_element_by_xpath(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "css": element = self.driver.find_element_by_css_selector(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) # if self.driver: # try: # style_red = 'arguments[0].style.border="2px solid #FF0000"' # style_green = 'arguments[0].style.border="2px solid #00FF00"' # style_null = 'arguments[0].style.border=""' # # for _ in range(2): # self.driver.execute_script(style_red, element) # time.sleep(0.1) # self.driver.execute_script(style_green, element) # time.sleep(0.1) # self.driver.execute_script(style_green, element) # time.sleep(0.2) # self.driver.execute_script(style_null, element) # except WebDriverException: # pass return element except FunctionTimedOut: element = [] else: NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") def get_elements(self, style, delay=DelayTime, describe=''): """ :param style: 元素定位 :param delay: :param describe: 描述用例执行,主要用于日志调试记录,非必填 :return: """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] for i in range(5): if by == "id": element = self.driver.find_elements_by_id(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "name": element = self.driver.find_elements_by_name(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "class": element = self.driver.find_elements_by_class_name(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "link_text": element = self.driver.find_elements_by_link_text(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "xpath": element = self.driver.find_elements_by_xpath(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) elif by == "css": element = self.driver.find_elements_by_css_selector(value) logger.info('get element: ' + str(value) + '>>' + str(describe)) time.sleep(delay) return element else: NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") # ---------------------------------------------------- def click_elem(self, style, describe=''): """ :param style: 元素定位 :param describe: 描述用例执行,主要用于日志调试记录,非必填 :return: """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: value = style.split("&&")[1] element = self.get_element(style).click() logger.info('click element: ' + str(value) + '>>' + str(describe)) return element # ---------------------------------------------------- def get_elem_send_keys(self, style, send_key, describe=None): """ :param style:元素定位 :param send_key: :param describe: 描述用例执行,主要用于日志调试记录,非必填 :return: """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: element = self.get_element(style).send_keys(send_key) logger.info('input keys: ' + str(send_key) + '>>' + str(describe)) return element # ---------------------------------------------------- def show_wait_visibility(self, style, timeout=20, delay=DelayTime): """ show_wait_visibility:显示等待函数(该方法需要找到元素,并且该元素也可见) 提供6种显示等待方法,开发者随使用情况调用 style必须为 XX&&XX的格式,以字符串形式传参 && 前面是定位的方式,后面是定位的元素。例如:id&&#kk timeout:显示等待超时时间 delay:延迟时间 # presence_of_element_located: 当我们不关心元素是否可见,只关心元素是否存在在页面中。 # visibility_of_element_located: 当我们需要找到元素,并且该元素也可见。 :return: """ # 显示等待方法导入 if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "id": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.ID, value))) time.sleep(delay) return expected elif by == "name": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.NAME, value))) time.sleep(delay) return expected elif by == "class": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.CLASS_NAME, value))) time.sleep(delay) return expected elif by == "link_text": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.LINK_TEXT, value))) time.sleep(delay) return expected elif by == "xpath": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.XPATH, value))) time.sleep(delay) return expected elif by == "css": expected = WebDriverWait(self.driver, timeout, 1).until( EC.visibility_of_element_located((By.CSS_SELECTOR, value))) time.sleep(delay) return expected else: raise NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") # ---------------------------------------------------- def show_wait_v_until_not(self, style, timeout=20, delay=DelayTime): if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "id": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.ID, value))) time.sleep(delay) return expected elif by == "name": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.NAME, value))) time.sleep(delay) return expected elif by == "class": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.CLASS_NAME, value))) time.sleep(delay) return expected elif by == "link_text": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.LINK_TEXT, value))) time.sleep(delay) return expected elif by == "xpath": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.XPATH, value))) time.sleep(delay) return expected elif by == "css": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.visibility_of_element_located((By.CSS_SELECTOR, value))) time.sleep(delay) return expected else: raise NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") # ---------------------------------------------------- def show_wait_presence(self, style, timeout=20, delay=DelayTime): """ show_wait_presence:显示等待函数(该方法不关心元素是否可见,只关心元素是否存在在页面中) 提供6种显示等待方法,开发者随使用情况调用 style必须为 XX&&XX的格式,以字符串形式传参 && 前面是定位的方式,后面是定位的元素。例如:id&&#kk timeout:显示等待超时时间 delay:延迟时间 # presence_of_element_located: 当我们不关心元素是否可见,只关心元素是否存在在页面中。 # visibility_of_element_located: 当我们需要找到元素,并且该元素也可见。 :return: """ # 显示等待方法导入 if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "id": expected = WebDriverWait(self.driver, timeout, 1).until(EC.presence_of_element_located((By.ID, value))) time.sleep(delay) return expected elif by == "name": expected = WebDriverWait(self.driver, timeout, 1).until( EC.presence_of_element_located((By.NAME, value))) time.sleep(delay) return expected elif by == "class": expected = WebDriverWait(self.driver, timeout, 1).until( EC.presence_of_element_located((By.CLASS_NAME, value))) time.sleep(delay) return expected elif by == "link_text": expected = WebDriverWait(self.driver, timeout, 1).until( EC.presence_of_element_located((By.LINK_TEXT, value))) time.sleep(delay) return expected elif by == "xpath": expected = WebDriverWait(self.driver, timeout, 1).until( EC.presence_of_element_located((By.XPATH, value))) time.sleep(delay) return expected elif by == "css": expected = WebDriverWait(self.driver, timeout, 1).until( EC.presence_of_element_located((By.CSS_SELECTOR, value))) time.sleep(delay) return expected else: raise NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") # ---------------------------------------------------- def show_wait_p_until_not(self, style, timeout=20, delay=DelayTime): if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "id": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.ID, value))) time.sleep(delay) return expected elif by == "name": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.NAME, value))) time.sleep(delay) return expected elif by == "class": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.CLASS_NAME, value))) time.sleep(delay) return expected elif by == "link_text": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.LINK_TEXT, value))) time.sleep(delay) return expected elif by == "xpath": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.XPATH, value))) time.sleep(delay) return expected elif by == "css": expected = WebDriverWait(self.driver, timeout, 1).until_not( EC.presence_of_element_located((By.CSS_SELECTOR, value))) time.sleep(delay) return expected else: raise NameError( "请输入正确的定位元素:'id','name','class','link_text','xpath','css'") @staticmethod def get_datetime_str(): """获取日期字符串""" datetime_str = datetime.now().strftime('%Y%m%d%H%M%S%f') return datetime_str @classmethod def create_folder(cls, folder_path, folder): """新建文件夹并返回文件路径""" work_file = os.path.join(folder_path, folder) if not os.path.exists(work_file): os.mkdir(work_file) return work_file """ 文件操作 """ @classmethod def clear_files(cls, path): """清除文件夹中的数据""" for root, dirs, files in os.walk(path): for f in files: os.unlink(os.path.join(root, f)) for d in dirs: shutil.rmtree(os.path.join(root, d))
# -*- coding: utf-8 -*-## file: web_page# Author: ShunZhe# Date: 2021/1/20import osimport platformimport timeimport pyautoguiimport pyperclipfrom airtest import aircvfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.keys import Keysfrom common import loggerfrom lib.base_page import BasePagefrom lib.ocv.cv import Templatefrom lib.ocv.error import TargetNotFoundErrorfrom lib.ocv.settings import Settingsfrom lib.path import PathDelayTime = 1pyautogui.PAUSE = 1 # 调用在动作执行后暂停的秒数pyautogui.FAILSAFE = True # 启动自动防故障功能,将鼠标移动到左上坐标(0,0),抛出failSafeException异常class Webpage(BasePage): """ web端页面基类,提供web端定位元素的api和各种操作元素的api,包括图像识别的方法 """ def get(self, url): """ 打开连接 """ self.driver.get(url) logger.info("open url: " + url) def switch_to_iframe(self, frame_id): """切换进入iframe页面""" logger.info('switch to the iframe') self.driver.switch_to_frame(frame_id) def switch_to_default_content(self): """从iframe切回主界面""" self.driver.switch_to_default_content() logger.info("switch to default content") def get_current_url(self): """ 获取当前窗口url地址 """ return self.driver.current_url def get_elem_text(self, style): """ 获取文本 :param style: :return: """ return self.get_element(style).text def get_elem_attribute(self, style, val): """ 获取某个元素值 :param style: :param val: 获取的属性 :return: """ return self.get_element(style).get_attribute(val) @classmethod def upload(cls, file): """ 上传文件,兼容mac和windows系统 :param file:上传文件路径 :return: """ if platform.system() == "Darwin": # mac系统 x_dim, y_dim = pyautogui.size() pyautogui.click(x_dim // 2, y_dim // 2, duration=0.5) pyautogui.click(x_dim // 2 + 50, y_dim // 2 + 50, duration=0.5) time.sleep(3) pyautogui.hotkey('command', 'shift', 'g') time.sleep(2) pyperclip.copy('/') pyautogui.hotkey('command', 'v') time.sleep(1) pyautogui.hotkey('command', 'a') pyautogui.hotkey('command', 'delete') time.sleep(1) pyperclip.copy(file) pyautogui.hotkey('command', 'v') elif platform.system() == "Windows": # windows系统 time.sleep(3) pyperclip.copy(file) pyautogui.hotkey('ctrl', 'v') time.sleep(1) pyautogui.press('enter', presses=2) time.sleep(2) def switch_to_last_window(self): """ 切换到当前浏览器最新打开的窗口 """ all_h = self.driver.window_handles return self.driver.switch_to.window(all_h[-1]) def switch_to_first_window(self): """ 切换到当前浏览器首次打开的窗口 """ all_h = self.driver.window_handles return self.driver.switch_to.window(all_h[0]) def get_elements_counts(self, style): """ 获取一组元素并返回元素个数 """ sum_counts = self.get_elements(style, describe="获取一组元素") logger.info('获取一组元素个数:' + str(len(sum_counts))) return len(sum_counts) def select_all(self, style): """ 模拟全选ctrl+a """ if platform.system().lower() == "darwin": self.get_element(style).send_keys(Keys.COMMAND, "a") else: self.get_element(style).send_keys(Keys.CONTROL, "a") logger.info("select_all:" + str(style.split("&&")[1])) def keyboard_cut(self, style): """ 模拟剪切ctrl+x """ if platform.system().lower() == "darwin": self.get_element(style).send_keys(Keys.COMMAND, "x") else: self.get_element(style).send_keys(Keys.CONTROL, "x") logger.info("keyboard_cut:" + str(style.split("&&")[1])) def keyboard_copy(self, style): """ 模拟复制ctrl+c """ if platform.system().lower() == "darwin": self.get_element(style).send_keys(Keys.COMMAND, "c") else: self.get_element(style).send_keys(Keys.CONTROL, "c") logger.info("keyboard_copy:" + str(style.split("&&")[1])) def keyboard_paste(self, style): """ 模拟粘贴ctrl+v """ if platform.system().lower() == "darwin": self.get_element(style).send_keys(Keys.COMMAND, "v") else: self.get_element(style).send_keys(Keys.CONTROL, "v") logger.info("keyboard_paste:" + str(style.split("&&")[1])) def keyboard_delete(self, style): """ 模拟delete键 """ self.get_element(style).send_keys(Keys.DELETE) logger.info("keyboard_delete:" + str(style.split("&&")[1])) def keyboard_enter(self, style): """ 模拟回车键 """ self.get_element(style).send_keys(Keys.ENTER) logger.info("keyboard_enter:" + str(style.split("&&")[1])) """ 鼠标操作 """ def move_to_element(self, style): """ Moving the mouse to the middle of an element """ ActionChains(self.driver).move_to_element(self.get_element(style)).perform() logger.info("focus element:" + str(style.split("&&")[1])) def right_click(self, style): """右键""" ActionChains(self.driver).context_click(self.get_element(style)).perform() logger.info("right click element:" + str(style.split("&&")[1])) def move_by_offset(self, x=0, y=0): """按住鼠标移动""" e = ActionChains(self.driver).move_by_offset(x, y) logger.info("click_and_hold to the coordinate is ({}, {})".format(x, y)) return e def click_and_hold(self, style): """按住鼠标""" res = ActionChains(self.driver).click_and_hold(on_element=self.get_element(style)) logger.info("click and hold the mouse") return res def click_after_focus(self, focus_style, style): """ hover元素并点击操作 :param focus_style: hover的元素 :param style: 点击的元素 :return: """ focus_elem = self.get_element(focus_style) click_elem = self.get_element(style) ActionChains(self.driver).move_to_element(focus_elem).click(click_elem).perform() def scroll_down(self, style, amount_to_scroll=-200): """ 向下滚动指定格数 style:元素定位 amount_to_scroll:滚动格数 eg: scroll_down(style, -10) # 向下滚动10格 """ self.move_to_element(style) time.sleep(2) if abs(amount_to_scroll) > 200: for i in range(abs(amount_to_scroll) // 200): time.sleep(2) pyautogui.scroll(-200) def scroll_up(self, style, amount_to_scroll=200): """ 向上滚动指定格数 style:元素定位 amount_to_scroll:滚动格数 eg: scroll_down(style, 10) # 向上滚动10格 """ self.move_to_element(style) time.sleep(2) if amount_to_scroll > 200: for i in range(int(amount_to_scroll) // 200): time.sleep(2) pyautogui.scroll(200) """ js操作浏览器 """ def js_click(self, style, delay=DelayTime, index=0, describe=''): """ :param style: 元素定位 :param delay: :param index: 获取定位元素项数,默认为0,第一项 :param describe: 描述用例执行,主要用于日志调试记录,非必填 :return: """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "css": js = """document.querySelectorAll('{css}')[{index}].click();""".format(css=value, index=index) self.driver.execute_script(js) time.sleep(delay) logger.info("click element by js:" + value + '>>' + describe) def js_get_attribute(self, style, attribute, index=0, describe=''): """ 获取指定元素属性 :param attribute: 被获取元素 :param style: 元素定位 :param index: 获取定位元素项数,默认为0,第一项 :param describe: 描述用例执行,主要用于日志调试记录,非必填 """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "css": time.sleep(2) js = """return document.querySelectorAll('{css}')[{index}].getAttribute('{attr}');""". \ format(css=value, index=index, attr=attribute) return self.driver.execute_script(js) logger.info("get_attribute by js:" + value + '>>' + describe) def js_update_inner_text(self, style, text, index=0, describe=''): """ 修改文本框 :param text: :param style: :param index: 获取定位元素项数,默认为0,第一项 :param describe: 描述用例执行,主要用于日志调试记录,非必填 """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "css": js = """var elm = document.querySelectorAll('{css}')[{index}]; elm.innerText='{text}';""".format(css=value, index=index, text=text) self.driver.execute_script(js) logger.info("update text by js:" + value + '>>' + describe) def js_get_text_content(self, style, index=0, describe=''): """ 获取文本 :param style: :param index: 获取定位元素项数,默认为0,第一项 :param describe: 描述用例执行,主要用于日志调试记录,非必填 """ if "&&" not in style: raise NameError("语法错误,style缺少'&&'") else: by = style.split("&&")[0] value = style.split("&&")[1] if by == "css": time.sleep(2) js = """return document.querySelectorAll('{css}')[{index}].textContent;""".format(css=value, index=index) return self.driver.execute_script(js) logger.info("get textContent by js:" + value + '>>' + describe) def clear_local_storage(self): """清除浏览器localStorage""" js = """window.localStorage.clear();""" self.driver.execute_script(js) logger.info("clear localStorage successful~") def add_cookies_and_refresh(self, cookies): """添加浏览器cookies""" self.driver.delete_all_cookies() self.driver.add_cookie(cookies) self.driver.refresh() time.sleep(2) logger.info("add cookies successful and refresh the browser") @staticmethod def get_screen_size(): """ 获取当前屏幕分辨率 """ screen_size = pyautogui.size() return screen_size def full_screenshot(self): """ 全屏幕截图 """ screenshot_path = os.path.abspath(Path().SCREENSHOT_PATH) if not os.path.exists(screenshot_path): os.mkdir(screenshot_path) time_str = self.get_datetime_str() file_path = f'{screenshot_path}/{time_str}.png' pyautogui.screenshot(file_path) return file_path def get_cv_obj(self): """根据图片路径,将图片处理为cv2的图片处理格式""" file_path = self.full_screenshot() cv_obj = aircv.imread(file_path) return cv_obj def _try_log_screen(self, screen=None): """ 记录图像识别的屏幕截图 Args: screen: screenshot to be saved Returns: None """ # 没有默认配置,则使用临时目录存放识别的图片 if not Settings.SS_DIR: Settings.SS_DIR = Path().TMP_IMG_PATH if screen is None: screen = self.get_cv_obj() datetime_str = self.get_datetime_str() filename = f"{datetime_str}.jpg" filepath = os.path.join(Settings.SS_DIR, filename) aircv.imwrite(filepath, screen) def get_template(self, filename, threshold=None, record_pos=None, resolution=(), rgb=False): """picture as touch/swipe/wait/exists target and extra info for cv match""" if not resolution: resolution = self.get_screen_size() if not os.path.exists(filename): filename = os.path.join(Settings.IMG_DIR_PATH, filename) logger.info(f"查找图片: {filename}") template = Template(filename, threshold=threshold, record_pos=record_pos, resolution=resolution, rgb=rgb) return template def loop_find(self, filename, timeout=Settings.FIND_TIMEOUT, threshold=None, interval=0.5, intervalfunc=None): """ 在当前屏幕查找预期图片,直到超时 Args: filename: mage name or image file path timeout: time interval how long to look for the image template threshold: default is None interval: sleep interval before next attempt to find the image template intervalfunc: function that is executed after unsuccessful attempt to find the image template Raises: TargetNotFoundError: when image template is not found in screenshot Returns: TargetNotFoundError if image template not found, otherwise returns the position where the image template has been found in screenshot """ query = self.get_template(filename, threshold=threshold) start_time = time.time() while True: screen = self.get_cv_obj() query.resolution = self.get_resolution(screen) if screen is None: logger.warn("Screen is None, may be locked") else: if threshold: query.threshold = threshold match_pos = query.match_in(screen) if match_pos: self._try_log_screen(screen) return match_pos if intervalfunc is not None: intervalfunc() # 超时则raise,未超时则进行下次循环: if (time.time() - start_time) > timeout: self._try_log_screen(screen) raise TargetNotFoundError('Picture %s not found in screen' % query) else: time.sleep(interval) @staticmethod def get_resolution(img): h, w = img.shape[:2] return w, h @staticmethod def click_mouse_coordinate(*pos): """点击鼠标坐标""" # 关闭安全特性 pyautogui.FAILSAFE = False pyautogui.moveTo(*pos) # 鼠标双击 pyautogui.doubleClick() def touch(self, filename, threshold=Settings.THRESHOLD, times=1, timeout=Settings.FIND_TIMEOUT, **kwargs): """ 点击识别到的图片位置 :param threshold: 识别图片的匹配度,默认0.8 :param filename: 识别图片的文件名或文件路径,直接传文件名,会拼接上ocv/settings文件配置的IMG_DIR_PATH路径 :param times: how many touches to be performed :param timeout: 查找图片最多等待时间 :param kwargs: platform specific `kwargs`, please refer to corresponding docs :return: finial position to be clicked :platforms: Android, iOS 用法: 页面类继承MobilePage self.touch('img_name.png', threshold=0.8) """ _pos = self.loop_find(filename, timeout=timeout, threshold=threshold) logger.info(f'{filename},获取到的图像坐标位置:{_pos}') for _ in range(times): if platform.system() == 'Darwin': pos = (_pos[0] / 2, _pos[1] / 2) self.click_mouse_coordinate(pos) else: self.click_mouse_coordinate(_pos) time.sleep(1) return _pos def screenshots_and_return_Coordinates(self, folder, filename, _x, _y, width, height, threshold=Settings.THRESHOLD, timeout=Settings.FIND_TIMEOUT): """截图并返回截图坐标""" folder_file = self.create_folder(Path().PLAYER_PATH, folder) time.sleep(4) pyautogui.moveTo(_x, _y, duration=0.1) if platform.system() == "Darwin": image = pyautogui.screenshot(region=(_x * 2, _y * 2, width * 2, height * 2)) image.save(os.path.join(folder_file, filename)) else: image = pyautogui.screenshot(region=(_x, _y, width, height)) image.save(os.path.join(folder_file, filename)) logger.info("Picture {} saved successfully!传入参数x坐标{},y坐标{},宽{},高{}".format(filename, _x, _y, width, height)) start_time = time.time() if time.time() - start_time > timeout: raise TargetNotFoundError("Picture is not Found!") else: logger.info(" The image {} has been identified".format(filename)) _pos = pyautogui.locateCenterOnScreen(os.path.join(folder_file, filename), confidence=threshold) if platform.system() == 'Darwin': _pos = (_pos[0] / 2, _pos[1] / 2) else: _pos = _pos logger.info("图片坐标:{}".format(_pos)) return _pos def is_img_exists(self, filename, threshold=Settings.THRESHOLD_STRICT, timeout=Settings.FIND_TIMEOUT, msg=""): """ 验证预期图片是否存在当前屏幕 :param threshold: 识别图片的匹配度,默认0.8 :param filename: 识别图片的文件名或文件路径,直接传文件名,会拼接上ocv/settings文件配置的IMG_DIR_PATH路径 :param timeout: 查找图片最多等待时间 :param msg: short description of assertion, it will be recorded in the report :raise AssertionError: if assertion fails :return: coordinates of the target """ try: pos = self.loop_find(filename, timeout=timeout, threshold=threshold) logger.info(f'{filename}获取到的图像坐标位置:{pos}') return True except TargetNotFoundError: logger.error(f"没有匹配到图像:{filename}, 匹配度设置:{threshold} message: {msg}") return False def is_element_exists(self, style): """检查元素是否存在""" try: self.get_element(style) logger.info(style.split("&&")[1] + " element exists") return True except: logger.info(style.split("&&")[1] + " element does not exist") return False