Selenium (软件):修订间差异
(→检测与防检测) |
(→窗口和标签页) |
||
第289行: | 第289行: | ||
! Python示例 | ! Python示例 | ||
|- | |- | ||
| | | 当前窗口句柄 | ||
| | | 获得当前窗口的窗口句柄,返回一个字符串 | ||
| driver.current_window_handle | | driver.current_window_handle | ||
|- | |||
| 所有窗口句柄 | |||
| 获得所有窗窗口的窗口句柄,返回一个列表 | |||
| driver.window_handles | |||
|- | |- | ||
| 切换窗口或标签页 | | 切换窗口或标签页 | ||
| | | WebDriver没有当前活动窗口,要使用某个窗口需要使用<code>switch_to.window('窗口句柄')</code>切换。 | ||
| | | <syntaxhighlight lang="python" > | ||
from selenium import webdriver | |||
driver = webdriver.Firefox() | |||
driver.get("https://seleniumhq.github.io") | |||
# 存储原始窗口的 ID | |||
original_window = driver.current_window_handle | |||
# 单击在新窗口中打开的链接 | |||
driver.find_element(By.LINK_TEXT, "new window").click() | |||
# 等待浏览器加载完毕 | |||
driver.implicitly_wait(7) | |||
# 循环执行,直到找到一个新的窗口句柄 | |||
for window_handle in driver.window_handles: | |||
if window_handle != original_window: | |||
driver.switch_to.window(window_handle) | |||
break | |||
print(driver.title) | |||
</syntaxhighlight> | |||
|- | |- | ||
| 创建新窗口或新标签页,并且切换 | | 创建新窗口或新标签页,并且切换 | ||
| 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 + | | 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 + | ||
| | | <code>driver.switch_to.new_window('tab')</code> # 打开新标签页并切换到新标签页 <br /><code>driver.switch_to.new_window('window')</code> # 打开新标签页并切换到新标签页 | ||
|- | |- | ||
| 关闭窗口或标签页 | | 关闭窗口或标签页 | ||
第312行: | 第333行: | ||
{{了解更多|[https://www.selenium.dev/documentation/zh-cn/webdriver/browser_manipulation/ Selenium 文档:WebDriver - 操控浏览器]}} | {{了解更多 | ||
|[https://www.selenium.dev/zh-cn/documentation/webdriver/interactions/windows/ Selenium 文档:WebDriver - 同窗口和标签一起工作] | |||
|[https://www.selenium.dev/documentation/zh-cn/webdriver/browser_manipulation/ Selenium 文档:WebDriver - 操控浏览器]}} | |||
===使用Cookie=== | ===使用Cookie=== |
2023年4月9日 (日) 07:18的最新版本
Selenium 是一个Web应用测试的开源框架,提供一系列Web浏览器自动化工具,可以模拟用户与浏览器的交互。Selenium IDE是一个Firefox插件,使用图形界面录制和测试。也可以通过Selenium WebDriver,使用多种语言来编写测试,包括:Java、Python、C#、Ruby、JavaScript 和 Kotlin 。
简介
主要工具
以下为Selenium提供的主要工具:
Selenium WebDriver:
Selenium IDE:
Grid:
安装 Selenium
使用不同的语言,安装Selenium方式不同。
Python中可以使用 pip 安装Selenium:
pip install selenium
也可以下载源代码安装。
JavaScript中可以使用 npm 安装 :
npm install selenium-webdriver
了解更多 >> Selenium 文档:安装 Selenium 库
安装浏览器和浏览器驱动
浏览器 | 支持的操作系统 | 维护者 | 驱动 | 驱动下载 |
---|---|---|---|---|
Chromium/Chrome | Windows/macOS/Linux | 谷歌 | ChromeDriver | 下载 |
火狐 | Windows/macOS/Linux | Mozilla | geckodriver | 下载 |
Edge | Windows 10 | 微软 | msedgedriver | 下载 |
Internet Explorer | Windows | Selenium 项目组 | 下载 | |
Safari | macOS El Capitan 及更高版本 | 苹果 | 内置 | |
Opera | Windows/macOS/Linux | Opera | 下载 |
以Debian/Ubuntu下安装Chrome浏览器和ChromeDriver驱动为例:
#安装Chrome浏览器
#官网下载Chrome稳定版的deb包
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
#安装Chrome
sudo apt install ./google-chrome-stable_current_amd64.deb
#验证成功,查看chrome版本,结果如:Google Chrome 87.0.4280.88
google-chrome --version
#chromedriver驱动官网:https://chromedriver.storage.googleapis.com/index.html
#在官网查找下载chrome版本对应的chromedriver驱动。如Google Chrome 87.0.4280.88
wget https://chromedriver.storage.googleapis.com/87.0.4280.88/chromedriver_linux64.zip
#解压缩
unzip chromedriver_linux64.zip
#可以将chromedriver文件放置在环境变量路径(通过echo $PATH查看)上。
mv chromedriver /usr/bin
在命令行输入驱动名,验证是否添加成功。
chromedriver # chrome
geckodriver # firefox
检测安装成功
以Python语言示例:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('https://www.baidu.com')
如果不将驱动加入环境变量,需要在每次使用时,指定驱动路径。以Python使用为例:
# executable_path 在selenium 4 已弃用
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
s = Service(r'D:\geckodriver-v0.31.0-win6\geckodriver.exe')
driver = webdriver.Firefox(service=s)
driver.get('https://www.baidu.com')
常见错误:
加入环境变量后,在代码中还是显示找不到
重启编辑器即可。
了解更多 >> Selenium 文档:WebDriver > 驱动要求
快速入门
浏览器
名称 | 描述 | 示例 |
---|---|---|
Chrome | from selenium import webdriver
driver = webdriver.Chrome()
| |
firefox | from selenium import webdriver
driver = webdriver.Firefox()
| |
无头浏览器
以Python语言chrome示例:
from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox') #
chrome_options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(chrome_options=chrome_options) #如果chromedriver没有添加到环境变量中,就需要添加参数指明路径executable_path='/path/to/chromedriver'
driver.get("https://www.baidu.com")
print(driver.page_source)
driver.quit()
firefox示例:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
op = Options()
op.headless = True
driver = webdriver.Firefox(options=op)
driver.get(url)
print(driver.title)
driver.close()
下载文件
firefox示例:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
op = Options()
op.set_preference("browser.download.folderList",2)
op.set_preference("browser.download.manager.showWhenStarting", False)
op.set_preference("browser.download.dir",save_path) # 设置下载位置
op.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream")
op.headless = True # 设置无头模式
driver = webdriver.Firefox(options=op)
# 需要先在浏览器中设置该文件直接保存
driver.get(r'https://test.com/test.jpg')
driver.close()
浏览器设置
浏览器参数
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--headless') # 无头模式(无界面)
options.add_argument("--incognito") # 隐私模式
driver = webdriver.Chrome(options=options)
driver.get("https://www.baidu.com")
print(driver.page_source)
driver.quit()
一些常用参数:
参数名 | 描述 | 示例 |
---|---|---|
--headless |
无头模式(无界面) | options.add_argument('--headless')
|
--incognito |
隐私模式 | options.add_argument('--incognito')
|
--window-size |
浏览器窗口大小 | options.add_argument('--window-size=1920,1080')
|
--user-agent |
浏览器User Agent | options.add_argument('--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"')
|
--disable-extensions |
禁用扩展程序 | options.add_argument('--disable-extensions')
|
--disable-gpu |
禁用GPU加速 | options.add_argument('--disable-gpu')
|
--ignore-certificate-errors |
忽略证书错误 | options.add_argument('--ignore-certificate-errors')
|
--proxy-server |
设置代理服务器 | options.add_argument('--proxy-server=http://username:password@proxyserver:port')
|
浏览器操作
以下Python编程语言示例:
from selenium import webdriver
driver = webdriver.Chrome()
浏览器导航
操作 | 描述 | Python示例 |
---|---|---|
打开网站 | 浏览器输入地址,打开网站 | driver.get("https://www.baidu.com") |
获取当前 URL | 从浏览器的地址栏读取当前的 URL | driver.current_url |
后退 | 按下浏览器的后退按钮 | driver.back() |
前进 | 按下浏览器的前进键 | driver.back() |
刷新 | 刷新当前页面 | driver.refresh() |
获取标题 | 从浏览器中读取当前页面的标题 | driver.title |
窗口和标签页
WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。
操作 | 描述 | Python示例 |
---|---|---|
当前窗口句柄 | 获得当前窗口的窗口句柄,返回一个字符串 | driver.current_window_handle |
所有窗口句柄 | 获得所有窗窗口的窗口句柄,返回一个列表 | driver.window_handles |
切换窗口或标签页 | WebDriver没有当前活动窗口,要使用某个窗口需要使用switch_to.window('窗口句柄') 切换。
|
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("https://seleniumhq.github.io")
# 存储原始窗口的 ID
original_window = driver.current_window_handle
# 单击在新窗口中打开的链接
driver.find_element(By.LINK_TEXT, "new window").click()
# 等待浏览器加载完毕
driver.implicitly_wait(7)
# 循环执行,直到找到一个新的窗口句柄
for window_handle in driver.window_handles:
if window_handle != original_window:
driver.switch_to.window(window_handle)
break
print(driver.title)
|
创建新窗口或新标签页,并且切换 | 创建一个新窗口或标签页,屏幕焦点将聚焦在新窗口或标签在上。注意:该特性适用于Selenium 4 + | driver.switch_to.new_window('tab') # 打开新标签页并切换到新标签页 driver.switch_to.new_window('window') # 打开新标签页并切换到新标签页
|
关闭窗口或标签页 | 当你完成了一个窗口或标签页的工作时,_并且_它不是浏览器中最后一个打开的窗口或标签页时,你应该关闭它并切换回你之前使用的窗口。 | driver.close() |
退出浏览器 | 调用quit退出浏览器。退出将会关闭所有与 WebDriver 会话相关的窗口和选项卡,结束浏览器进程,结束后台驱动进程,通知 Selenium Grid 浏览器不再使用,以便可以由另一个会话使用 | driver.quit() |
使用Cookie
Cookie是从网站发送并存储在您的计算机中的一小段数据,主要用于识别用户并加载存储的信息。
名称 | 描述 | 示例 |
---|---|---|
添加Cookie add_cookie()
|
添加Cookie,然后手动或自动刷新浏览器。 driver.add_cookie({"name": "key", "value": "value"}) 获取cookie可以在浏览器Web开发者工具,或使用selenium函数获取。 |
cookie = {
'version':'1.1.0',
'username' : 'auser',
'impress':'df88568486969',
'fim': 'mikllf',
}
cookies = [{'name':k, 'value':v} for k,v in cookie.items()]
for item in cookies:
driver.add_cookie(item)
|
了解更多 >> Selenium 文档:使用 Cookie
元素
WebElement表示DOM元素。
查找元素
可以通过使用WebDriver实例从文档根节点进行搜索,或者在另一个WebElement下进行搜索来找到WebElement。
操作 | 方法 | 描述 | Python示例 |
---|---|---|---|
查找单个元素 | Find Element | 此方法用于查找元素并返回第一个匹配的单个WebElement引用。 | driver.find_element(By.NAME, "q") |
查找多个元素 | Find Elements | 与"Find Element"相似, 但返回的是匹配WebElement列表。要使用列表中的特定WebElement,您需要遍历元素列表以对选定元素执行操作。 | driver.find_elements(By.TAG_NAME, 'p') |
查找当前页面上下文中具有焦点的元素 | Active Element | 此方法用于追溯或查找当前页面上下文中具有焦点的DOM元素 | driver.switch_to.active_element |
WebDriver API提供了内置方法来查找基于不同属性的WebElement (例如ID, Name, Class, XPath, CSS选择器, 链接文本等)。以下使用查找单个元素Find Element示例,查找多个元素Find Elements同样适用。 Python版本的find_element_by_*
系列的方法,在新版本中以弃用
操作 | 描述 | Python 示例 |
---|---|---|
By ID | 通过ID查找元素。适用元素如:<div id="q">...</div>
|
driver.find_element(By.ID, "q") |
By Name | 通过Name查找元素。适用元素如:<input name="btnK">...</input>
|
driver.find_element(By.NAME, 'btnK') |
By Class Name | 通过Class Name查找元素。适用元素如:<p class="rk">...</p>
|
driver.find_element(By.CLASS_NAME, 'rk') |
By Tag Name | 通过标签名查找元素 | driver.find_element(By.TAG_NAME, "div") |
By Link Text | 通过链接文本查找元素 | driver.find_element(By.LINK_TEXT, "更多信息...") |
By Partial Link Text | 通过部分链接文本查找元素 | driver.find_element(By.PARTIAL_LINK_TEXT, "更多信") |
By CSS | 通过CSS选择器查找元素 | driver.find_element(By.CSS_SELECTOR, "h1") |
By XPath | 通过XPath查找元素。 | driver.find_element(By.XPATH, "//form[1]") |
元素属性和方法
操作 | 方法或属性 | 描述 | Python示例 |
---|---|---|---|
元素是否被启用或禁用 | is_enabled() | 此方法用于检查网页上连接的元素是否被启用或禁用. 返回一个布尔值, 如果在当前浏览上下文中启用了连接的元素, 则返回True; 否则返回false 。 | driver.find_element(By.NAME, 'btnK').is_enabled() |
元素是否被选中 | is_selected() | 此方法确定是否 已选择 引用的元素. 此方法广泛用于复选框, 单选按钮, 输入元素和选项元素.返回一个布尔值, 如果在当前浏览上下文中 已选择 引用的元素, 则返回 True, 否则返回 False。 | driver.find_element(By.CSS_SELECTOR, "input[type='checkbox']:first-of-type").is_selected() |
元素标签名 | tag_name | 获取元素的TagName(标签名)。 | driver.find_element(By.CSS_SELECTOR, "h1").tag_name |
元素的尺寸和坐标 | rect | 用于获取参考元素的尺寸和坐标,提取的数据主体包含以下详细信息:1.元素左上角的X轴位置,2.元素左上角的y轴位置,3.元素的高度,4.元素宽度 | driver.find_element(By.CSS_SELECTOR, "h1").rect |
元素CSS值 | value_of_css_property() | 获取当前浏览上下文中元素的特定计算样式属性的值。 | ddriver.findElement(By.LINK_TEXT, "More information...").value_of_css_property('color') |
获取元素文本 | text | 获取特定元素渲染后的文本 | driver.find_element(By.CSS_SELECTOR, "h1").text |
获取元素属性的值 | get_attribute() | element.get_attribute('href') 获取元素的href值 element.get_attribute('innerHTML') 获取元素的内部HTML代码 ele.get_atrribute("outerHTML") 获取元素的HTML代码
| |
获取元素属性的值 | get_property() | element.get_property('href')
|
选择列表元素
选择列表元素相比普通元素,提供了一系列方法,方便与<select> 元素进行交互。该类仅适用于用于 HTML 元素 select 和 option。
Python为例,点击某个选择列表的所有选项:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
driver = webdriver.Firefox()
driver.get('https://example.com')
select_element = driver.find_element(By.TAG_NAME, 'select')
select = Select(select_element)
for option in select.options:
print(option.text) # 打印选项文本
option.click() # 点击选项
以下是select元素类提供的特别方法,其他属性方法见同普通元素的属性方法如元素可见文本elem.text
,点击元素elem.click()
。
名称 | 描述 | 示例 |
---|---|---|
构建类 | 生成选择列表元素对象。定位 <select> 元素,然后使用Select()初始化一个Select 对象。Selenium 4.5 开始, 您无法针对禁用的 <select> 元素构建 Select 对象. | select_element = driver.find_element(By.NAME, 'selectomatic')
select = Select(select_element)
|
全部选项 | 获取 <select> 元素中所有选项列表 | select.options
|
所选中的选项列表 | 获取 <select> 元素中所选中的选项列表。对于单选列表,返回只包含一个元素的列表,对于复选列表则表示包含的零个或多个元素。 | select.all_selected_options
|
通过文本选择选项 | 根据其可见文本选择选项 | select.select_by_visible_text('2021年')
|
通过value值选择选项 | 根据其值属性选择选项 | select.select_by_value('2021')
|
通过序号值选择选项 | 根据其在列表中的位置选择选项 | select.select_by_index(3)
|
通过value值的disabled选择选项 | 具有 disabled 属性的选项可能无法被选择。Selenium v4.5 + 支持 | with pytest.raises(NotImplementedError):
select.select_by_value('disabled')
|
取消选择选项 | 只有复选类型的选择列表才能取消选择选项. 您可以对要选择的每个元素重复使用这些方法. | select.deselect_by_value('eggs')
|
了解更多 >> Selenium 文档: 使用选择列表元素
操作
键盘操作
键盘操作通过使用底层接口允许我们向web浏览器提供虚拟设备输入。以下示例为Python版,打开百度网页,在输入框输入”webdriver“并按回车键:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
# 打开百度页面
driver.get("http://www.baidu.com")
# 输入"webdriver"文本和输入"ENTER"按键
driver.find_element(By.ID, "kw").send_keys("webdriver" + Keys.ENTER)
# 查看页面代码
driver.page_source
名称 | 描述 | 示例 |
---|---|---|
键盘输入 sendKeys |
用于模拟键盘输入。 | |
按下按键 keyDown |
用于模拟按下辅助按键(CONTROL, SHIFT, ALT)的动作。 | |
按键弹起 keyUp |
用于模拟辅助按键(CONTROL, SHIFT, ALT)弹起或释放的操作。 | |
清除 clear |
用于清除可编辑元素的内容。 |
了解更多 >> Selenium 文档:WebDriver - Keyboard
鼠标操作
了解更多 >> Selenium 文档:Mouse actions
笔操作
滚轮操作
等待
网页加载有大量异步内容,某些元素可能在程序运行后才出现,导致查找时出现找不到。
名称 | 描述 | 示例 |
---|---|---|
显式等待 | 条件为假时一直尝试,条件真时继续执行。 | from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))
|
隐式等待 | WebDriver在查找元素时先等待设置的时间,默认时间为0,表示禁用。不要混合使用隐式和显式等待,这样做会导致不可预测的等待时间。 | from selenium import webdriver
driver = Firefox()
driver.implicitly_wait(10)
|
流畅等待 | 流畅等待实例定义了等待条件的最大时间量,以及检查条件的频率。用户可以配置等待来忽略等待时出现的特定类型的异常,例如在页面上搜索元素时出现的NoSuchElementException。 | from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
driver = Firefox()
driver.get("http://www.baidu.com")
wait = WebDriverWait(driver, timeout=10, poll_frequency=1, ignored_exceptions=[ElementNotVisibleException, ElementNotSelectableException])
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//div")))
|
了解更多 >> selenium 文档:等待
显式等待
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait(driver, timeout=10).until(lambda d: d.find_element(By.TAG_NAME,"p"))
每个语言的selenium都附带了一些常用的预期的条件,方便使用:
名称 | 描述 |
---|---|
invisibility_of_element_located() | 检查元素是否可见 |
presence_of_element_located() | 检查元素是否存在 |
示例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
# Selenium WebDriver 3.13+
with webdriver.Firefox() as driver:
wait = WebDriverWait(driver, 10)
driver.get("https://www.baidu.com")
driver.find_element(By.NAME, "wd").send_keys("hello world" + Keys.RETURN)
first_result = wait.until(EC.presence_of_element_located((By.ID, "1")))
print(first_result.text)
扩展
名称 | 描述 | 网站 |
---|---|---|
Selenium Wire | 支持Python,可以访问或修改浏览器发出的底层请求。 安装 pip install selenium-wire
|
https://github.com/wkeeling/selenium-wire |
检测与防检测
防检测
有些网站会使用js检测浏览器是否为webdriver,检测出来就会访问不正常,所以需要隐藏webdriver指纹特征。
方法 | 描述 |
---|---|
execute_cdp_cmd()隐藏指纹特征 | 先运行cdp命令清除webdriver,再浏览。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_argument("--incognito") # 可选,配置隐私模式
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator,"webdriver",{get: () => undefined})'
})
driver.get('https://www.baidu.com')
|
使用stealth.min.js隐藏指纹特征 | |
控制正在运行的浏览器 |
资源
官网
- 官网:https://www.selenium.dev
- 中文文档:https://www.selenium.dev/documentation/zh-cn/
- Github:https://github.com/SeleniumHQ/selenium
- PyPI:https://pypi.python.org/pypi/selenium
相关网站
- 维基百科:Selenium (software)
- MDN:WebDriver
- baijum/selenium python文档:https://selenium-python.readthedocs.io/index.html