本文记录内容来自多位博主, 具体请参考以下链接:
selenium总结1
selenium总结2
警告框
等待方式
selenium安装
1. 安装 selenium
打开 cmd : pip install selenium
2. 下载浏览器驱动
在这里提供三个常用的下载地址(更多的浏览器驱动请查看首行第二个链接):
部分驱动可能会受浏览器的版本影响这里再提供一个 Google 浏览器的下载路径(我再下载时并没有碰到这个问题)
查看驱动和浏览器的映射关系
尽量把下载好的驱动放到一个显眼的位置, 再使用驱动时需要用到路径
selenium使用
基于浏览器驱动对象的方法和属性
实例化对象
- Chrome()
from selenium.webdriver import Chrome
# 使用驱动时会返回一个浏览器对象, 此时运行程序会自动打开一个浏览器
driver = Chrome("E:\\driver\\chromedriver")
下列方法是由 Chrome 创建出来的对象直接调用的方法及属性
发出请求
- get()
driver.get() <-- 打开指定的网址
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
url = "www.baidu.com"
driver.get(url)
获取源码
- page_source
driver.page_source <-- 返回页面的源码数据
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
url = "www.baidu.com"
driver.get(url)
page_source = driver.page_source
断言
不管是在做功能测试还是自动化测试,最后一步需要拿实际结果与预期进行比较。这个比较称之为断言。
- title 获取当前页面标题
driver.title <-- 返回当前页面的标题
- current_url 获取当前页面 url
driver.current_url <-- 返回当前页面 url
标签定位
selenium 提供了8中方法来定位:
- find_element_by_id()
driver.find_element_by_id() <-- 输入 id 标签的值, 返回该标签对象
- find_element_by_name()
driver.find_element_by_name() <-- 输入 name 标签的值, 返回该标签对象
- find_element_by_class_name()
driver.find_element_by_class_name() <-- 输入 class 标签的值, 返回该标签对象
- find_element_by_tag_name()
driver.find_element_by_tag_name() <-- 输入标签名称, 返回该标签对象
- find_element_by_link_text()
driver.find_element_by_link_text() <-- 输入标签的文本内容, 返回该标签对象 (精准匹配)
- find_element_by_partial_link_text()
driver.find_element_by_partial_link_text() <-- 输入标签的文本内容, 返回该标签对象 (模糊匹配)
- find_element_by_xpath()
driver.find_element_by_xpath() <-- 输入 xpath 表达式, 返回该标签对象
- find_element_by_css_selector()
driver.find_element_by_css_selector() <-- 类选择器
参考网址: 类选择器
上述方法只能返回一个标签对象, 将方法的 element 改为 elements 即可返回一个列表的多个标签对象
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
url = "www.baidu.com"
# 使用get方法打开一个网页
driver.get(url)
# 定位的方法会返回定位的标签对象
search_input = driver.find_element_by_id("kw")
设置窗口大小及刷新页面
- 刷新页面: refresh()
driver.refresh() <-- 刷新当前浏览器页面
- 设置窗口大小: set_window_size(x, y) x 为宽, y 为 高
driver.set_window_size(1920, 1080) <-- 将窗口大小设置为 1920*1080
- 最大化浏览器: maximize_window()
driver.maximize_window() <-- 最大化当前浏览器
from selenium.webdriver import Chrome
import time
driver = Chrome("E:\\driver\\chromedriver")
driver.get("www.baidu.com")
driver.set_window_size(1920, 1080)
time.sleep(2)
driver.refresh()
无头浏览器
在执行 selenium 时, 不再弹出浏览器窗口显示执行界面
- 导入并创建一个 Options 对象
from selenium.webdriver.chrome.options import Options
options = Options()
- .add_argument("–headless")
options.add_argument("–headless")
- .add_argument(“disable–gpu”)
options.add_argument(“disable–gpu”)
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
driver = Chrome(executable_path="E://driver//chromedriver", options=options)
规避检测
非人为的去访问网页时, 在 consola 中输入, window.navigator.webdriver 会显示 True, 证明这并不是一个人为的访问行为
- 以chrome为例, 79版本以前的浏览器使用
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(executable_path="E://driver//chromedriver", options=options)
- 79版本之后, 修改此值不再生效, 这里搬一下其他博主的方法
from selenuim import webdriver
driver = webdriver.Chrome()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
79版本之后的 chrome 使用上述方法, 虽然可以在consola中显示人为访问的行为, 但是我在使用时, 部分网页仍然拒绝访问
页面截屏
- 对当前页面截屏: save_screenshot(filename)
driver.save_screenshot() <-- 接收一个参数, 为图片保存的地址
from selenium.webdriver import Chrome
driver = Chrome(executable_path="E://driver//chromedriver")
driver.get("https://www.baidu.com")
driver.save_screenshot("./图片.jpg")
执行 JS 代码
- execute_script()
driver.execute_script() <-- 传入 js 代码并执行
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
前进后退
- 前进 forward()
driver.forward() <-- 页面前进
- 后退 back()
driver.back() <–页面后退
from selenium.webdriver import Chrome
import time
driver = Chrome("E:\\driver\\chromedriver")
# 打开百度首页
driver.get("www.baidu.com")
time.sleep(2)
# 打开百度翻译
driver.get("https://fanyi.baidu.com/")
time.sleep(2)
# 后退到首页
driver.back()
time.sleep(1)
# 前进回百度翻译
driver.forward()
页面窗口切换
当我们点击浏览器上的链接时, 会创建出新的页面, 进行窗口的切换需要获得页面的句柄
- 获取当前页面句柄 : current_window_handle
driver.current_window_handle <-- 返回当前页面句柄
- 返回所有窗口的句柄 : window_handles
driver.window_handles <-- 返回所有已打开的页面句柄
- 切换到对应的窗口 : switch_to.window()
driver.switch_to.window() <-- 传入对应的窗口句柄
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
driver = Chrome("E:\\driver\\chromedriver.exe")
driver.get("https://www.baidu.com")
handle = driver.current_window_handle
print(handle)
button = WebDriverWait(driver, 20, 0.5).until(EC.visibility_of_element_located((By.XPATH, "//*[@id='s-hotsearch-wrapper']/div/a[1]/div")))
button.click()
sleep(5)
button1 = WebDriverWait(driver, 20, 0.5).until(EC.visibility_of_element_located((By.XPATH, "//*[@id='bottom_layer']/div[1]/p[4]/a")))
button1.click()
sleep(5)
all_handles = driver.window_handles
print(driver.window_handles)
for h in all_handles:
driver.switch_to_window(h)
sleep(3)
driver.quit()
基于元素的方法和属性
文本输入
- 输入内容 send_keys()
search_input.send_keys() <-- 传入一个字符串对象
- 传入本地文件 send_keys()
search_input.send_keys() <-- 传入文件的绝对路径
- 清除文本 clear()
search_input.clear() <-- 清除该标签对象中的内容
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
url = "www.baidu.com"
# 使用get方法打开一个网页
driver.get(url)
# 定位的方法会返回定位的标签对象
search_input = driver.find_element_by_id("kw")
# 向搜索框内输入内容
search_input.send_keys("飞机")
# 向搜索框传入文件
search_input.send_keys("E:\\xiaojichimi.txt")
# 清除文本
search_input.clear()
点击和回车
- 点击 click()
button.click() <-- 点击 button 标签对象
- 回车 submit()
search_input.submit() <-- 执行回车操作
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
url = "www.baidu.com"
# 使用get方法打开一个网页
driver.get(url)
# 定位的方法会返回定位的标签对象
search_input = driver.find_element_by_id("kw")
# 向搜索框内输入内容(输入内容后可以直接使用回车)
search_input.send_keys("飞机")
search_input.submit()
# 定位到搜索按钮
button = driver.find_element_by_id("su")
button.click()
元素的常用属性及方法
- 返回元素的尺寸: size
search_input.size <-- 返回该标签对象的尺寸(width, height)
- 返回元素的坐标: location
search_input.location <-- 返回该标签对象的坐标(x, y)
- 返回元素的文本信息: text
search_input.text <-- 返回该标签对象的文本信息
- 返回元素的属性值: get_attribute()
search_input.get_attribute() <-- 传入一个标签的名称, 返回该标签的属性值
- 返回元素的结果是否可见: is_displayed()
search_input.is_displayed() <-- 返回一个bool型值, 表示该标签是否可见
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
driver.get("www.baidu.com")
# 定位到搜索框
search_input = driver.find_element_by_id("kw")
# 返回搜索框的尺寸
print(search_input.size) # print(search_input.size["width"]) print(search_input.size["height"])
# 返回搜索框的左边
print(search_input.location) # print(search_input.location["x"]) print(search_input.location["y"])
# 返回搜索框的文本信息
print(search_input.text)
# 返回搜索框中的属性值
print(search_input.get_attribute("type")) 指定想要获取的属性
# 返回元素的结果是否可见
print(search_input.is_displayed()) # 返回bool类型的值
动作链
模拟在浏览器中的一系列动作(连续性 动作)
- 动作链: ActionChains() <–传入浏览器驱动创建出来的对象
使用 ActionChains(驱动对象) 类创建对象, 使用对象调用下列方法
from selenium.webdriver import ActionChains
mouse = ActionChains() <-- 返回一个动作链对象
-
点击长按: click_and_hold() <–接收的参数是一个标签的定位
mouse.click_and_hold() <-- 传入一个对象, 表示长按此对象
-
移动偏移: move_by_offset(x, y) <–X轴移动量, Y轴移动量
mouse.move_by_offset(100, 0) <-- 传入两个参数, 表示将当前定位的对象向右偏移 100 个像素
-
右击: context_click()
mouse.context_click() <-- 右击传入的对象, 默认为当前定位的对象
-
双击: double_click()
mouse.double_click() <-- 双击传入的对象, 默认为当前定位的对象
-
指定区域内点击: move_to_element_with_offset(to_element, x, y)
mouse.move_to_element_with_offset() <-- 传入一个对象(to_element), 两个参数(x, y) 在对象内偏移量并点击
-
拖动: drag_and_drop() <–将一个元素拖动到另一个元素的位置
mouse.drag_and_drop() <-- 接收两个参数对象, 将第一个对象拖到第二个对象的位置
-
鼠标悬停: move_to_element() <–将光标移动动指定标签的位置
mouse.move_to_element() <-- 接收一个参数对象, 将光标移动到该对象的位置
-
释放动作: release()
mouse.release() <-- 释放当前的动作
-
立即执行动作: perform()
perform() <-- 配合执行动作使用, 表示执行当前的动作
例: mouse.move_to_element().perform()
from selenium.webdriver import Chrome
import time
# 导入动作链对应的类
from selenium.webdriver import ActionChains
driver = Chrome("E:\\driver\\chromedriver")
driver.get("https://detail.1688.com/offer/524426612853.html")
slider = driver.find_element_by_id("nc_1_n1z")
# 实例化一个动作链对象
action = ActionChains(driver)
# 点击长按指定的标签
action.click_and_hold(slider)
# 滑动标签
for i in range(1, 5):
# 横向滑动25个像素, 并立即执行
action.move_by_offset(25,0).perform()
time.sleep(0.3)
# 指定区域内点击
Ve_code = driver.find_element_by_id("") # 指定元素
x = width # 指定宽度
y = height # 指定高度
mouse.move_to_element_with_offset(Ve_code, x, y).click().perform()
# 释放动作
action.release()
键盘动作
Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, send_keys()方法可以用来模拟键盘输入, 除此 之外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等。
from selenium.webdriver.common.keys import Keys <-- 导入 Keys 类
- send_keys(Keys.BACK_SPACE) 退格键
search_input.send_keys(Keys.BACK_SPACE) <-- 删除前一个内容
- send_keys(Keys.SPACE) 空格键
search_input.send_keys(Keys.SPACE) <-- 输入空格
- send_keys(Keys.TAB) 制表键
search_input.send_keys(Keys.TAB) <-- 制表符
- send_keys(Keys.ESCAPE) 回退键
search_input.send_keys(Keys.ESCAPE) <-- 键盘上的 Esc
- send_keys(Keys.ENTER) 回车键
search_input.send_keys(Keys.ENTER) <-- 回车键
- send_keys(Keys.CONTROL,‘a’) 全选
search_input.send_keys(Keys.CONTROL, “a”) <-- ctrl+a 全选
- send_keys(Keys.CONTROL,‘c’) 复制
search_input.send_keys(Keys.CONTROL, “c”) <-- ctrl+c 复制
- send_keys(Keys.CONTROL,‘x’) 剪切
search_input.send_keys(Keys.CONTROL, “x”) <-- ctrl+x 复制
- send_keys(Keys.CONTROL,‘v’) 粘贴
search_input.send_keys(Keys.CONTROL, “v”) <-- ctrl+v 粘贴
- send_keys(Keys.F1) 键盘 F1-F12(方法类似)
search_input.send_keys(Keys.F1) <-- 键盘 F1
iframe
在原有的框架中创建包含另外一个文档的内联框架
如果定位的标签存在于 iframe 标签中, 则不能直接定位到该标签, 需要切换浏览器标签定位的作用域
- 切换iframe: switch_to_frame()
driver.switch_to_frame() <-- 切换工作域, 默认支持接收 id 和 name 的属性值
- 释放iframe: switch_to_default_content()
driver.switch_to_default_content() <-- 释放当前的工作域
iframe的切换是默认支持 id 和 name的, 如果两个属性值都为空可以先定位到iframe的标签, 在将返回结果作为参数传入
from selenium.webdriver import Chrome
driver = Chrome("E:\\driver\\chromedriver")
driver.get("www.baidu.com") # 这里没有找到合适的网页, 所以临时用百度充当一下
# 切换作用域
driver.switch_to_frame("kw")
# 定位iframe标签切换
frame = driver.find_element_by_tag_name("iframe")
driver.switch_to_frame(frame)
# 释放iframe
driver.switch_to_default_content()
等待方式
加入等待时间,主要是考虑到网页加载需要时间,可能由于网速慢,或者使用了 ajax 技术实现了异步加载等,如果程序找不到指定的页面元素,就会导致报错发生。
强制等待 : time.sleep()
使用 Python 自身的库 time.sleep() 可以实现强制等待。
强制等待使用简单,但是,当网络条件良好的时候,建议减少使用,因为如果频繁使用强制等待的方式等待元素加载,会导致整个项目的自动化时间延长。
这种等待方式的使用场景主要是脚本调试。
time.sleep() <-- 指定程序休眠的时间
隐式等待 : implicitly_wait()
隐式等待实际上是,设置了一个最长的等待时间,如果在规定时间内网页加载完成, 则直接执行下一步, 如果到达设定的时间, 则抛出异常
driver.implicitly_wait() <-- 指定隐式等待时间
隐式等待设置一次,对整个 driver 周期都能够起作用,所以,在最开始设置一次即可。
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) 设置隐式等待时间 10秒
显性等待 : WebDriverWait()
显性等待, WebDriverWait, 配合该类的until()和until_not()方法, 根据判断条件进行等待, 在规定时间内, 直到某个条件符合或不符合才会继续执行, 超出时间则抛出异常
具体参数和理论请参照 : https://blog.csdn.net/fenqi1989/article/details/107827793?
from selenium.webdriver import Chrome
# 导入模块 By, WebDriverWait, expocted_condtions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
driver = Chrome("E:\\driver\\chromedriver.exe")
driver.get("https://www.baidu.com")
button = WebDriverWait(driver, 20, 0.5).until(EC.visibility_of_element_located((By.XPATH, "//*[@id='s-hotsearch-wrapper']/div/a[1]/div")))
button.click()
sleep(3)
driver.quit()
WebDriverWait(driver, 20, 0.5).until(
EC.visibility_of_element_located(
(By.XPATH, "//*[@id='s-hotsearch-wrapper']/div/a[1]/div")
)
)
直到 XPATH 定位的元素出现在页面且可以被定位才会继续向下执行
当我们在程序只使用一个显性等待时, 那么网页的加载就会停留在我们要定位的元素上, 之后的内容不会加载出来, 这时如果程序中有需要的内容未被加载则会报错, 此时需要显性等待和隐形等待一起使用, 但要注意的是: 最长的等待时间取决于两者之间的大者, 如果隐性等待时间>显性等待时间, 则该句代码的最长等待时间等于隐性等待时间
警告框
在WebDriver中处理JavaScript所生成的alert、confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用text/accept/dismiss/ send_keys等方法进行操作。
消息框类型
-
alert 警告消息框
警告消息框提供了一个"确定"按钮让用户关闭该消息框 并且该消息框是模式对话框 也就是说用户必须先关闭该消息框然后才能继续进行操作。
-
confirm 确认消息框
确认消息框向用户提示一个"是与否"问题 用户可以根据选择"确定"按钮和"取消"按钮。
-
prompt 提示消息对话
提示消息框提供了一个文本字段 用户可以在此字段输入一个答案来响应您的提示 该消息框有一个"确定"按钮和一个"取消"按钮 选择"确认"会响应对应的提示信息,选择"取消"会关闭对话框。
接收消息框方法及属性
selenium 中提供了 switch_to_alert() 用来接收消息框
driver.switch_to_alert() <–接收网页的消息框, 并返回一个消息框对象
-
text 返回消息框中的文字信息
driver.switch_to_alert().text <-- 返回消息框中的文本内容
-
accept() 接受现有警告框, 即点击确认
driver.switch_to_alert().accept() <-- 点击消息框的确认按钮
-
dismiss() 解散现有警告框, 即点击取消
driver.switch_to_alert().dismiss() <-- 点击消息框中的取消按钮
-
send_keys() 发送文本至警告框
driver.switch_to_alert().send_keys() <-- 传入内容到文本框中
具体详细内容及理论知识请参照:https://blog.csdn.net/w68688686/article/details/103989052
cookie操作
- get_cookies() 获得所有的cookie信息
driver.get_cookies() <–以列表的形式 返回所有的cookie信息
- get_cookie(name) 返回key为"name"的cookie信息
driver.get_cookie(“name”) <–返回key值为name的信息
- add_cookie() 添加cookie
driver.add_cookie() <–添加cookie, 传入的参数是一个字典对象, 必须有name和value值
- delete_cookie() 删除cookie
driver.delete_cookie(name, optionsString) <–删除cookie信息, name是要删除的cookie的名称,
“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”。
- delete_all_cookies() 删除所有cookie信息
driver.delete_all_cookies() <–删除所有cookie的信息