Selenium
0x01 原理与安装
(1)原理
Selenium 是一套 Web 网站的程序自动化操作解决方案
由此,编写自动化程序需要使用客户端库,当需要模拟用户点击界面的按钮,就会发送点击元素的请求给浏览器驱动,之后浏览器驱动向浏览器转发请求,其中的请求满足 HTTP。该流程中的客户端库由 Selenium 组织提供。
Selenium 自动化流程如下:
- 自动化程序调用 Selenium 客户端库函数
- 客户端库会发送 Selenium 命令给浏览器的驱动程序
- 浏览器驱动程序接收到命令后驱动浏览器去执行命令
- 浏览器执行命令
- 浏览器驱动程序获取命令执行的结果,返回给自动化程序
- 自动化程序对返回结果进行处理
(2)安装
-
安装客户端库
以 Python 语言举例
执行命令
pip install selenium
安装 -
安装浏览器驱动
Chrome 浏览器驱动下载链接
Edge 浏览器驱动下载链接注意:浏览器驱动的版本尽量与浏览器版本一致
以下全部操作以 Chrome 环境为例
(3)简单实例:自动打开 Chrome 并进入百度
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# 创建 WebDriver 对象,指明使用 Chrome 浏览器驱动
wd = webdriver.Chrome(service=Service(r'../venv/Scripts/chromedriver.exe'))
# 调用 WebDriver 对象的 get 方法,可以让浏览器打开指定网址
wd.get('https://www.baidu.com')
# 运行后暂停
os.system("pause")
(4)常见问题
-
关闭 chromedriver 日志
from selenium import webdriver # 添加参数,禁止 chromedriver 日志写屏 options = webdriver.ChromeOptions() options.add_experimental_option('excludeSwitched', ['enable-logging']) # 这里指定 options 参数 wd = webdriver.Chrome(options=options)
-
浏览器首页显示防病毒重置设置
- 在运行窗口(win+R)输入
regedit
并运行 - 找到
HKEY_CURRENT_USER\Software\Google\Chrome
- 删除其
TriggeredReset
子项 - 关闭注册表编辑器
- 在运行窗口(win+R)输入
0x02 选择元素
(1)选择元素的方法
在网页中开启控制台:F12 或 Ctrl+Shift+I
(2)根据 id 选择
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://www.baidu.com/')
# 根据 id 选择元素,返回的就是该元素的 WebElement 对象
element = wd.find_element(By.ID, 'kw')
# 通过该 WebElement 对象,就可以对页面元素进行操作
element.send_keys('微信公众号认证\n')
os.system("pause")
- 当传入的 id 被判断为不存在时会抛出
selenium.common.exceptions.NoSuchElementException
异常 - 当 Selenium 的版本低于 4 时,可以使用
find_element_by_id('kw')
方法
将输入回车的方法进行搜索换为按按钮进行搜索:
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://www.baidu.com/')
# 根据 id 选择元素,返回的就是该元素的 WebElement 对象
element = wd.find_element(By.ID, 'kw')
# 通过该 WebElement 对象,就可以对页面元素进行操作
element.send_keys('微信公众号认证')
# 通过点击“百度一下”按钮进行搜索
element = wd.find_element(By.ID, 'su')
# 触发单击事件
element.click()
os.system("pause")
(3)根据 class 选择
find_elements_by_class_name('nav-search-input')
element
不加s
表示选择第一个class
为nav-search-input
的标签element
加s
表示选择所有class
为nav-search-input
的标签
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('http://www.moj.gov.cn/')
# 根据 class 选择元素,返回的就是该元素的 WebElement 对象
elements = wd.find_elements(By.CLASS_NAME, 'mainlevel')
for element in elements:
print(element.text)
os.system("pause")
当没有符合条件的元素出现时:
find_element
会抛出异常find_elements
会返回空列表
类似的可以通过
tag
名称、css
选择器进行选择:
find_element(By.TAG_NAME, 'input')
find_element(By.CSS_SELECTOR, 'button[type=submit]')
(4)选择延迟
程序运行速度超过浏览器加载速度时需要延迟程序
import time
time.sleep(1) # 单位为 秒
Selenium 内置了一个方法implicitly_wait()
,用于设置最大等待时长:
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('http://www.moj.gov.cn/')
wd.implicitly_wait(10)
elements = wd.find_elements(By.CLASS_NAME, 'mainlevel')
for element in elements:
print(element.text)
pass
0x03 操控元素
(1)点击
调用方法click()
,实际点击的位置是元素的中心点
(2)输入
调用方法send_keys()
,在方法中添加需要输入的字符串信息
调用方法clear()
,用于清除输入框已有的字符串
调用元素对象方法element.get_attribute('value')
,用于获取输入框已有的内容
(3)获取
-
文本
调用元素对象属性
element.text
特殊情况:当元素的文本内容没有或未完全展示在界面上,此时使用下述方法:
element.get_attribute("innerText")
element.get_attribute("textContent")
-
属性
调用元素对象方法
element.get_attribute('href')
整个元素对应的 HTML:
element.get_attribute('outerHTML')
某个元素内部的 HTML:
element.get_attribute('innerHTML')
0x04 CSS 表达式
省略 CSS 基础
方法find_elements(By.CSS_SELECTOR, 'xxx')
中,xxx
为 CSS 选择器参数
举例:采取 CSS 选择器选中 class 为 mainlevel 的标签
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('http://www.moj.gov.cn/')
wd.implicitly_wait(10)
# 设置 CSS 选择器选择类 mainlevel
elements = wd.find_elements(By.CSS_SELECTOR, '.mainlevel')
for element in elements:
print(element.text)
pass
0x05 frame 切换/窗口切换
(1)切换到 frame
对于一些网页中使用了<iframe></iframe>
标签,Selenium 在默认情况下无法进入该标签中被嵌入的另一份 HTML 文档,此时需要切换操作范围至被嵌入的文档中。
切换方法为 WebDriver 对象中的switch_to
属性:
wd.switch_to.frame(frame_reference)
其中,frame_reference
可以是frame
元素的属性name
或ID
wd.switch_to.frame('frame1')
wd.switch_to.frame('innerFrame')
当frame
元素没有设置属性name
和ID
时,可以通过 CSS 选择器或选取tag
的方法:
wd.switch_to.frame(wd.find_element(By.CSS_SELECTOR, '[src="xxx.html"]'))
wd.switch_to.frame(wd.find_element(By.TAG_NAME, 'iframe'))
当需要切换回主 HTML 时,使用wd.switch_to.default_content()
(2)浏览器窗口切换(多页面操作)
对于一些网页的<a></a>
标签设置了属性target="_blank"
,即在新窗口打开对应链接,此时 Selenium 不会主动进行窗口切换,可以使用 WebDriver 对象中的switch_to
属性:
wd.switch_to.window(handle)
其中,handle
窗口的句柄,句柄可以看作网页窗口的 ID。
考虑到当前浏览器中可能打开了多个窗口,可以通过以下方法找到并切换窗口:
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get('http://www.moj.gov.cn/pub/sfbgw/')
# 打开新窗口链接
element = wd.find_element(By.CLASS_NAME, 'sLinkItem_first')
element.click()
# 输出新窗口标题
print("1.", wd.title)
for handle in wd.window_handles:
# 先顺序进行窗口切换
wd.switch_to.window(handle)
# 通过标题判断是否为需要的窗口
if '中国政府网' in wd.title:
# 如果正确则跳出循环
break
# 在新窗口中进行操作
wd.implicitly_wait(10)
print("2.", wd.title)
element = wd.find_element(By.ID, 'mainlevel_02')
element.click()
os.system("pause")
当需要返回之前的网页时,有以下两种方法:
-
继续采取上述循环的方法找到相应的网页
-
记录该窗口的句柄并直接跳转
# 保存主窗口的句柄 mainWindow = wd.current_window_handle # ... # 通过记录的句柄切换回主窗口 wd.switch_to.window(mainWindow)
0x06 选择框
(1)radio 单选框
找到目标位置,直接模拟用户点击即可。
(2)checkbox 复选框
找到目标位置,必须首先确认当前复选框的状态,之后直接模拟用户点击即可。
确认当前复选框的状态有以下两种方法:
print(wd.find_elements(By.CSS_SELECTOR, 'input[type="checkbox"]').is_selected())
- True / False
print(wd.find_elements(By.CSS_SELECTOR, 'input[type="checkbox"]').get_attribute("checked"))
- true / None
全选方法:
elements = wd.find_elements(By.CSS_SELECTOR, 'input[type="checkbox"]')
for element in elements:
judge = element.is_selected()
print(judge)
if judge is False:
element.click()
(3)select 下拉框
对于 select 选择框,Selenium 提供了专门的 Select 类进行操作
# 导入 Select 类
from selenium.webdriver.support.ui import Select
# 创建 Select 对象
select = Select(element)
-
select.select_by_value(value)
根据选项的 value 属性值选择元素
-
select.select_by_index(index)
根据选项的次序值选择元素
-
select_by_visible_text(text)
根据选项的可见文本选择元素
-
deselect_by_value(value)
根据选项的 value 属性值去除元素
-
deselect_by_index(index)
根据选项的次序值去除元素
-
deselect_by_visible_text(text)
根据选项的可见文本去除元素
-
deselect_all()
去除所有元素
select 下拉选框通过是否设置
multiple
属性控制是否可以多选
单选:直接模拟用户点击操作即可
多选:先查看已选项,后进行选择操作
0x07 实战技巧
(1)更多操作
对于进行双击、右击、移动、悬停、拖拽等操作,Selenium 提供了ActionChains
类来实现,以鼠标移动举例:
import os
from selenium import webdriver
from selenium.webdriver.common.by import By
# 导入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChains
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get('https://www.baidu.com/')
ac = ActionChains(wd)
# 鼠标移动到元素上
ac.move_to_element(
wd.find_element(By.CSS_SELECTOR, '[name="tj_briicon"]')
).perform() # perform() 是执行上述鼠标移动操作的“启动器”
os.system("pause")
(2)冻结界面
用于解决无法查看鼠标悬停后触发的页面
setTimeout(function(){debugger}, 5000)
(3)弹出框操作
-
Alert,警告信息
只需点击确认即可
wd.switch_to.alert.accept()
当需要获取对话框中的信息时,使用
wd.switch_to.alert.text
即可 -
Confirm,确认信息
需要选择确认或取消
确认:
wd.switch_to.alert.accept()
取消:
wd.switch_to.alert.dismiss()
-
Prompt,提示输入
需要输入提交信息,可使用
# 输入信息 wd.switch_to.alert.send_keys(text) # 确认提交 wd.switch_to.alert.accept() # 取消提交 wd.switch_to.alert.dismiss()
-
非类 Alert 弹出框
根据 HTML 元素选择
0x08 Xpath 选择器
省略 Xpath 基础