# -*- coding: utf-8 -*-#
# file: BasePage
# Author: ShunZhe
# Date: 2021/1/9
import os
import shutil
import time
from datetime import datetime
from func_timeout.exceptions import FunctionTimedOut
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from common import logger
DelayTime = 1
class 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/20
import os
import platform
import time
import pyautogui
import pyperclip
from airtest import aircv
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from common import logger
from lib.base_page import BasePage
from lib.ocv.cv import Template
from lib.ocv.error import TargetNotFoundError
from lib.ocv.settings import Settings
from lib.path import Path
DelayTime = 1
pyautogui.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