放出这个类,用法见测试用例。
1、基于selenium的二次封装,整体代码非常短易于理解,带有两个自定义方法示例供参考,易于扩展。 2、支持无限实例化此类,仍然保持使用同一个浏览器窗口。 3、支持使用自定义的方法名字,同时全所未有的支持了直接性的使用所有此类中没有定义的方法,但在官方类中有的api方法,比如直接支持DriverWrapper().execute_script(script, *args)这种写法。 4、其余想自定义名称的方法可以在这个类下面接着写或者继承这个类再添加其他更多方法
5、支持了一个控制台日志,精确 到文件的名字 类名 是在哪一行打印的日志。
经过测试,支持python2和3,支持chrom和firefox,需要安装selenium包和浏览器驱动放到有环境变量的文件夹下。然后就能运行了。
# coding:utf-8import loggingimport unittestfrom selenium import webdriverclass 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 valueclass 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.open(‘https://www.sina.com‘)
???????driver_wrapper.logger.info(‘运行完了,现在想关闭浏览器‘) ???????driver_wrapper2.driver.close() ?# 这样做也可以,但不算是动态添加属性了,这是直接使用的该实例的driver属性的方法,driver属性是Chrome的一个实例。if __name__ == ‘__main__‘: ???unittest.main()
史上最强大的selenium webdriver的封装
原文地址:https://www.cnblogs.com/ydf0509/p/9221969.html