1、之前已经发过两次使用单浏览器了,但是这个最完美,此篇并没有使用任何单例模式的设计模式,用了实例属性结果缓存到类属性。

2、最简单的控制单浏览器是只实例化一次类,然后一直使用这个对象,但每个地方运行前必须确保先调用实例化的那段代码,这在多个测试方法之间没有依赖关系时候,并不需要指定先在什么地方实例化。使用一些方法控制,这可以在任何地方实例化无数次都没问题,比判断全局变量为空则实例化弹出浏览器这种方法好用很多。因为此种方法高度封装后,不会在其他类外地方要写代码控制了,在任何地方实例化浏览器都是一样的写法,具有高度的统一性。此类并不是用了单例模式,就算用不用此类,控制一个浏览器不是需要使用什么单例模式,只需要控制driver属性在任何实例中是同一个对象就可以了。

3、如果要使用单例模式来保证那个slenium使之只有一个浏览器,则要小心一个地方,常规型的python3中重写__new__,只能保证每个实例是指向同一个对象,并不能保证只调用__init__一次,需要处理下, 参考

python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。

放出这个类,用法见测试用例。

 1、基于selenium的二次包装,整体代码非常短易于理解,带有两个自定义方法示例供参考,易于扩展。
2、支持无限实例化此类,只要曾经弹出了浏览器,在任何跨函数 跨类 跨python文件中再次实例化此类,绝对不会弹第二个浏览器。所有地方无论怎么写,仍然保持使用同一个浏览器窗口。(当然指的是单次运行python文件,如果自己反复的关闭和启动python,那肯定是不能使用已打开的浏览器的)
3、支持使用自定义的方法名字,同时全所未有的支持了直接性的使用所有此类中没有定义的方法,但在官方类中有的api方法,比如直接支持DriverWrapper().execute_script(script, *args)这种写法。
4、其余想自定义名称的方法可以在这个类下面接着写或者继承这个类再添加其他更多方法
5、支持了一个控制台日志,精确 到文件的名字 类名 是在哪一行打印的日志。 经过测试,支持python2和3,支持chrom和firefox,需要安装selenium包和浏览器驱动放到有环境变量的文件夹下。然后就能运行了。
# coding:utf-8

import logging
import unittest
from selenium import webdriver class cached_class_property(object):
def __init__(self, func):
self.func = func def __get__(self, obj, cls):
if obj is None:
return self
value = self.func(obj)
setattr(cls, self.func.__name__, value)
return value class DriverWrapper():
"""
1、基于selenium的二次封装,
2、支持无限实例化此类,仍然保持使用同一个浏览器窗口。
3、支持使用自定义的方法名字,同时直接性的支持使用所有此类中没有定义的方法,但在官方类中有的api方法,比如直接支持DriverWrapper().execute_script(script, *args)这种写法。
4、其余想自定义名称的方法可以在这个类下面接着写或者继承这个类再添加其他更多方法
""" def __init__(self, driver_name):
"""
:param driver_name: 浏览器名字数字或者字母
"""
self.driver_name = driver_name @cached_class_property
def driver(self):
driver_var = None
if self.driver_name in ['chrome', 1]:
driver_var = webdriver.Chrome()
if self.driver_name in ['firefox', 2]:
driver_var = webdriver.Chrome()
return driver_var @cached_class_property
def logger(self):
logger_var = logging.getLogger(self.__class__.__name__)
logger_var.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(filename)s - %(lineno)d - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S"))
logger_var.addHandler(stream_handler)
return logger_var def open(self, url):
self.driver.get(url) def find_element_by_css_selector(self, css_str): # 使用自定义的方法覆盖了原方法,比如先打印出一段话
self.logger.debug('要查找的元素的css选择器是 --> ' + css_str)
self.driver.find_element_by_css_selector(css_str) def __getattr__(self, item): # 想把其他的webdriver的操作方法直接添加进来,不一个一个的再写一个方法然后调用driver属性的方法,不想一直搞冗余的代码,可以这么做。python先使用__getattribute__,查不到才会调用__getsttr__方法,利用这个特性,来实现这个添加driver的属性到自己类里面
return getattr(self.driver, item) class _Test(unittest.TestCase):
def test(self):
driver_wrapper = DriverWrapper(1)
driver_wrapper.open('https://www.baidu.com') # 有人不喜欢用get,可以叫open什么的
driver_wrapper.find_element_by_css_selector('#kw') # 当类中存在方法,优先使用了自己类里面的方法,所以每次使用css选择器查找元素时候会打印一个日志
driver_wrapper.find_element_by_id('kw') # 当类中不存在此方法,使用Chrome类的方法 driver_wrapper2 = DriverWrapper(1) # 重新实例化一次这个类,仍然可以接着使用之前的浏览器,不会重新弹一个浏览器窗口
driver_wrapper2.get('https://www.sina.com') # 仍然可以使用get方法打开页面
driver_wrapper.logger.info('运行完了,现在想关闭浏览器')
driver_wrapper2.driver.close() # 这样做也可以,但不算是动态添加属性了,这是直接使用的该实例的driver属性的方法,driver属性是Chrome的一个实例。 if __name__ == '__main__':
unittest.main()

史上最强大的python selenium webdriver的包装的更多相关文章

  1. Python+Selenium+webdriver环境搭建(windows)以及相关资源下载链接

    今天记录一下测试小菜鸟alter在测试入门的一点关于python+Selenium+webdriver环境搭建的经历以及资源分享.欢迎交流学习,批评指正. 一.Python的下载与安装 1.pytho ...

  2. Python Selenium Webdriver常用方法总结

    Python Selenium Webdriver常用方法总结 常用方法函数 加载浏览器驱动: webdriver.Firefox() 打开页面:get() 关闭浏览器:quit() 最大化窗口: m ...

  3. python selenium webdriver入门基本操作

    python selenium webdriver入门基本操作 未经作者允许,禁止转载! from selenium import webdriver import time driver=webdr ...

  4. 强烈推荐:Android史上最强大的自定义任务软件Tasker

    强烈推荐:Android史上最强大的自定义任务软件Taskerhttp://bbs.mumayi.com/thread-28387-1-1.html(出处: 木蚂蚁手机乐园) Android上的Tas ...

  5. Python+Selenium WebDriver API:浏览器及元素的常用函数及变量整理总结

    由于网页自动化要操作浏览器以及浏览器页面元素,这里笔者就将浏览器及页面元素常用的函数及变量整理总结一下,以供读者在编写网页自动化测试时查阅. from selenium import webdrive ...

  6. 史上最全!Selenium元素定位的30种方式

    Selenium对网页的控制是基于各种前端元素的,在使用过程中,对于元素的定位是基础,只有准去抓取到对应元素才能进行后续的自动化控制,我在这里将对各种元素定位方式进行总结归纳一下. 这里将统一使用百度 ...

  7. windows操作系统python selenium webdriver安装

    这几天想搞一个爬虫,就来学习一下selenium,在网上遇见各种坑,特写一篇博文分享一下selenium webdriver的安装过程. 一.安装selenium包 pip install selen ...

  8. Python + Selenium WebDriver Api 知识回顾

    一直再用 Selenium WebDriver 但是用的都比较零散,也没有做过总结,今天借此机会,整理一下,方便大家使用时查阅 webDriver  的属性 ['CONTEXT_CHROME', 'C ...

  9. Linux环境下搭建python+selenium+webdriver环境

    1.下载并安装python,一般安装linux系统,自带有python,则python不用安装.要下载可以在官网上下载: 或者使用下面命令安装: sudo apt-get install python ...

随机推荐

  1. netty tcp拆包

    private List<byte[]> getCompletePacket(byte[] bytes, ByteBuf byteBuf) { byte[] clone = bytes.c ...

  2. [开发笔记]-初学WPF之自学笔记

    一:动态加载背景图片 代码: 在窗体加载时,Window_Loaded 方法中: #region 测试动态加载背景图片 /* 1.图片右键 属性: 复制到输出目录:选择“如果较新则复制” 生成操作选择 ...

  3. exec和sp_executesql

    sqlserver中的exec和sp_executesql都能执行动态的sql语句和存储过程,但exec用法较为简单,不能带参数,也没有返回参数. sp_executesql则显得功能更加完善,可以用 ...

  4. w3svc无法启动

    w3svc无法启动 运行命令regedit,打开注册表编辑器,进入:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP]: a) Cha ...

  5. Linux共享库 base64库

    base64网上实现很多,但是如果是对中文进行编码,有的无法编码,有的编码结果不一致 经过研究,发现base64算法都没有问题,问题出现在汉字的编码上,下面的base64编码稍微做了一些改进,增加了编 ...

  6. Qt的一些鲜为人知但是非常有用的小功能

    1. Q_GADGET:不需要从QObject继承就可以使用Qt的Meta Object功能  2. Q_ENUMS:对枚举对象进行反射(reflection)  3. Q_SIGNAL:不需要sig ...

  7. 解决DoubanFM第三方客户端UI线程与工作线程交互问题

    最新文章:Virson's Blog 首先要感谢yk000123的慷慨开源,开源地址见:http://doubanfm.codeplex.com/ 最近正好在学习WPF,然后在Codeplex上找到了 ...

  8. 自然语言交流系统 phxnet团队 创新实训 个人博客 (七)

    使用Lucene 3.0.0的结构遍历TokenStream的内容. 以前版本的Lucene是用TokenStream.next()来遍历TokenStream的内容, 目前的版本稍微修改了一下, 使 ...

  9. Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.【转】

    今天碰到了一个查询异常问题,上网查了一下,感谢原创和译者 如果你使用的数据库连接类是 the Data Access Application Blocks "SqlHelper" ...

  10. Python bytes decode() 方法

    描述 bytes decode() 方法以指定的编码格式解码 bytes 对象,默认编码为 'utf-8'. 对应的编码方法:encode() 方法 . 语法 Python bytes decode( ...