八大元素定位方式
单数定位方法,遇到多个值,默认取第一个。也可以加索引取其他值,索引从1开始
driver.find_element_by_id()
driver.find_element_by_name()
driver.find_element_by_class_name()
find_element_by_link_text()
driver.find_element_by_partail_link_text()
driver.find_element_by_xpath()
driver.find_element_by_css_slecter()
复数定位,返回的是一个list。和上述方法相同,只是把element改为elements
如:driver.find_elements_by_xpath()
其他书写方式
在做web自动化时,往往是需要封装脚本的。上述的方法不利于封装,并且后期将不再维护了。
# 导入By类
from selenium.webdriver.common.by import By
# 以下三种写法是相等的
driver.find_element_by_id('kw')
driver.find_element('id','kw')
driver.find_element(By.ID,'kw') # 需要先导入By类
三种等待方式
我们在做web自动化时,经常会遇到因为加载慢而出现元素未找到的情况,这种情况只需要加一个等待就好。
等待有三种方式:强制等待、隐式等待和显式等待
sleep():强制等待,设置固定休眠时间
执行sleep()后线程休眠的时间,如设置3秒,则必须等待3秒再继续下面的代码。
import time
# 强制等待3秒钟
time.sleep(3)
implicitly_wait():隐式等待,设置的全局等待,只需要设置一次
对页面中所有的元素设置加载时间,如设置10秒,如果在1秒的时候找到元素则继续,不需要等到10秒后再继续流程。如果超过10秒未找到则抛出异常。
注:隐式等待只对查找元素生效,对于页面中是否包含某个文本,元素是否可以点击是不生效的
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 设置隐式等待,最长等待时间是10秒
WebDriverWait():显式等待,是针对某个元素设置的等待时间
在设置的时间内,默认每隔一段时间检测一次是否满足条件,满足条件则继续执行下面的代码,超过时间就抛出异常。默认检测频率是0.5秒,默认抛出异常NoSuchElementException。
显式等待使用时需要加上条件配合使用,比如等待某个元素可见、等待某个元素可点击、等待某个元素是否包含某个文本等等,因此需要导入两个模块
以下是最常用的几种条件:
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait # 导入显示等待模
from selenium.webdriver.support import expected_conditions # 导入条件模块
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 实例化一个WebDriverWait,最长等待时间为10秒,默认0.5秒检测一次,这里设置为0.2秒。
#wait = WebDriverWait(driver, timeout=10, poll_frequency=0.2)
wait = WebDriverWait(driver, 10, 0.2) # 简写
locator = ['id', 'kw']
# 等待某个元素加载
elem = wait.until(expected_conditions.presence_of_element_located(locator))
# 等待元素可见
elem = wait.until(expected_conditions.visibility_of_element_located(locator))
# 等待元素可以被点击
elem = wait.until(expected_conditions.element_to_be_clickable(locator))
elem.send_keys('上海')
elem.submit()
# 等待页面标题中含有“上海”
wait.until(expected_conditions.title_contains('上海'))
iframe标签切换
提供 iframe 的标识:index, name, iframe, Webelement
如果想定位iframe标签下的元素,不能直接查找,需要先切换到该iframe标签下才能进行定位。如图,要定位select需要先切换到iframe下
[图片上传失败...(image-9dd793-1629275203459)]
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.w3school.com.cn/tiy/t.asp?f=html_select')
# 通过 WebElement 切换
iframe = driver.find_element('id', 'iframeResult')
driver.switch_to.frame(iframe)
# 通过 name 属性切换
driver.switch_to.frame('iframeResult')
# 通过索引切换
driver.switch_to.frame(0)
#切换后就可以找到select元素了
elem = driver.find_element('xpath', '//select')
print(elem)
# 退回主页面
driver.switch_to.default_content()
# 退回父级iframe
driver.switch_to.parent_frame()
alert弹窗处理
现在的网页一般是css或js实现弹窗效果,可以使用常用的元素定位方法来操作。如果遇到了alert弹窗,怎么处理呢?
其实很简单,只需要使用switch_to.alert方法就可以切换到弹窗,然后使用text/accept/dismiss/ send_keys等方法进行操作。
# 切换到alert弹窗,没有括号,也不需要传参数,全局只有一个
my_alert = driver.switch_to.alert
# 返回alert弹框中的文字信息
print(my_alert.text)
# 确定,接收弹窗
my_alert.accept()
# 取消,关闭弹窗
my_alert.dismiss()
# 向弹窗发送文字
my_alert.send_keys('哈哈哈')
window窗口切换
在web自动化时,如果遇到点击链接在新窗口打开,而我们要操作新窗口就要用到切换窗口了。比如,百度搜索“京东”,点击京东官网
- 切换窗口用到的是switch_to.window(),它需要传入目标窗口的句柄
- 句柄可以理解为窗口的id,在浏览器中是唯一的
- 切换窗口的步骤:打开新窗口--> 获取当前浏览器所有句柄--> 选择最后一个句柄,因为新窗口都是放在最后的
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
# 打开百度,定位输入框,输入“京东”,点击搜索
driver.get("http://www.baidu.com")
elem = driver.find_element('id', 'kw')
elem.send_keys('京东')
driver.find_element('id', 'su').click()
# 查找京东,点击
driver.find_element('xpath',"//h2[@class='c-font-big']").click()
# 等待新页面出现
time.sleep(2)
#获取所有句柄
handle = driver.window_handles
#切换到最后一个句柄
driver.switch_to.window(handle[-1])
鼠标操作
selenium给我们提供了一个ActionChains类来处理鼠标的操作,比如悬浮、移动、拖拽、右击等。使用前需要先导入,先来看一个百度“设置”的示例
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.baidu.com')
driver.maximize_window()
# 实例化一个ActionChains,可全局使用
ac = ActionChains(driver)
# 找到”设置“元素
setting = driver.find_element('xpath', "//span[text()='设置']")
# 鼠标悬停, move_to_element
ac.move_to_element(setting).perform()
time.sleep(2)
# 找到高级搜索
adv_setting = driver.find_element('xpath', "//a[text()='高级搜索']")
adv_setting.click() # 也可以用 ac.click(adv_setting).perform() 方法
鼠标操作的所有方法,后面都需要执行perform()操作才会生效
所有的鼠标操作可以连在一次,最后再一次性释放操作,称为“链式调用”,比如
ac.move_to_element(setting).click(adv_setting).drag_and_drop().context_click().perform()
鼠标操作常见的方法:
perform() # 执行链中的所有动作
ac.click(elem).perform() #单击
ac.double_click(elem).perform() # 双击
ac.context_click(elem).perform() #右击
ac.move_to_element(elem).perform() #鼠标移动到elem,悬停
ac.drag_and_drop(elem1, elem2).perform() #elem1拖拽到elem2然后松开
键盘操作
selenium提供了比较完整的键盘操作,在使用的模拟键盘操作之前需要导入。先来看一个百度搜索的示例
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.implicitly_wait(10)
# 定位百度搜索框,输入搜索词“python“,分别用三种方法来实现搜索
driver.get('http://www.baidu.com')
input_el = driver.find_element('id', 'kw')
input_el.send_keys('python')
# 方法一,定位“搜索”元素,点击
driver.find_element('id', 'su').click()
# 方法二,form表单下可以用submit() 提交进行搜索
input_el.submit()
# 方法三,敲回车键
input_el.send_keys(Keys.ENTER)
# 方法四,ActionChains 和 Keys 组合使用,传入鼠标操作
ac = ActionChains(driver)
ac.send_keys(Keys.ENTER).perform()
在keys类中,定义了非常多的按键操作,并且按键是可以组合操作的,比如Ctrl+C等。按键操作往往是结合元素来操作的,例如百度搜索实例的方法三。这些操作都是需要使用send_keys()来发送的。以下内容是在实际上会常用到的
from selenium.webdriver.common.keys import Keys
send_keys(Keys.CONTROL,'a') # 全选(Ctrl+A)
send_keys(Keys.CONTROL,'c') # 复制(Ctrl+C)
send_keys(Keys.CONTROL,'x') # 剪切(Ctrl+X)
send_keys(Keys.CONTROL,'v') # 粘贴(Ctrl+V)
send_keys(Keys.ENTER)# 回车键
send_keys(Keys.BACK_SPACE) # 删除键
send_keys(Keys.SPACE) # 空格键
send_keys(Keys.TAB) # 制表键
send_keys(Keys.ESCAPE) # 回退键
send_keys(Keys.F5) # 刷新键
Select下拉框
from selenium import webdriver
from selenium.webdriver.support.select import Select
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('url')
# 方法一:直接定位选项的元素进行点击
driver.find_element('xpath', "ele").click()
# 方法二,先找到select元素,再把元素对象传入Select类进行实例化
s = driver.find_element('id', "ele")
s_obj = Select(s)
# 以下分别通过value属性值、text文本和索引进行选择
s_obj.select_by_value('value')
s_obj.select_by_visible_text('text')
s_obj.select_by_index(1)
js脚本
修改12306官网的出发日期
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.12306.cn/index/')
# 执行 js 语句写上日期(修改value值),js可以多个语句写在一起,分号隔开,按顺序执行
time.sleep(5)
js_code = "let input = document.getElementById('train_date');input.readOnly = false;input.value = '2021-03-11';"
driver.execute_script(js_code)
time.sleep(5)
上面查找元素用的是js,我们也可以js和python混用,使用python来查找元素
import time
from selenium import webdriver
driver = webdriver.Chrome()
input_elem = driver.find_element('id', 'train_date')
time.sleep(2)
# 准备 js 代码
js_code = "arguments[0].readOnly = false; arguments[0].value = '2021-03-22';"
driver.execute_script(js_code, input_elem)
time.sleep(3)
arguments可以理解为python里面的占位符,如果还有参数,可以继续使用arguments[1]、arguments[2]来占位
窗口滚动
窗口滚动selenium是无法实现的,所以这里是借助的js代码来操作滚动条。在python中,执行js代码用的是
driver.execute_script(js_code)
窗口滚动最常用的是滚动到可视范围内,下面是12306上的小示例
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('https://www.12306.cn/index/')
# 找到需要定位的元素
el = driver.find_element('xpath', "//h2[contains(text(),'友情链接')]")
# 方法一,将元素滚动到可视范围之内
el.location_once_scrolled_into_view()
# 方法二,和方法一效果相同
driver.execute_script("arguments[0].scrollIntoView();", el)
# 将元素向下滚动200个像素(y坐标)
driver.execute_script('window.scrollBy(0,200);')
# 向右滚动200个像素(x坐标)
driver.execute_script('window.scrollBy(200,0);')
# 将窗口滚动到底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 设置窗口大小
driver.set_window_size(800, 700)
文件上传
我们在使用python做web自动化的过程中,经常会遇到文件上传的操作。对于文件上传存在input输入框情况,可以直接定位input元素,使用send_keys(filepath)方法实现。对于没有input输入框的文件上传,则需要借助第三方工具,在上传文件时打开系统窗口。以下是两个上传文件操作比较简单的工具
-
windows系统:pywinauto库
安装:pip install pywinauto
导入:from pywinauto.keyboard import send_keys -
mac/Linux/window通用:pyautogui 跨平台
python3.8环境:先安装依赖 pip install pillow==6.2.2,再安装 pip install pyautogui
非python3.8环境:直接 pip install pyautogui
导入:import pyautogui
input元素使用send_keys()方法
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
URL = 'https://xxxx/kk-form/fs/fm/form/161519068236342881d3774ec5428571/fill'
driver.get(URL)
# 获取上传组件的元素
f = driver.find_element('xpath', "(//input[@class='van-uploader__input'])[1]")
# 使用send_keys直接发送文件路径即可
f.send_keys(r'/Users/lili/Documents/weixin.jpeg')
time.sleep(5)
driver.quit()
非input元素,window方法:使用pywinauto库
from pywinauto.keyboard import send_keys
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
URL = 'https://xxxx/kk-form/fs/fm/form/161519068236342881d3774ec5428571/fill'
driver.get(URL)
f = driver.find_element('xpath', "(//input[@class='van-uploader__input'])[1]")
# 触发点击事件,让系统的弹框弹出来
f.click()
# 等待,因为弹框弹出来需要时间
time.sleep(1)
# 这里是pywinauto 的send_keys 方法
send_keys(r'/Users/lili/Documents/weixin.jpeg')
# 使用return提交
send_keys('{VK_RETURN}')
非input元素,mac/Linux/window的通用方法:pyautogui库
from selenium import webdriver
import pyautogui
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
URL = 'https://xxxx/kk-form/fs/fm/form/161519068236342881d3774ec5428571/fill'
driver.get(URL)
f = driver.find_element('xpath', "(//input[@class='van-uploader__input'])[1]")
# 触发点击事件,让系统的弹框弹出来
f.click()
time.sleep(1)
# 写入路径
pyautogui.write(r'/Users/lili/Documents/weixin.jpeg')
# 敲回车:相当于点击【打开】按钮,需要敲2次,避免失败
pyautogui.press('enter', 2)