2w元教学课程,免费分享,教你搞定selenium自动化框架封装!

2w元教学课程,免费分享,教你搞定selenium自动化框架封装!

首先,大家在做selenium自动化的时候,通常都是调用官网提供的元素定位方法,直接调用,可能初期做自动化的时候,不会有什么问题,但是随着我们项目功能越来越多,业务也越来越复杂,有些定位功能,需要单独定制,如果是直接调用的话,我们需要修改所有调用元素定位方法的代码,这样我们维护代码需要耗费很多时间,下面我们通过将元素定位单独封装,来解决这个问题,话不多说,直接贴代码。

(注意:这里执行的地方,需要依赖driver驱动,这里我用的是Chrome浏览器,所以安装的是Chromedriver,大家可以直接去下载搭建环境)

log.py

# -*- coding: utf-8 -*-
# @Time    : 2019/2/15 9:23 AM
# @Author  : 余少琪
# @FileName: log.py
# @email   : 1603453211@qq.com
"""
这里封装了打印日志,之后做自动化的过程中,可以调用直接LogHandler方法,
将元素定位的信息打印出来,方便我们查看及定位问题。
"""
import logging
from logging import handlers
import colorlog
from common.setting import DevConfig
class LogHandler(object):
# 日志级别关系映射
level_relations = {

'debug': logging.DEBUG,
'info': logging.INFO,
'warning': logging.WARNING,
'error': logging.ERROR,
'crit': logging.CRITICAL
}
def __init__(self, filename, level='info', when='D', backCount=3, fmt='%(asctime)s - %(filename)s[line:%('
'lineno)d] - %(levelname)s: %(message)s'):
self.logger = logging.getLogger(filename)
self.log_colors_config = {

'DEBUG': 'cyan',
'INFO': 'white',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
}
formatter = colorlog.ColoredFormatter(
'%(log_color)s[%(asctime)s] [%(name)s] [%(levelname)s]: %(message)s',
log_colors=self.log_colors_config)
# 设置日志格式
format_str = logging.Formatter(fmt)
# 设置日志级别
self.logger.setLevel(self.level_relations.get(level))
# 往屏幕上输出
sh = logging.StreamHandler()
# 设置屏幕上显示的格式
sh.setFormatter(formatter)
# 往文件里写入#指定间隔时间自动生成文件的处理器
th = handlers.TimedRotatingFileHandler(filename=filename, when=when, backupCount=backCount, encoding='utf-8')
"""
#实例化TimedRotatingFileHandler
#interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
# S 秒
# M 分
# H 小时、
# D 天、
# W 每星期(interval==0时代表星期一)
# midnight 每天凌晨    
"""
# 设置文件里写入的格式
th.setFormatter(format_str)
# 把对象加到logger里
self.logger.addHandler(sh)
self.logger.addHandler(th)
log_path = DevConfig().log_path
Log = LogHandler(log_path + '/all.log', level='debug')
# get_info_log = LogHandler(log_path + '/info.log', level='info')
# get_error_log = LogHandler(log_path + '/error.log', level='error')
if __name__ == '__main__':
msg = '111'
# log = LogHandler('all.log', level='debug')
Log.logger.debug('debug')
# log.logger.info(msg)
# log.logger.warning('警告')
# log.logger.error('报错')
# log.logger.critical('严重')
# LogHandler('error.log', level='error').logger.error('error')
# is_open = ReadIni(node='log').get_value("run")
# get_info_log.logger.info("111")

依赖库

> pip install PyUserInput 	 	
> pip intsall pyperclip
# -*- coding: utf-8 -*-
# @Time    : 2019/2/15 8:54 AM
# @Author  : 余少琪
# @FileName: basepage.py
# @email   : 1603453211@qq.com
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# DevConfig 是我自己存放项目文件地址的,你们可以结合自己的业务单独创建
from common.setting import DevConfig
import datetime
from Outputs.logs.log import Log
from selenium.webdriver.support.select import Select
from time import time, sleep
from pykeyboard import PyKeyboard
import pyperclip
from pymouse import PyMouse
import os
import platform
class BasePage:
def __init__(self, driver: WebDriver):
self.driver = driver
# 等待元素可见
def wait_ele_visible(self, loc, img_name, timeout=20, poll_fre=0.5):
"""
:param loc: 元素
:param timeout:
:param poll_fre:
:return: 等待元素
"""
start_time = time()
try:
WebDriverWait(self.driver, timeout, poll_frequency=poll_fre).until(EC.visibility_of_element_located(loc))
Log.logger.info("等待{0}元素可见, 用时{1:.2f}秒.".format(loc, time()-start_time))
except:
self.save_page_shots(img_name)
Log.logger.error("等待{0}元素可见失败, 用时{1:.2f}秒.".format(loc, time()-start_time))
raise
def send_pictures(self, loc, img_name, file):
"""
上传图片
:param loc:
:param img_name:
:param file: 图片路径
:return:
"""
start_time = time()
platform_system = platform.system()
if platform_system  == 'Windows':
try:
self.get_element(loc, img_name).send_keys(file)
Log.logger.info("开始上传文件,文件路径{0}, 用时{1:.2f}秒.".format(file, time() - start_time))
except:
self.save_page_shots(img_name)
Log.logger.error("上传图片失败!图片路径{0}".format(file))
raise
elif platform_system == 'Linux' or platform_system == "Darwin":
def _is_China(file):
# 判断文件名称中是否包含中文
for ch in file:
if u'\u4e00' <= ch <= u'\u9fff':
return True
return False
try:
if _is_China(file) is True:
Log.logger.error("文件路径中不允许包含中文字符!请修改文件命名。文件路径:{0}".format(file))
if _is_China(file) is False:
Log.logger.info("开始上传图片, 图片路径:{0}".format(file))
self.click_element(loc, img_name)
k = PyKeyboard()
# k.press_keys(['Command', 'Shift', 'E'])
m = PyMouse()
filepath = '/'
# 模拟键盘点击 Command + Shift + G
k.press_keys(['Command', 'Shift', 'G'])
# 获取当前屏幕尺寸
x_dim, y_dim = m.screen_size()
m.click(x_dim // 2, y_dim // 2, 1)
# 复制文件路径开头的斜杠/
pyperclip.copy(filepath)
# 粘贴斜杠/
k.press_keys(['Command', 'V'])
# 输入文件全路径进去
k.type_string(file)
sleep(2)
k.press_key('Return')
sleep(2)
k.press_key('Return')
sleep(2)
except:
self.save_page_shots(img_name)
Log.logger.error("上传图片失败!图片路径{0}".format(file))
raise
else:
Log.logger.error("{0}操作系统不支持上传文件功能!".format(get_current_system()))
# 精准 link text 定位
def accurate_link_text(self, text, img_name):
start_time = time()
Log.logger.info("开始通过 link text 进行定位, 定位内容:{0},用时{1:.2f}秒.".format(text, time()-start_time))
try:
self.driver.find_element_by_link_text(str(text)).click()
except:
self.save_page_shots(img_name)
Log.logger.error("精准 link text 定位失败!,用时{0:.2f}秒.".format(time()-start_time))
# 等待元素可点击
def wait_ele_clickable(self, loc, img_name, timeout=20, poll_fre=0.5):
"""
:param loc: 元素
:param timeout:
:param poll_fre:
:return: 等待元素
"""
start_time = time()
Log.logger.info("{0} 等待 {1} 元素可点击, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))
try:
WebDriverWait(self.driver, timeout, poll_frequency=poll_fre).until(EC.element_to_be_clickable(loc))
except:
self.save_page_shots(img_name)
Log.logger.error("等待元素可点击失败:{0}, 用时{1:.2f}秒.".format(loc, time()-start_time))
raise
# 元素存在
def wait_page_contain_element(self):
pass
# 查看元素
def get_element(self, loc, img_name):
start_time = time()
Log.logger.info("在 {0} 查找元素:{1}, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))
try:
ele = self.driver.find_element(*loc)
except:
self.save_page_shots(img_name)
Log.logger.error("查找元素{0}失败!用时{1:.2f}秒.".format(loc, time()-start_time))
raise
else:
return ele
# 查找所有元素
def get_elements(self, loc, img_name):
start_time = time()
Log.logger.info("在 {0} 查找元素:{1}, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))
try:
ele = self.driver.find_elements(*loc)
except:
self.save_page_shots(img_name)
Log.logger.error("查找元素{0}失败!用时{1:.2f}秒.".format(loc, time()-start_time))
raise
else:
return ele
# 点击元素
def click_element(self, loc, img_name, timeout=20, poll_fre=0.5):
start_time = time()
self.wait_ele_visible(loc, img_name, timeout, poll_fre)
ele = self.get_element(loc, img_name)
Log.logger.info("对 {0} 点击元素:{1},用时{2:.2f}秒. ".format(img_name, loc, time()-start_time))
try:
ele.click()
except:
self.save_page_shots(img_name)
Log.logger.error("点击元素失败, 元素内容:{0}".format(loc))
raise
# 元素的输入属性
def input_text(self, loc, value, img_name, timeout=20, poll_fre=0.5):
start_time = time()
self.wait_ele_visible(loc, img_name, timeout, poll_fre)
ele = self.get_element(loc, img_name)
Log.logger.info("对 {0} 将元素 {1} 输入文本值:{2}, 用时{3:.2f}秒.".format(img_name, loc, value, time()-start_time))
try:
ele.send_keys(value)
except:
self.save_page_shots(img_name)
Log.logger.error("元素输入文本失败!内容: {0}, 用时{1:.2f}秒. ".format(value, time()-start_time))
raise
# 获取元素属性
def get_ele_attribute(self, loc, attr_name, img_name,  timeout=20, poll_fre=0.5):
start_time = time()
self.wait_ele_visible(loc, img_name, timeout, poll_fre)
ele = self.get_element(loc, img_name)
Log.logger.info("在 {0} 获取元素 {1} 的 {2} 属性, 用时{3:.2f}秒".format(img_name, loc, attr_name, time()-start_time))
try:
value = ele.get_attribute(attr_name)
except:
self.save_page_shots(img_name)
Log.logger.error("获取元素属性{0}失败!用时{1:.2f}秒".format(loc, time()-start_time))
else:
Log.logger.info("属性值为:{}".format(value))
return value
# 获取属性的文本内容
def get_ele_text(self, loc, img_name,  timeout=20, poll_fre=0.5):
start_time = time()
self.wait_ele_visible(loc, img_name, timeout, poll_fre)
ele = self.get_element(loc, img_name)
Log.logger.info("在 {0} 获取元素 {1} 的文本值, 用时{2:.2f}秒 ".format(img_name, loc, time()-start_time))
try:
text = ele.text
except:
self.save_page_shots(img_name)
Log.logger.error("获取元素文本值失败!文本值内容:{0}, 用时{1:.2f}秒".format(loc, time()-start_time))
else:
Log.logger.info("属性值为:{0}, 用时{1:.2f}秒".format(text, time()-start_time))
return text
# 截图
def save_page_shots(self, img_name):
# 将图片存储在 OutPuts 的 screenshot 的文件中,唯一不同的是图片的命名
file_name = "{}_{}.png".format(img_name, datetime.datetime.now())
# 判断文件如果不存在,则创建存放一个文件夹
# DevConfig.screenshots_path是我自己创建的文件夹路径,你们可以自己创建一个
if not os.path.exists(DevConfig.screenshots_path):
os.mkdir(DevConfig.screenshots_path)
self.driver.save_screenshot(DevConfig.screenshots_path + "/" + file_name)
Log.logger.info("页面图片保存在:{}".format(DevConfig.screenshots_path + "/" + file_name))
# 切换至iframe页面
def switch_to_ifaram(self, loc, img_name):
Log.logger.info("切换ifram页面:{}".format(loc))
try:
WebDriverWait(self.driver, 20).until(EC.frame_to_be_available_and_switch_to_it(loc))
except:
self.save_page_shots(img_name)
Log.logger.error("切换至iframe页面失败!")
# 纵向滚动条操作
def vertical_scroll_bar(self, img_name, *postion, type=None):
"""
:param img_name:
:param postion: 滚动条的坐标,为 postion 为 0,则表示滑动到顶部,为 1000 时则表示滑动到底部
横向滑动时,需要同时传 x ,y 轴的坐标
:param type: 纵向 :portrait; 横向 :transverse
:return:
"""
Log.logger.info("开始滑动滚动条,滚动位置为{0}".format(postion))
try:
global js
# 判断滚动类型为纵向
if type == 'portrait' or type is None:
js = 'var action=document.documentElement.scrollTop=' + ",".join(map(str, postion))
# 判断滚动类型为横向
elif type == 'transverse':
js = "window.scrollTo" + str(postion) + ";"
self.driver.execute_script(js)
except:
self.save_page_shots(img_name)
Log.logger.error("滚条条滑动失败!")
# 富文本框输入
def rishtext(self, content, loc, img_name, loc_type="Id"):
"""
:param content: 富文本输入内容
:param loc: 元素名称
:param img_name:
:param loc_type: Id , ClassName, Name,TagName
:return:
"""
try:
Log.logger.info("开始输入富文本内容:{0}".format(content))
js = 'document.getElementBy' + str(loc_type) + "(" + str(
loc) + ")" + 'contentWindow.document.body.innerHTML="%s"' % content
self.driver.execute_script(js)
except:
self.save_page_shots(img_name)
Log.logger.error("富文本框输入失败!")
# 下拉框定位
def drop_down_menu_positioning(self, loc, img_name, type, value):
"""
:param loc:  loc = driver.find_element_by_id("kw")
:param img_name:
:param type: 下拉框定位类型,index 为坐标元素定位,value 为值定位,text则为文字定位
:param value:
:return:
"""
Log.logger.info("开始进行下拉框定位,定位类型:{0}, 定位内容:{1}".format(type, value))
try:
select = Select(loc)
if type == "index":
select.select_by_index(value)
elif type == 'value':
select.select_by_value(value)
elif type == 'text':
select.select_by_visible_text(value)
except:
self.save_page_shots(img_name)
Log.logger.error("下拉框定位失败!")
if __name__ == '__main__':
pass

元素定位我们已经封装好了,那么我们来看看具体的运行情况,下面我们以打开百度地址为例,然后在百度输入框中,输入“selenium”进行查询

    from  selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
# 打开百度地址
driver.get("http://www.baidu.com")
# 实例化BasePage,然后传入driver对象
basepage = BasePage(driver)`在这里插入代码片`
# 因为是输入内容,所以我们这里调用封装好的input_text()方法进行调用
basepage.input_text((By.NAME, "wd"), 'selenium', '再输入框中输入内容')
basepage.click_element((By.ID, 'su'), '点击搜索')

可以看到我们已经搜索成功了,下面我们再来看看日志的情况
在这里插入图片描述
查看日志信息
在这里插入图片描述
以上这些就是元素定位封装的方法,basepage中我只封装了一些常用的定位方法,selenium中元素定位的方式有很多,如果还有其他需要的,可以自己单独在进行封装。关于元素封装我也是基于自己对于自动化的学习和理解整理出来的,如果大家有什么更好的方式,欢迎随时讨论~

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100660.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • springboot转发和重定向_nginx重定向和转发的区别

    springboot转发和重定向_nginx重定向和转发的区别重定向就是浏览器重新发送新的请求,请求域改变,浏览器上的地址栏有变动,发送的地址是相对于项目的地址;转发就是服务器在服务器内部进行请求的转发,请求域不变,浏览器上的地址栏不变;一般在处理一个请求后再跳转到另一个处理请求时,进行重定向redirect;当请求不能变时,用forward转发请求。更详细的解释…

  • Python 万能代码模版:爬虫代码篇「建议收藏」

    Python 万能代码模版:爬虫代码篇「建议收藏」你好,我是悦创。很多同学一听到Python或编程语言,可能条件反射就会觉得“很难”。但今天的Python课程是个例外,因为今天讲的**Python技能,不需要你懂计算机原理,也不需要你理解复杂的编程模式。**即使是非开发人员,只要替换链接、文件,就可以轻松完成。并且这些几个实用技巧,简直是Python日常帮手的最佳实践。比如:爬取文档,爬表格,爬学习资料;玩转图表,生成数据可视化;批量命名文件,实现自动化办公;批量搞图,加水印、调尺寸。接下来,我们就逐一用Python实

  • 或非门_与非门转化为或非门

    或非门_与非门转化为或非门 

  • 两款免费、好用的数据库连接工具

    一、NavicateNavicat是一套快速、可靠的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设。它的设计符合数据库管理员、开发人员及中小企业的需要。Navicat是以直觉化的图形用户界面而建的,让你可以以安全并且简单的方式创建、组织、访问并共用信息。1、安装步骤(1)解压navicat_premium12文件,得到安装文件和破解文件。(2)双击navicat12024_premium_cs_x64.exe安装文件,根据点击下一步安装完成,记住安装目录,安装完成后先不

  • 机器学习-支持向量回归

    机器学习-支持向量回归一,介绍支持向量回归(SVR)是期望找到一条线,能让所有的点都尽量逼近这条线,从而对数据做出预测。SVR的基本思路和SVM中是一样的,在ϵ−SVR需要解决如下的优化问题:                                       其回归图形如下:           …

  • 廖雪峰的 Python 教程_python基础教程廖雪pdf

    廖雪峰的 Python 教程_python基础教程廖雪pdfimportmath#一元二次方程defquadratic(a,b,c): n=b/a/2 m=abs(n*n-c/a) x1=math.sqrt(m)-n x2=-math.sqrt(m)-n returnx1,x2#一个或多个数的乘积defproduct(f,*args): result=f; forxinargs: resu…

    2022年10月30日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号