省略浏览器驱动路径

我们的代码创建 WebDriver对象时,需要指定浏览器驱动路径,比如

from selenium.webdriver.chrome.service import Service
wd = webdriver.Chrome(service=Service(r'd:\tools\chromedriver.exe'))

这样写有几个问题:

一是,比较麻烦, 每次写自动化代码都 要指定路径。

二是,如果你的代码给别人运行,他的电脑上存放浏览器驱动的路径不一定和你一样(比如他的电脑是苹果Mac电脑),得改脚本。

有什么好办法呢?

我们可以把浏览器驱动 所在目录 加入环境变量 Path , 写代码时,就可以无需指定浏览器驱动路径了,像下面这样

wd = webdriver.Chrome()

因为,Selenium会自动在环境变量 Path 指定的那些目录里查找名为chromedriver.exe 的文件。

一定要注意的是, 加入环境变量 Path 的,

不是浏览器驱动全路径,比如 d:\tools\chromedriver.exe

而是 浏览器驱动所在目录,比如 d:\tools

而且设置完环境变量后,别忘了重启IDE(比如 PyCharm) 新的环境变量才会生效。

特别注意:Selenium 升级到版本 4 以后, 下面这种 find_element_by* 方法都作为过期不赞成的写法

# 初始化代码 .... 

wd.find_element_by_id('username').send_keys('byhy') wd.find_element_by_class_name('password').send_keys('sdfsdf') wd.find_element_by_tag_name('input').send_keys('sdfsdf') wd.find_element_by_css_selector('button[type=submit]').click()

运行会有告警,所以现在都要写成下面这种格式

from selenium.webdriver.common.by import By

# 初始化代码 ....

wd.find_element(By.ID, 'username').send_keys('byhy')
wd.find_element(By.CLASS_NAME, 'password').send_keys('sdfsdf')
wd.find_element(By.TAG_NAME, 'input').send_keys('sdfsdf')
wd.find_element(By.CSS_SELECTOR,'button[type=submit]').click()

ActionChains类(鼠标操作)

click(on_element=None)     --- 鼠标单击

       double_click(on_element=None)    ---  双击       

       context_click(on_element=None)   ---  右击       

       click_and_hold(on_element=None)   ---  鼠标单击并且按住不放

       drag_and_drop(source,target)   ---  拖拽

       drag_and_drop_by_offset(source,xoffset,yoffset)   ---  将目标拖动到指定的位置

       key_down(value,element=None)  ---  按下某个键盘上的键

       key_up(value,element=None)   ---  松开某个键

       move_by_offset(xoffset,yoffset)   ---  鼠标从当前位置移动到某个坐标

       move_to_element(to_element)   ---  鼠标移动到某个元素

       move_to_element_with_offset(to_element,xoffset,yoffset)   ---  移动到距某个元素(左上角坐标)多少距离的位置

       perform()    ---  执行链中的所有动作

       release(on_element=None)   ---  在某个元素位置松开鼠标左键

举例:

鼠标右击

from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains  # 引入 ActionChains 类 
driver = webdriver.Firefox()
driver.get("http://yunpan.360.cn")
#.......此处省略1W代码,哈哈哈 
# 定位到要右击的元素
right_click = driver.find_element
# 对定位到的元素执行鼠标右键操作
ActionChains(driver).context_click(right_click).perform() 
#.......(省略其他代码)

1)ActionChains(driver)

调用 ActionChains() 类,将浏览器驱动 driver 作为参数传入。

2)context_click(right_click)

context_click() 方法用于模拟鼠标右击操作,在调用时需要指定元素定位。

3)perform()

执行所有 ActionChains 中存储的行为,可以理解为是对整个操作的提交动作。

下拉框操作

下拉框属性

# 1.导入包Select类
from selenium.webdriver.support.select import Select
 
# 2.定位下拉菜单元素
 
# 3.把定位的下拉菜单元素存储到Select类中创建下拉框对象
select = Select(下拉菜单元素)
 
# 4.1 通过value属性来选择,option标签的一个属性值
select.select_by_value('属性值')
 
# 4.2 通过选项索引(index)值选择 索引从0开始
select.select_by_index(索引值)
 
# 4.3 通过选项名称选择
select.select_by_visible_text('选择名称')

2、下拉菜单对象的其他操作(了解)

调用方法选择下拉框中的选项

操作 说明

all_selected_options 查看所有已选

first_selected_option 查看第一个已选

is_multiple 查看是否是多选

options 查看选项元素列表

取消选择:

操作说明

deselect_by_value() 通过option标签的value属性来选择

deselect_by_index() 通过选项索引(index)值选择 索引从0开始

deselect_by_visible_text() 通过选项名称选择

对JS元素操作

Python selenium对js元素进行增删改查操作

增加属性
 driver.execute_script(“arguments[0].%s=arguments[1]” %attributeName,elementObj, value)

修改属性
driver.execute_script(“arguments[0].setAttribute(arguments[1],arguments[2])”, elementObj, attributeName, value)

获取属性
elementObj.get_attribute(attributeName)

删除属性
driver.execute_script(“arguments[0].removeAttribute(arguments[1])”,elementObj, attributeName)

attributeName 就是属性名字 elementObj 就是元素对象 value 就是值

多窗口切换 window_handles

多窗口切换

  • current_window_handle:获得当前窗口句柄

  • window_handles:获取所有窗口的句柄到当前会话,返回一个窗口句柄列表

  • switch_to.window():切换窗口句柄

import time
from selenium import webdriver
 
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
 
# 获得百度搜索窗口句柄
search_windows = driver.current_window_handle
print(search_windows)
 
driver.find_element_by_link_text('登录').click()
driver.find_element_by_link_text("立即注册").click()
 
# 获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
print(all_handles)
 
# 切换到注册窗口 方式1 通过判断是否与当前窗口句柄一致
for handle in all_handles:
    if handle != search_windows:
        driver.switch_to.window(handle)
        driver.find_element_by_name("userName").send_keys('我是测试小白')
        driver.find_element_by_name('phone').send_keys('12345678910')
        time.sleep(2)
        # 后续步骤省略
 
# 切换到注册窗口 方式2 通过获取的所有窗口列表的索引切换
# driver.switch_to.window(all_handles[1])
# driver.find_element_by_name("userName").send_keys('我是测试小白')
# driver.find_element_by_name('phone').send_keys('12345678910')
# time.sleep(2)
 
driver.quit()

三大等待方式

1.  强制等待

  • 方法:sleep(seconds),seconds 等待时间,单位 秒 s

  • 说明:不管浏览器是否加载完了,程序都得等待3秒,不建议使用,严重影响执行速度


from selenium import webdriver
from time import sleep
 
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/IT_heima?spm=1001.2014.3001.5343')
 
sleep(2)  # 强制等待2秒再执行下一步
print(driver.current_url)
print(driver.title)
 
driver.close()

2.  隐式等待

  • 方法:implicitly_wait(time_to_wait) ,  time_to_wait 等待时间, 单位秒 s

  • 说明:设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。此方法是全局性的,设置一次即可

  • 弊端:程序会一直等待整个页面加载完成,也就是一般情况下看到浏览器标签栏那个小圈不再转,才会执行下一步,但是页面的元素已加载完,js等未加载完,仍会等待


from selenium import webdriver
 
driver = webdriver.Chrome()
# 隐式等待,最长等20秒
driver.implicitly_wait(20)
driver.get('https://blog.csdn.net/IT_heima?spm=1001.2014.3001.5343')
 
print(driver.current_url)
print(driver.title)
 
driver.close()

3. 显示等待

   init方法:__init__(driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)

  • driver :浏览器驱动driver :浏览器驱动

  • timeout :最长超时时间,默认以秒为单位。timeout :最长超时时间,默认以秒为单位。

  • poll_frequency :检测的间隔(步长)时间,默认为0.5S。

  • ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。

 unit方法:until( method, message='')

  • method:传入执行的方法

  • message:超时时的提示信息

  until_not方法:同until

  • 使用: WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)

 
from selenium import webdriver
from selenium.common.exceptions import ElementNotVisibleException
from selenium.webdriver.support.ui import WebDriverWait
 
driver = webdriver.Chrome()
# 隐式等待,最长等20秒
driver.implicitly_wait(20)
driver.get('http://baidu.com')
 
print(driver.current_url)
print(driver.title)
 
# 每隔0.5s去查找元素 kw,超时时间为10s,返回WebElement对象
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("kw"))
element.send_keys('selenium')
 
# 每隔1去查找元素 kw是否可见,超时时间为30s,返回结果为布尔值  
is_disappeared = WebDriverWait(driver, 30, 1, ElementNotVisibleException).until_not(
    lambda x: x.find_element_by_id("kw1").is_displayed())
print(is_disappeared)
 
# 错误用法   until() 第一个参数应该是方法,此处传入的是WebElement对象,所以不正确,可参照上面的写法
# WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))
driver.close()

4. 总结

  • sleep(n):强制等待n秒,影响程序执行速度

  • implicitly_wait( ):隐式等待,全局性,设置一次即可,针对的是整个页面是否加载完成

  • WebDriverWait( ):显示等待,针对单个元素判断,灵活

  • 隐式等待和显时等待同时使用时,超时时间取两者最长的