当前位置:   article > 正文

Webdriver常用及基础方法_webdriver用法

webdriver用法

Webdriver常用方法

表达式操作
title()获取title标签,或者使用title属性
get(url)get方式请求url
get_attribute(name)获取属性值
back()浏览器后退
forward()浏览器前进
close()关闭当前页面
refresh()刷新浏览器
quit()关闭浏览器
maximize_window()浏览器最大化
minimize_window()浏览器最小化
click()鼠标左键单击
clear()清除内容
send_keys(key)输入内容
switch_to.window切换页面句柄
switch_to.frame切换iframe
switch_to.alert切换弹窗
实例展示
from selenium import webdriver #导入模块
driver = webdriver.Chrome() #创建一个浏览器实例
driver.get("http://www.baidu.com") #使用get方法访问指定url
driver.maximize_window() # 最大化浏览器
driver.find_element_by_xpath('//input[@id="kw"]').clear() #对定位element进行清除内容操作
driver.find_element_by_xpath('//input[@id="kw"]').send_keys('淘宝网')#对定位element进行输入操作
driver.find_element_by_xpath('//input[@id="su"]').click() #对定位element进行鼠标左键点击操作
driver.quite()#退出浏览器
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Webdriver基础方法

初始化

from selenium import webdriver

class Driver(object):
    def __init__(self,url=None,browser="",options=None,capabilities=None):
        self.driver = None
        self.url = url
        self.browser = browser
        try:
	        if self.browser=="chrome":
	        	self.driver = webdriver.Chrome(options=options,desired_capabilities=capabilities)
	        elif self.browser == 'firefox':
	            self.driver = webdriver.Firefox()
	        elif self.browser == 'edge':
	            self.driver = webdriver.Edge()
	        else:
	            raise TypeError('未找到指定浏览器及其对应的驱动')
	    except:
	    	raise TypeError('浏览器启动失败')
    	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

1.控制页面元素稳定

from selenium import webdriver

def waitpages(self):
'''
检测页面,页面不变化了,认为页面稳定了
:return: page_source
'''
   begin = int(time.time())
   source = self.driver.page_source
   while True:
       time.sleep(0.3)
       nowsource = self.driver.page_source
       if source == nowsource:
           break
       else:
           now = int(time.time())
           if now - begin > 3:
               break
       source = nowsource
 
def waithtml(self, outtime=3):
'''
方法二
'''
    try:
        WebDriverWait(self.driver, outtime).until(
            lambda driver: driver.execute_script('return document.readyState') == 'complete')
    except exceptions.TimeoutException:
        pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

2.判断元素是否可见

	from selenium import webdriver
	
    def elementisvisable(self,element):
        '''
        判断元素是否可见,在selenium的判断的基础上增加了一些特殊的判断,判断了元素尺寸。
        :param element:页面元素
        :return:element
        '''
        try:
            if not element.is_displayed():
                return False
            size = element.size
            if not int(size['height']) and not int(size['width']):
                return False
            loc = element.location
            if int(loc['x']) < -9000 and int(loc['y']) < -9000:
                return False
            if not element.is_enabled():
                return False
        except:
            return False
        return True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

3.单个元素定位

	from selenium import webdriver
	
    def getelement(self, value=None, by=By.XPATH, outtime=30,check=Ture):
        '''
        返回xpath指向的元素,如果指向多个可见的,只返回第一个,能自动过滤网页中的隐藏元素,并且带超时等待

        :param value: xpath,或者是用其他方式查找元素依赖的参数
        :param by: 默认用xpath的方法去找,也可以根据自己的需求定义
        :param outtime: 一个作用是等待元素出现,第二是配置了超时时间,不能低于2s,有可能会导致元素获取不到
        :param check: 控制是否启用waitpages方法,默认启用
        :return: webelemnet元素
        '''
        if check:
        	self.waitpages()
        # 循环查找可见元素,直到超时,每隔0.3秒查找一次,如果超时报异常
        starttime = int(time.time())
        while True:
            visable_elements = []
            elements = self.driver.find_elements(by=by, value=value)
            for element in elements:
                if self.elementisvisable(element):
                    visable_elements.append(element)
            if visable_elements:
                return visable_elements[0]
            else:
                nowtime = int(time.time())
                if nowtime - starttime >= outtime:
                    raise exceptions.NoSuchElementException('此xpath未找到元素:{}'.format(value))
                else:
                    time.sleep(0.3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

4.多个元素定位

	from selenium import webdriver
	
    def getelements(self,value=None,by=By.XPATH,filter=False,outtime=5,check=True) -> list:
        '''
        返回xpath指向的页面所有元素
        :param value: xpath
        :param by: 默认使用xpath方法
        :param filter: 是否开启过滤,过滤隐藏元素,如果设置为False,不会过滤,只会有selenium的默认等待时间
        :param outtime: 隐士等待时间,默认30s,可以根据自己的需求配置
        :param check: 控制是否启用waitpages方法,默认启用
        :return: 不开启过滤,会返回所有找到的webelement数组
                开启过滤只会返回显示在页面上的webelement数组
        '''
        if check:
        	self.waitpages(check)
        starttime = int(time.time())
        while True:
            visable_elements = []
            elements = self.driver.find_elements(by=by, value=value)
            if filter:
                for element in elements:
                    if self.elementisvisable(element):
                        visable_elements.append(element)
            else:
                visable_elements = elements
            if visable_elements:
                return visable_elements
            else:
                nowtime = int(time.time())
                if nowtime - starttime >= outtime:
                    return visable_elements
                else:
                    time.sleep(0.3)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

5.鼠标左键单击

	from selenium import webdriver
	from selenium.webdriver import ActionChains
	
    def click(self,xpath,outtime=30):#方法一
	    '''
	    调用getelement方法,用click()方法对页面元素进行点击
	    :param xapth: 元素xpath表达式
	    :param outtime: 元素超时等待时间
	    '''
        self.getelement(xpath, outtime=outtime).click()
    
    def click(self,xpath,outtime=30):#方法二
    	'''
    	调用getelement方法,基于ActionChains库,用click()方法对应元素进行点击
    	:param xpath: 元素xpath表达式
    	:param outtime: 元素超时等待时间
    	'''
    	ac = self.getelement(xpath,outtime=outtime)
		ActionChains(driver).move_to_element(ac).click(ac).perform()
	
	def click_offset(self,x,y,ouyttime):#方法三
		'''
		基于ActionChains库,在页面指定坐标处进行点击
		:param x: 目标位置横坐标
		:param y: 目标位置纵坐标
		:param outtime: 元素超时等待时间
		'''
		ActionChains(driver).move_by_offset(x,y).click().perform()  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

6.鼠标左键双击

from selenium import webdriver
from selenium.webdriver import ActionChains

def double_click(self, xpath, outtime=30):
	'''
	调用getelement方法,基于ActionChains库,用double_click()方法对对应元素进行点击
	:param xpath: 元素xpath表达式
   	:param outtime: 元素超时等待时间
	'''
    ActionChains(driver).double_click(self.getelement(xpath, outtime=outtime)).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

7.鼠标悬停

from selenium import webdriver
from selenium.webdriver import ActionChains

def move_to_element(self, xpath, outtime=30):
	'''
	调用getelement方法,基于ActionChains库,用double_click()方法对对应元素进行点击
	:param xpath: 元素xpath表达式
   	:param outtime: 元素超时等待时间
	'''
    ActionChains(driver).move_to_element(self.getelement(xpath, outtime=outtime)).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

8.鼠标右键点击

from selenium import webdriver
from selenium.webdriver import ActionChains

def context_click(self, xpath, outtime=30):
	'''
	调用getelement方法,基于ActionChains库,用context_click()方法对对应元素进行点击
	:param xpath: 元素xpath表达式
   	:param outtime: 元素超时等待时间
	'''
    ActionChains(driver).context_click(self.getelement(xpath, outtime=outtime)).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

9.鼠标拖拽目标至指定位置

from selenium import webdriver
from selenium.webdriver import ActionChains

def drag_and_drop_to_element(self, sr_xpath, tg_xpath, outtime=30):
    '''
    调用getelement方法,基于ActionChains库,拖拽页面元素到目标页面元素
    :param sr_xpath: 定位需要拖拽元素的xpath
    :param tg_xpath: 定位拖拽至目标元素的xpath
    :param outtime: 定位元素超时时间
    '''
    ActionChains(driver).drag_and_drop(
    	self.getelement(sr_xpath, outtime=outtime),
   		self.getelement(tg_xpath, outtime=outtime)).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

10.鼠标拖拽目标至指定位置_增强版

from selenium import webdriver
from selenium.webdriver import ActionChains

class BorderPoints(IntEnum):
    LEFT_TOP = 1  # 左上角
    TOP = 2  # 上边缘中间
    RIGHT_TOP = 3  # 右上角
    LEFT = 4  # 左边缘中间
    CENTER = 5  # 中心
    RIGHT = 6  # 右边缘中间
    LEFT_BOTTOM = 7  # 左下角
    BOTTOM = 8  # 下边缘中间
    RIGHT_BOTTOM = 9  # 右下角
    PART_UP = 10  # 上半部
    PART_DOWN = 11  # 下半部
    PART_LEFT = 12  # 左半部
    PART_RIGHT = 13  # 右半部
    QUARDRANT_A = 14  # 第一象限
    QUARDRANT_B = 15  # 第二象限
    QUARDRANT_C = 16  # 第二象限
    QUARDRANT_D = 17  # 第二象限

def drag_and_drop_to_element(self, sr_xpath, tg_xpath, sr_borderpoint=BorderPoints.CENTER, tg_borderpoint=BorderPoints.CENTER, outtime=30):
    '''
    拖拽页面元素到目标页面元素

    :param sr_xpath: 定位需要拖拽元素的xpath
    :param tg_xpath: 定位拖拽至目标元素的xpath
    :param borderpoint: 元素的边缘、部位、或者中央的位置点。
    :param borderpoint: 元素的边缘、部位、或者中央的位置点。
    :param outtime: 定位元素超时时间
    '''
    sr_element = self.driver.getelement(sr_xpath, outtime=outtime, proxy=proxy)
    sr_size = sr_element.size
    tg_element = self.driver.getelement(tg_xpath, outtime=outtime, proxy=proxy)
    tg_size = tg_element.size
    action = ActionChains(self.driver.driver)
    action.move_to_element(sr_element)
    if sr_borderpoint == 1:
        action.move_by_offset(-sr_size["width"] / 2, -sr_size["height"] / 2)
    elif sr_borderpoint == 2:
        action.move_by_offset(0, -sr_size["height"] / 2)
    elif sr_borderpoint == 3:
        action.move_by_offset(sr_size["width"] / 2, -sr_size["height"] / 2)
    elif sr_borderpoint == 4:
        action.move_by_offset(-sr_size["width"] / 2, 0)
    elif sr_borderpoint == 5:
        pass
    elif sr_borderpoint == 6:
        action.move_by_offset(sr_size["width"] / 2, 0)
    elif sr_borderpoint == 7:
        action.move_by_offset(-sr_size["width"] / 2, sr_size["height"] / 2)
    elif sr_borderpoint == 8:
        action.move_by_offset(0, sr_size["height"] / 2)
    elif sr_borderpoint == 9:
        action.move_by_offset(sr_size["width"] / 2, sr_size["height"] / 2)
    elif sr_borderpoint == 10:
        action.move_by_offset(0, -sr_size["height"] / 4)
    elif sr_borderpoint == 11:
        action.move_by_offset(0, sr_size["height"] / 4)
    elif sr_borderpoint == 12:
        action.move_by_offset(-sr_size["width"] / 4, 0)
    elif sr_borderpoint == 13:
        action.move_by_offset(sr_size["width"] / 4, 0)
    elif sr_borderpoint == 14:
        action.move_by_offset(-sr_size["width"] / 4, -sr_size["height"] / 4)
    elif sr_borderpoint == 15:
        action.move_by_offset(sr_size["width"] / 4, -sr_size["height"] / 4)
    elif sr_borderpoint == 16:
        action.move_by_offset(-sr_size["width"] / 4, sr_size["height"] / 4)
    elif sr_borderpoint == 17:
        action.move_by_offset(sr_size["width"] / 4, sr_size["height"] / 4)
    else:
        raise Exception("参数错误:sr_borderpoint")
    action.click_and_hold()
    action.move_to_element(tg_element)
    if tg_borderpoint == 1:
        action.move_by_offset(-tg_size["width"] / 2, -tg_size["height"] / 2)
    elif tg_borderpoint == 2:
        action.move_by_offset(0, -tg_size["height"] / 2)
    elif tg_borderpoint == 3:
        action.move_by_offset(tg_size["width"] / 2, -tg_size["height"] / 2)
    elif tg_borderpoint == 4:
        action.move_by_offset(-tg_size["width"] / 2, 0)
    elif tg_borderpoint == 5:
        pass
    elif tg_borderpoint == 6:
        action.move_by_offset(tg_size["width"] / 2, 0)
    elif tg_borderpoint == 7:
        action.move_by_offset(-tg_size["width"] / 2, tg_size["height"] / 2)
    elif tg_borderpoint == 8:
        action.move_by_offset(0, tg_size["height"] / 2)
    elif tg_borderpoint == 9:
        action.move_by_offset(tg_size["width"] / 2, tg_size["height"] / 2)
    elif tg_borderpoint == 10:
        action.move_by_offset(0, -tg_size["height"] / 4)
    elif tg_borderpoint == 11:
        action.move_by_offset(0, tg_size["height"] / 4)
    elif tg_borderpoint == 12:
        action.move_by_offset(-tg_size["width"] / 4, 0)
    elif tg_borderpoint == 13:
        action.move_by_offset(tg_size["width"] / 4, 0)
    elif tg_borderpoint == 14:
        action.move_by_offset(-tg_size["width"] / 4, -tg_size["height"] / 4)
    elif tg_borderpoint == 15:
        action.move_by_offset(tg_size["width"] / 4, -tg_size["height"] / 4)
    elif tg_borderpoint == 16:
        action.move_by_offset(-tg_size["width"] / 4, tg_size["height"] / 4)
    elif tg_borderpoint == 17:
        action.move_by_offset(tg_size["width"] / 4, tg_size["height"] / 4)
    else:
        raise Exception("参数错误:tg_borderpoint")
    action.release().perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113

11.鼠标拖拽至指定坐标

from selenium import webdriver
from selenium.webdriver import ActionChains

def drag_and_drop_to_setoff(self,sr_xpath,x,y,outtime=30):
	'''
    调用getelement方法,基于ActionChains库,拖拽页面元素到目标坐标
    :param sr_xpath: 定位需要拖拽元素的xpath
    :param x: 目标横坐标
    :param y: 目标纵坐标
    :param outtime: 定位元素超时时间
    '''
	ac = self.getelement(sr_xpath)
	ActionChains(driver).drag_and_drop_by_offset(ac,x,y).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

12.鼠标拖拽至指定坐标_增强版

from selenium import webdriver
from selenium.webdriver import ActionChains

class BorderPoints(IntEnum):
    LEFT_TOP = 1  # 左上角
    TOP = 2  # 上边缘中间
    RIGHT_TOP = 3  # 右上角
    LEFT = 4  # 左边缘中间
    CENTER = 5  # 中心
    RIGHT = 6  # 右边缘中间
    LEFT_BOTTOM = 7  # 左下角
    BOTTOM = 8  # 下边缘中间
    RIGHT_BOTTOM = 9  # 右下角
    PART_UP = 10  # 上半部
    PART_DOWN = 11  # 下半部
    PART_LEFT = 12  # 左半部
    PART_RIGHT = 13  # 右半部
    QUARDRANT_A = 14  # 第一象限
    QUARDRANT_B = 15  # 第二象限
    QUARDRANT_C = 16  # 第二象限
    QUARDRANT_D = 17  # 第二象限

def drag_and_drop_by_offset(self, sr_xpath, offset_x, offset_y, borderpoint=BorderPoints.CENTER, outtime=30):
    '''
    拖拽页面元素的边缘点、部位、或中央点到偏移的位置,共有9个位置,默认为中央点,可以设置为上下左右,或者四个角,或者上部、下部、左部,右部。

    :param sr_xpath: 定位需要拖拽元素的xpath
    :param borderpoint: 元素的边缘、部位、或者中央的位置点。
    :param offset_x: 水平偏移量
    :param offset_y: 垂直偏移量
    :param outtime: 定位元素超时时间
    :return:
    '''
    element = self.driver.getelement(sr_xpath, outtime=outtime, proxy=proxy)
    size = element.size
    action = ActionChains(self.driver.driver)
    action.move_to_element(element)
    if borderpoint == 1:
        action.move_by_offset(-size["width"] / 2, -size["height"] / 2)
    elif borderpoint == 2:
        action.move_by_offset(0, -size["height"] / 2)
    elif borderpoint == 3:
        action.move_by_offset(size["width"] / 2, -size["height"] / 2)
    elif borderpoint == 4:
        action.move_by_offset(-size["width"] / 2, 0)
    elif borderpoint == 5:
        pass
    elif borderpoint == 6:
        action.move_by_offset(size["width"] / 2, 0)
    elif borderpoint == 7:
        action.move_by_offset(-size["width"] / 2, size["height"] / 2)
    elif borderpoint == 8:
        action.move_by_offset(0, size["height"] / 2)
    elif borderpoint == 9:
        action.move_by_offset(size["width"] / 2, size["height"] / 2)
    elif borderpoint == 10:
        action.move_by_offset(0, -size["height"] / 4)
    elif borderpoint == 11:
        action.move_by_offset(0, size["height"] / 4)
    elif borderpoint == 12:
        action.move_by_offset(-size["width"] / 4, 0)
    elif borderpoint == 13:
        action.move_by_offset(size["width"] / 4, 0)
    elif borderpoint == 14:
        action.move_by_offset(-size["width"] / 4, -size["height"] / 4)
    elif borderpoint == 15:
        action.move_by_offset(size["width"] / 4, -size["height"] / 4)
    elif borderpoint == 16:
        action.move_by_offset(-size["width"] / 4, size["height"] / 4)
    elif borderpoint == 17:
        action.move_by_offset(size["width"] / 4, size["height"] / 4)
    else:
        raise Exception("参数错误:borderpoint")
    action.click_and_hold().move_by_offset(offset_x, offset_y).release().perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

13.模拟键盘输入

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys

def send_keys(self, xpath, key, outtime=30):
	'''
	调用getelement方法,在定位目标处输入指定内容(可以输入键盘关键字,比如Keys.ENTER)
    :param xpath: 定位需要输入元素的xpath
    :param key: 输入的文本信息 
	'''
    self.getelement(xpath, outtime=outtime).send_keys(key)

def send_keys(self,xpath,key,outtime=30):
	'''
	调用getelement方法,基于ActionChains库,在定位目标处输入指定内容
    :param xpath: 定位需要输入元素的xpath
    :param key: 输入的文本信息 
	'''
	ActionChains(driver).send_keys_to_element(self.getelement(xpath),key).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

14.鼠标复选

from selenium import webdriver
from selenium.webdriver import ActionChains

def clicks(self, xpaths, outtime=30):
	'''
	调用getelement方法,基于ActionChains库,在页面复选多个指标元素
	:param xpaths: 定位需要点击元素的xpath,数组形式,如['xpath1','xpath2']
    :param outtime: 定位元素超时时间 
	'''
	ActionChains(driver).keydown(Keys.CONTROL).perform()
	for xpath in xpaths:
		self.getelement(xpath, outtime=outtime).click()
	ActionChains(driver).keyup(Keys.CONTROL).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

15.清除内容

from selenium import webdriver
from selenium.webdriver import ActionChains

def clear(self, xpath, outtime=30):
	'''
	调用getelement方法,清除指定元素内的文本内容
	:param xpaths: 定位需要清除元素的xpath
    :param outtime: 定位元素超时时间 
	'''
    self.getelement(xpath, outtime=outtime).clear()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

16.等待元素出现

from selenium import webdriver

def waitelement(self, xpath=None,time=30, by=By.XPATH):
    '''
    等待元素出现,设置超时,需要注意iframe,需要对隐藏元素做优化,需要注意的是,首先确定xpath指向的网页元素
    是没有隐藏在网页中的,不然会立刻报错,因为selenium的等待函数是不能识别隐藏元素的
    :param xpath: 查找元素的xpath
    :param time: 查找超时时间,默认30s
    :param by: 定位元素的方法
    :return: 如果出现在网页中,返回True;未出现,就返回False
    '''
    try:
        WebDriverWait(self.driver,time).until(EC.presence_of_element_located((by, xpath)))
        # 解决有可能是隐藏元素的问题
        self.getelement(xpath, outtime=time)
    except:
        return False
    else:
        return True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

17.等待元素消失

from selenium import webdriver

def wait_ele_disappear(self, xpath,outtime=30):
    '''
    等待某个元素在网页上消失,默认设置的查找时间为3s,如果3s之内没有找到,循环会自己跳出
    如果一直未跳出,就会触发超时异常
    :param xpath: 定位元素的xpath
    :param outtime: 超时时间
    '''
    starttime = int(time.time())
    while self.waitelement(xpath=xpath, time=3):
        time.sleep(0.1)
        nowtime = int(time.time())
        if nowtime - starttime >= outtime:
            raise exceptions.NoSuchElementException('元素(xpath:{})未消失!'.format(xpath))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

18.添加页面标签属性

from selenium import webdriver

def addAttribute(self, elementObj, attributeName, value):
     '''
     直接向网页里面的标签添加属性

     :param elementObj: 网页元素,Webelement
     :param attributeName: 添加属性名称
     :param value: 添加属性值
     '''
     return self.driver.execute_script("arguments[0].%s=arguments[1]" % attributeName, elementObj, value)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

19.修改页面标签属性

from selenium import webdriver

def setAttribute(self, elementObj, attributeName, value):
    '''
    直接修改网页里面标签的属性值

    :param elementObj: 需要修改的网页元素
    :param attributeName: 需要修改的属性名称
    :param value: 修改的属性值
=    '''
    return self.driver.execute_script("arguments[0].setAttribute(arguments[1],arguments[2])", elementObj,
                                      attributeName, value)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

20.删除页面标签属性

from selenium import webdriver

def removeAttribute(self, elementObj, attributeName):
     '''
     移除网页里面的标签属性
     :param elementObj: 网页元素,Webelement
     :param attributeName: 移除属性名称
     '''
     return self.driver.execute_script(f'arguments[0].removeAttribute(\"{attributeName}\")',elementObj)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

21.修改页面标题文本内容

from selenium import webdriver

def settext(self, elementObj, text):
     '''
     直接修改网页里面标签的文本内容,用于无法使用send_kye时
     :param elementObj: 网页标签元素
     :param text: 想要改变的内容
     :return:
     '''
     return self.driver.execute_script("arguments[0].innerHTML=arguments[1]", elementObj, text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

基于Webdriver的一些常用操作

1.获取页面表格数据

from lxml import etree
from selenium import webdriver

def gettable(self, sources_xpath, cells_xpath='/td', cell_xpath='/span'):
    '''
   	获取当前页面指定表格的数据,以数组的形式存储
    :param sources_xpath: 指定表格的tbody资源
    :param cells_xpath: 所有列xpath
    :param cell_xpath: 列信息xpath
    '''
    table_tip = self.driver.getelement(sources_xpath)
    table_sources = table_tip.get_attribute('innerHTML')
    table_source = etree.HTML(table_sources)#此处是获取页面html代码到本地,优化爬取数据的效率
    ary = []
    rows = table_source.xpath('//tbody/tr')#获取所有行,此处xpath可根据实际dome结构更改
    for row in rows:
        ary_row = []
        cells = row.xpath(".{}".format(cells_xpath))#获取所有列
        for cell in cells:
            try:
                value = cell.xpath(".{}/text()".format(cell_xpath))[0]#获取单个表元数据
            except:
                value = "空"
            ary_row.append(value)
        ary.append(ary_row)
    return ary
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

2.写入excel

import pandas as pd
import glob,os

def	write_excel(self,paths,filename,data):
    '''
    将数据转换为DataFrame格式,并写入到excel文件中
    :param paths: 写入路径,格式为分组
    :param filename: 将要生成的excel文件名称,带格式
    :param data: 将要写入的数据
    '''
    data = pd.DataFrame(data)
    path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))#获取一个相对路径,os.path.realpath(__file__)返回当前文件所处路径,os.path.dirname返回指定路径的父目录路径
    #该处使用的是一个相对路径,适用于我们将数据存储于工程目录#
    for writepath in paths:
        path = os.path.join(path, '{}'.format(writepath))#获取excel将要写入的目录路径
    path = os.path.join(path, '{}'.format(filename))#指定将要生成的excel文件名称
    fs_page = glob.glob(path)
    for page in fs_page:
        os.remove(page)#删除该路径上已存在的同名文件
    data.to_excel(path)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3.读取excel

import pandas as pd
import glob,os

def read_execl_str(path):
    '''
    以文本格式读取execl里面的每一列数据,能解决execl里面以文本格式储存的数据读取出来之后,变成了int64类型
    添加遍历所有列的功能,就能实现一个execl里面所有标签的数据都以文本格式读取
    :param path: 读取的execl文件的绝对路劲
    :return: 返回pands对象
    '''
    pd.set_option('display.max_rows', None)
    pd.set_option('display.max_columns', None)
    pd.set_option('display.max_colwidth', 1000)
    pd.set_option('display.width', 1000)
    tmp = pd.read_excel(io=path, sheet_name=None)
    sheets = list(tmp.keys())  # 获取Execl所有sheet名
    dic = {}
    for sheet in sheets:
        tmp_df = tmp[sheet]
        col_list = tmp_df.columns.values.tolist()
        for col in col_list:
            dic[col] = str
    return pd.read_excel(io=path, sheet_name=None, dtype=dic)

def read_excel(self,paths,filename,sheet='Sheet1'):
    '''
    读取下指定目录的指定excel文件
    :param paths: 写入路径,格式为分组
    :param filename: 将要生成的excel文件名称,带格式
    :param sheet: 读取excel的sheet页面
    '''
    path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))#获取一个相对路径,os.path.realpath(__file__)返回当前文件所处路径,os.path.dirname返回指定路径的父目录路径
    for readpath in paths:
        path = os.path.join(path,'{}'.format(readpath))
    path = os.path.join(path,'{}'.format(filename))
    readdata = read_execl_str(path)['{}'.format(sheet)]
    return readdata
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

3.移动download文件夹下文件至指定文件夹


import time,glob,os,shutil

def movefile(slef,downfile,dirpaths,dirfile):
	'''
    移动download文件下文件至指定目录
    :param downfile: download文件下文件,带格式
    :param dirpaths: 移动目录的文件夹路径
    :param dirfile: 移动目标文件名称,带格式
    '''
	# 获取下载目录
	home = os.path.expanduser('~')
	starttime = int(time.time())
	while True:
    	zipf = glob.glob(os.path.join(os.path.join(home, 'Downloads'),downfile)
	    if zipf:
	    	break
	    nowtime = int(time.time())
	    if nowtime - starttime >= 60:
	        raise TimeoutError('获取文件超时')
	    time.sleep(1)
	# 获取目标路径
	testDataDir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
	for path in dirpaths:
	   testDataDir = os.path.join(testDataDir,path)
	# 定义备份文件
	targetf = os.path.join(testDataDir, dirfile)
	# 判断备份文件是否存在,存在则删除已存在的
	if os.path.exists(targetf):
	   os.remove(targetf)
	# 移动备份文件至目标路径
	shutil.move(zipf[0], targetf)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

4.上传文件

import time,glob,os,shutil

def uploadfile(self, paths, filename):
    '''
    上传指定文件夹下指定路径的文件
    paths: 文件路径,数组格式
    filename: 文件名称,带格式
    '''
    dialog = win32gui.FindWindow('#32770', '打开')#获取顶部句柄
    ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
    ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
    Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None)#定位路径输入框
    button = win32gui.FindWindowEx(dialog, 0, 'Button', None)#定位按钮
    path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    for path in paths:
        path = os.path.join(path, path)
    path = os.path.join(path, filename)
    if os.path.exists(path):#由于存在目标文件不存在的情况,这里加一个判断
        time.sleep(2)
        win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, path)
        win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button)
     else:
        win32gui.CloseWindow(dialog)
        raise AssertionError(path + "文件不存在")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

5.拉动滚动条

from selenium import webdriver

def scroll(self, speed=50):
    '''
    页面会以一定的速度滚动到网页的最下面

    :param speed: 页面向下滚动的速度
    :return:
    '''
    js = """ 
            (function () { 
                //这个是网页被卷去的高度,刚进来肯定是0
                var y = document.body.scrollTop; 
                var step = %(speed)s; 
                window.scroll(0, y); 
                function f() { 
                //最后卷曲的高度会大于网页的高度,所以会全部滚动完成
                    if (y < document.body.scrollHeight) { 
                        y += step; 
                        window.scroll(0, y); 
                        //50毫秒之后执行函数f。这里有点奇怪,是一个递归的函数
                        setTimeout(f, 100); 
                    }
                } 
                setTimeout(f, 1000); 
            })(); 
            """
    js = js % dict(speed='{}'.format(speed), )
    self.driver.execute_script(js)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

6.元素坐标获取

from selenium import webdriver
import time,glob,os,shutil

def getelement_sizeandloc(self, value=None, by=By.XPATH):
    '''
    获取网页元素再网页中的位置,用于有时候使用selenium的方法点击元素会报错,可以使用这个函数获取元素位置,再去操作
    :param value:xpath
    :param by:定位方式
    :return:picture对象,提供了常规的点击之类的操作
    '''
    element = self.getelement(value)
    x = element.location['x']
    y = element.location['y']
    height = element.size['height']
    width = element.size['width']
    return (x, y, width, height)

def getabsloc(self, value=None, by=By.XPATH, xpath=None):
    '''
    返回元素在屏幕上的绝对坐标,中心点的坐标
    :param value: xpath表达式
    :param by: 查找元素方法
    :param xpath: [iframe1,iframe2,iframe3]这个需要手动将iframe以数列的形式
                传递进来,并且,外层的iframe在前面
    :return: 返回一个对象,用来模拟鼠标等事件
    '''
    # 获取元素位置和大小,8个像素点应该是不会影响操作的,默认用获取到的原点做偏移
    if xpath is None:
        xpath = []
    # 获取元素的相对位置
    rect_ele = self.getelement_sizeandloc(value=value, by=by)
    # 获取窗口大小
    rect_bro = self.driver.get_window_rect()
    # 获取到iframe的大小,以及iframe的层数
    frame_x = 0
    frame_y = 0
    if xpath:
        frame_x, frame_y = self.__getiframerect(xpath)
    # 获取网页截图大小,只获取一次,不用每次都需要对网页进行截图
    if not self.page_origin:
        pic_path = os.path.join(sys.path[0], 'tmp_img')
        if not os.path.exists(pic_path):
            os.mkdir(pic_path)
        pic_path = os.path.join(pic_path, 'tmp.png')
        self.driver.get_screenshot_as_file(filename=pic_path)
        img = cv2.imdecode(np.fromfile(pic_path, dtype=np.uint8), -1)
        size = img.shape
        self.page_origin = (rect_bro['x'], rect_bro['y'] + (rect_bro['height'] - size[0]))
        os.remove(pic_path)
        os.rmdir(os.path.split(pic_path)[0])
    mid_absloc_x = rect_ele[0] + rect_ele[2] / 2 + self.page_origin[0] + 8 + frame_x
    mid_absloc_y = rect_ele[1] + rect_ele[3] / 2 + self.page_origin[1] - 8 + frame_y

    return absaction(int(mid_absloc_x), int(mid_absloc_y))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

7.压缩文件

import os,zipfile

def zip(self,filepath,filename,files:list):
	'''
	:param filepath: 文件目录
	:param filename: 压缩文件名称
	:param files: 文件组,将被压缩的所有文件
	'''
    path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    path = os.path.join(path, 'TestData')#获取到存放文件的根目录TestData,这个路径根据你的真实路径去写
    for src in filepath:#从根目录往下,找到你要解压的文件的位置
        path = os.path.join(path, '{}'.format(src))
    zip_src = os.path.join(path,'{}.zip'.format(filename))
    old_file = glob.glob(zip_src)
    for page in old_file:
        os.remove(page)#判断是否存在历史文件,如果存在则删除历史文件
    filedir = zipfile.ZipFile(zip_src,'w',zipfile.ZIP_DEFLATED)
    for file in files:
        new_file = os.path.join(path,'{}'.format(file))
        if glob.glob(new_file):
            filedir.write(new_file,file)
        else:
            raise AssertionError('文件不存在!')
    filedir.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

8.解压文件

import os,zipfile

def unzip(self,filepath,filename):
	'''
	:param filepath: 文件目录
	:param filename: 压缩文件名称
	'''
    path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    path = os.path.join(path, 'TestData')
    for src in filepath:
        path = os.path.join(path, '{}'.format(src))
    zip_src = os.path.join(path,'{}'.format(filename))
    if glob.glob(zip_src):
        files = zipfile.ZipFile(zip_src,'r')
        for file in files.namelist():
            old_path = os.path.join(path,file)
            old_file = glob.glob(old_path)
            for page in old_file:
                os.remove(page)
            files.extract(file,path)
    else:
        raise AssertionError('文件不存在!')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

9.展开树结构资源

def expandtree(self,paths,o_xpath='//div[text()="{}"]'):
     '''
     函数功能:选择文件时根据名称展开路径
     :param paths: 展开的节点名称,数组形式,如['根节点','父节点','子节点']     
     :param o_xpath: 资源树根节点xpath
     '''
     xpath = o_xpath
     expand = '/preceding-sibling::i[@class="eui-icon eui-tree-expand"]'
     shrink = '/preceding-sibling::i[@class="eui-icon eui-tree-shrink"]'
     for path in paths:
         if self.wait(xpath.format(path)+expand, 1):
             self.click(xpath.format(path)+expand)
             self.wait(xpath.format(path)+shrink)
         xpath = xpath.format(path)+'/parent::div/following-sibling::ul/li//div[text()="{}"]/'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/149896
推荐阅读
  

闽ICP备14008679号