参考:https://cloud.tencent.com/developer/article/1722974
selenium介绍
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
中文参考文档:https://www.selenium.dev/zh-cn/documentation/webdriver/getting_started/
环境准备
selenium 安装
1 | pip install selenium -i https://mirrors.aliyun.com/pypi/simple/ |
chrome driver下载
最新版本地址:https://googlechromelabs.github.io/chrome-for-testing/
历史版本地址:https://sites.google.com/chromium.org/driver/downloads
- 首先查看chrome浏览器版本:(浏览器设置 -> 关于chrome)

- 下载对应版本后,解压并运行exe程序即可。默认启动端口9515
使用
使用示例
1 | from selenium import webdriver |
浏览器创建
Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS。
1 | from selenium import webdriver |
元素定位
webdriver 提供了一系列的元素定位方法,常用的有以下几种:
| 定位一个元素 | 定位多个元素 | 含义 |
|---|---|---|
| find_element_by_id | find_elements_by_id | 通过元素id定位 |
| find_element_by_name | find_elements_by_name | 通过元素name定位 |
| find_element_by_xpath | find_elements_by_xpath | 通过xpath表达式定位 |
| find_element_by_link_text | find_elements_by_link_tex | 通过完整超链接定位 |
| find_element_by_partial_link_text | find_elements_by_partial_link_text | 通过部分链接定位 |
| find_element_by_tag_name | find_elements_by_tag_name | 通过标签定位 |
| find_element_by_class_name | find_elements_by_class_name | 通过类名进行定位 |
| find_elements_by_css_selector | find_elements_by_css_selector | 通过css选择器进行定位 |
注意:
1、find_element_by_xxx找的是第一个符合条件的标签,find_elements_by_xxx找的是所有符合条件的标签。
2、根据ID、CSS选择器和XPath获取,它们返回的结果完全一致。
3、另外,Selenium还提供了通用方法find_element(),它需要传入两个参数:查找方式By和值。实际上,它就是find_element_by_id()这种方法的通用函数版本,比如find_element_by_id(id)就等价于find_element(By.ID, id),二者得到的结果完全一致。
实例演示
假如有一个web页面,通过前端工具查看到一个元素的属性是这样的。
1 | <html> |
通过id定位:
1 | dr.find_element_by_id("kw") |
通过name定位:
1 | dr.find_element_by_name("wd") |
通过class name定位:
1 | dr.find_element_by_class_name("s_ipt") |
通过tag name定位:
1 | dr.find_element_by_tag_name("input") |
通过Xpath定位:
当使用 Selenium 进行自动化测试时,XPath 是一种非常有用的工具,它可以帮助我们在 HTML 或 XML 文档中找到特定的元素或节点。XPath 使用路径表达式来选择节点或元素,类似于文件系统中的路径,以下是些常用的写法
1 | dr.find_element_by_xpath("//*[@]") |
常规情况下,我们可以通过浏览器的开发者工具,进行Copy Xpath,但我们还需要学习下它其他的编写语法
选取元素
使用元素名称来选取元素,例如:
1 | //div # 选取所有 <div> 元素 |
选取属性
使用 @ 符号来选取元素的属性,例如:
1 | //input[@name='username'] # 选取 name 属性为 'username' 的 <input> 元素 |
选取子元素
使用 / 符号来选取元素的子元素,例如:
1 | //div/p # 选取所有 <div> 元素的子元素 <p> |
选取父元素
使用 .. 来选取元素的父元素,例如:
1 | //input[@name='username']/.. |
选取文本内容
使用 text() 来选取元素的文本内容,例如:
1 | //h1/text() # 选取所有 <h1> 元素的文本内容 |
选取包含特定文本的元素
使用 contains() 来选取包含特定文本的元素,例如:
1 | //div[contains(text(),'登录')] # 选取所有包含文本 '登录' 的 <div> 元素 |
选取位置
使用方括号 [] 来选取位置,例如:
1 | //ul/li[1] # 选取所有 <ul> 元素的第一个 <li> 子元素 |
使用索引选择符合条件的第n个,例如
1 | # 选取所有 符合条件的<ul>元素的第二个 |
这些是 XPath 的一些基本语法,可以用于定位 HTML 或 XML 文档中的元素或节点。需要注意的是,XPath 语法非常灵活,可以根据具体需求进行组合和定制。
查找当前节点之后的所有同级节点
- following
following关键字用于查找当前节点之后的所有同级节点。以下是使用following的基本语法:
1 | # 格式 |
例如,假设有以下XML文档:
1 | <bookstore> |
如果要查找第一个<book>元素之后的所有同级元素,可以使用以下XPath表达式:
1 | /bookstore/book[1]/following::book |
这将返回第二个和第三个<book>元素。
- following-sibling
following-sibling是一个关键字,用于查找当前节点之后的所有同级节点。与following不同的是,following-sibling只查找当前节点之后的同级节点,而不包括后代节点。
以下是使用following-sibling的基本语法:
1 | <xpath expression>/following-sibling::<node name> |
其中,<xpath expression>是要查找的起始节点,<node name>是要查找的同级节点的名称。
例如,假设有以下XML文档:
1 | <bookstore> |
如果要查找第一个<book>元素之后的所有同级元素,可以使用以下XPath表达式:
1 | /bookstore/book[1]/following-sibling::book |
这将返回第二个和第三个<book>元素,因为这两个元素是第一个<book>元素之后的同级元素。注意,这个表达式不会返回第一个<book>元素本身,因为following-sibling只查找当前节点之后的同级节点。
多个条件
在XPath中,可以使用逻辑运算符和多个谓语来同时指定多个条件。
下面是一些常用的逻辑运算符:
and: 与运算符,用于同时满足多个条件,例如://div[@class="foo" and @id="bar"]表示同时匹配class属性为foo和id属性为bar的div元素。or: 或运算符,用于满足多个条件中的任意一个,例如://div[@class="foo" or @class="bar"]表示匹配class属性为foo或bar的div元素。not: 非运算符,用于匹配不满足指定条件的元素,例如://div[not(@class="foo")]表示匹配class属性不为foo的div元素。
多个谓语可以在一个XPath表达式中使用方括号[]来连接,例如:
1 | //div[@class="foo"][position()<3]/a[text()="click"] |
上述XPath表达式表示匹配class属性为foo且在父元素中的位置小于3的div元素下的文本为click的a元素。
选取不包含某属性的标签
排除一个属性
1 | //tbody/tr[not(@class)] |
排除一个或者多个属性
1 | //tbody/tr[not(@class or @id)] |
通过css定位:
css定位有N种写法,这里列几个常用写法:
1 | dr.find_element_by_css_selector("#kw") |
假如页面上有如下一组文本链接
1 | <a href="http://news.baidu.com" rel="external nofollow" name="tj_trnews" 新闻</a |
通过link text定位:
1 | dr.find_element_by_link_text("新闻") |
通过partial link text定位:
1 | dr.find_element_by_partial_link_text("新") |
操作浏览器行为
常用的控制浏览器操作的一些方法
| 方法 | 说明 |
|---|---|
| set_window_size() | 设置浏览器的大小 |
| back() | 控制浏览器后退 |
| forward() | 控制浏览器前进 |
| refresh() | 刷新当前页面 |
| clear() | 清除文本 |
| send_keys (value) | 模拟按键输入 |
| click() | 单击元素 |
| submit() | 用于提交表单 |
| get_attribute(name) | 获取元素属性值 |
| is_displayed() | 设置该元素是否用户可见 |
| size | 返回元素的尺寸 |
| text | 获取元素的文本 |
示例
1 | from selenium import webdriver |
调用JavaScript代码
虽然WebDriver提供了操作浏览器的前进和后退方法,但对于浏览器滚动条并没有提供相应的操作方法。在这种情况下,就可以借助JavaScript来控制浏览器的滚动条。WebDriver提供了execute_script()方法来执行JavaScript代码。
用于调整浏览器滚动条位置的JavaScript代码如下:
1 | <!-- window.scrollTo(左边距,上边距); --> |
示例
1 | from selenium import webdriver |
解决element click intercepted问题
一般element click intercepted问题都是在click行为期间发生的,是因为所点击元素被隐藏导致
解决该问题可以调用js来替代click方法
1 | ele = driver.find_element_by_id('kw') |
获取页面源码数据
通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。
示例
1 | from selenium import webdriver |
cookie操作
有时候我们需要验证浏览器中cookie是否正确,因为基于真实cookie的测试是无法通过白盒和集成测试进行的。WebDriver提供了操作Cookie的相关方法,可以读取、添加和删除cookie信息。
WebDriver操作cookie的方法:
| 方法 | 说明 |
|---|---|
| get_cookies() | 获得所有cookie信息 |
| get_cookie(name) | 返回字典的key为“name”的cookie信息 |
| add_cookie(cookie_dict) | 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值 |
| delete_cookie(name,optionsString) | 删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域” |
| delete_all_cookies() | 删除所有cookie信息 |
示例
1 | from selenium import webdriver |
谷歌无头浏览器
PhantomJs已停止维护更新,这里使用谷歌的无头浏览器,是一款无界面的谷歌浏览器。很多时候我们爬取数据,并不想打开一个浏览器窗口进行操作,我们只需要获取数据或者拿到cookie然后进行操作。
示例
1 | from selenium import webdriver |
selenium规避被检测识别
现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined。而使用selenium访问则该值为true。那么如何解决这个问题呢?
只需要设置Chromedriver的启动参数即可解决问题。在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:
示例
1 | from selenium import webdriver |
其他“奇技淫巧”
导包
1 | from selenium import webdriver |
获取某元素上方50像素的位置,然后点击
1 | # 通过XPath定位到页面上文本内容为"注意事项"的div元素,并赋值给elem变量。 |
上述脚本存在一个问题:定位元素使用了绝对偏移坐标,重复执行时就可能导致点击位置超出元素范围。如果是希望点击举例指定元素的某个位置,可以进行如下修改:
每次获取元素位置时,都调用 location_once_scrolled_into_view,确保获取的是最新位置。
点击位置使用元素相对偏移,而不是绝对坐标偏移。
1 | elem = driver.find_element_by_xpath("//div[text()='注意事项']") |
获取屏幕向下300的位置,然后点击
1 | # 计算目标位置坐标 |
ElementClickInterceptedException
当使用
driver.find_element(xxx).click()进行元素点击操作时,报错:ElementClickInterceptedException,可使用如下方式替代
1 | driver.execute_script("arguments[0].click();", driver.find_element(xxx)) |
Selenium Grid
介绍
Selenium 测试的主要组成部分有:测试代码、WebDriver、Grid(Selenium Server,非必需)、浏览器驱动(Driver)和浏览器。
当我们编写完 Selenium 测试用例在本地调试时,WebDriver 通过浏览器驱动直接与浏览器进行交互。这时,WebDriver、浏览器驱动和浏览器位于同一主机。这种最基本的交互方式如下图所示。

本地调试完成,使用自动化流水线触发执行测试用例时,一般不会使用上述这种 WebDriver 与浏览器(驱动)直接交互的方式,而会选择远程交互的方式。
远程交互方式是指 WebDriver 通过 Grid(Selenium Server)来与浏览器(驱动)远程交互。这时,Grid 可以不与浏览器及其驱动位于同一主机,测试代码及 WebDriver 也可以不与 Grid 或浏览器位于同一主机。这种远程交互的方式如下图所示。

可以看到,使用 Grid 以后,测试用例只需知道 Grid 的地址即可,无需安装浏览器及驱动,使得测试用例的执行变得非常简单。
安装
参考:https://github.com/SeleniumHQ/docker-selenium/tree/3.141.59-zirconium
docker-compose.yml:https://github.com/behappy-project/behappy-test-automation/blob/main/selenium.yml
注:selenium grid 4.0+版本改动很大,此安装版本以3.141为主
VNC Viewer
安装好的node-chrome-debug自带vnc server,所以这里使用vnc viewer监听其5900端口进行远程监控,默认连接密码是secret
地址:https://www.realvnc.com/en/connect/download/viewer/
安装好的vnc默认4个workspace,在测试时会交替执行,这里可以删除其它无用的workspace

Selenium IDE
Selenium介绍
Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。Selenium家庭成员有三个,分别是Selenium WebDriver、Selenium IDE和Selenium Grid,这篇博客主要介绍Selenium IDE的使用方法。Selenium官网地址

Selenium IDE介绍
Selenium IDE是Chrome和FireFox浏览器中的插件,Selenium IDE结合浏览器提供脚本录制、脚本回放、脚本编辑、元素定位等功能,使用Selenium IDE可以将录制的脚本生成相应单元测试框架的自动化测试脚本,录制脚本支持导出Python pytest、Java JUnit、 NUnit等格式
Selenium IDE安装
Chrome浏览器安装
官网下载地址:点击进入,通过浏览器安装如下图,此方式不FQ无法进入页面

推荐使用此网站下载Chrome的插件,下载后解压zip压缩包,将selenium-ide.crx拖至Chrome拓展程序页面,等弹窗出现点击【添加】即可

FireFox浏览器安装
无需FQ,通过浏览器直接安装即可

Selenium IDE使用
Chrome和FireFox浏览器插件安装成功后,使用方法都是一样的,此处示例使用的是Chrome浏览器
点击浏览器菜单栏中的Selenium IDE图标,进入初始界面

Selenium IDE 窗口功能介绍

举个栗子:点击【Record a new test in a new project】,输入项目名称点击【OK】,输入URL地址点击【START RECORDING】,开始录制,自动打开界面,在界面进行操作后关闭窗口,点击录制停止按钮,输入用例标题点击【OK】,一条用例录制完成,如下图

导出用例
选中要导出的用例,点击鼠标右键→【Export】,选择要导出的格式,点击【Export】

导出测试套件也是相同的方法,先选择【Test Suites】,选择要导出的测试套件,点击鼠标右键→【Export】,选择要导出的格式,点击【Export】即可
以下是导出的上图中的用例代码
1 | # Generated by Selenium IDE |
通过PyCharm运行以上代码,需要先配置好环境
① 安装pytest,点击【File】→【Settings】→【Project:xxx.py】→【Python:Interpreter】点击添加按钮【+】,搜索pytest,选择安装包,点击【Install Package】,若还缺少其它包,通过此方法添加即可
② 已配置好WebDriver,ChromeDriver或者FireFoxDriver,具体依据所选浏览器,以ChromeDriver为例,配置方法请查看此文章
③ 在代码后添加main函数,如下:
1 | if __name__ == '__main__': |
或者在Terminal中使用命令运行,如下:
1 | python -m pytest test_case.py |
通过PyCharm运行导出的用例,结果如下图,PyCharm中会显示测试结果

Selenium IDE其它操作

Selenium IDE有助于更深层次的学习Selenium,初学时期可以使用此工具,随着技能的提升,后续应自己多写测试脚本