当前位置: 首页 > news >正文

Selenium详细教程

参考资料:https://www.byhy.net/

文章目录

    • 一.Selenium介绍
      • 1.1 介绍
      • 1.2 自动化原理
      • 1.3 自动化流程
    • 二.环境配置
      • 2.1 浏览器驱动
      • 2.2 关闭驱动日志
    • 三.选择元素的基本方法
      • 1.根据id属性选择元素
      • 2.根据class属性选择元素
      • 3.根据tag选择元素
      • 4.通过WebElement选择对象
    • 四.等待界面元素出现
      • 4.1 等待过程会出现的问题
      • 4.2 解决方案
        • 1.睡觉
        • 2.implicitly_wait方法(隐式等待/全局等待)
    • 五.操控元素的基本方法
      • 5.1 点击元素
      • 5.2 输入框
      • 5.3 获取元素信息
        • 1.获取元素的文本内容
        • 2.获取元素属性
        • 3.获取整个元素对应的HTML
        • 4.获取输入框里的文字
    • 附录1:HTML标签大全
      • 列表标签
    • 六.CSS表达式(上)
      • 6.1 CSS selector语法原理
      • 6.2 根据tag名、id、class选择元素
        • 1.根据tag名选择元素
        • 2.根据id号选择元素
        • 3.根据class属性选择元素
      • 6.3 选择子元素和后代元素
      • 6.4 根据属性选择
      • 6.5 验证CSS Selector
    • 七.CSS表达式(下)
      • 7.1 组选择
      • 7.2 按次序选择子节点
        • 1.父元素的第n个子节点
        • 2.父元素的倒数第n个子节点
        • 3.父元素的第几个某类型的子节点
        • 4.父元素的倒数第几个某类型的子节点
        • 5.奇数节点和偶数节点
        • 6.兄弟节点选择
    • 七.frame切换/窗口切换
      • 7.1 主窗口和嵌入的窗口
      • 7.2 窗口切换
        • 1.切换回主窗口
        • 2.切换为新的窗口
        • 3. **新窗口操作**
        • 4. 回到原窗口
    • 八.选择框
      • 8.1 radio框
      • 8.2 checkbox框
      • 8.3 select框
    • 九.实战技巧
      • 9.1 ActionChains操作元素
      • 9.2 直接执行javascript
      • 9.3 冻结页面
      • 9.4 弹出对话框
        • Alert
        • Prompt
      • 9.5 其他技巧
        • 窗口大小
        • 窗口标题
        • 获取当前窗口URL地址
        • 截屏
        • 上传文件


一.Selenium介绍

1.1 介绍

Selenimu是目前主流的Web浏览器的自动化方案

用过他,我们可以写出自动化程序,像人一样在浏览器里操作Web网页,比如点击界面按钮,在文本框中输入文字等操作

而且也可以从web界面读取信息,如获取火车、汽车票务信息,招聘网站职位信息等等,然后用程序进行分析处理

1.2 自动化原理

image-20251029084429915

从上图可以看出:

我们写的自动化程序 需要使用 客户端库

我们程序的自动化请求都是通过这个库里面的编程接口发送给浏览器。

比如,我们要模拟用户点击界面按钮, 自动化程序里面就应该 调用客户端库相应的函数, 就会发送 点击元素 的请求给 下方的 浏览器驱动。 然后,浏览器驱动再转发这个请求给浏览器。

这个自动化程序发送给浏览器驱动的请求 是HTTP请求。

客户端库从哪里来的? 是Selenium组织提供的。

Selenium组织提供了多种 编程语言的Selenium客户端库, 包括 java,python,js, ruby等,方便不同编程语言的开发者使用。

我们只需要安装好客户端库,调用这些库,就可以发出自动化请求给浏览器咯。

浏览器驱动 也是一个独立的程序,是由浏览器厂商提供的, 不同的浏览器需要不同的浏览器驱动。 比如 Chrome浏览器和 火狐浏览器有 各自不同的驱动程序。

浏览器驱动接收到我们的自动化程序发送的界面操作请求后,会转发请求给浏览器, 让浏览器去执行对应的自动化操作。

浏览器执行完操作后,会将自动化的结果返回给浏览器驱动, 浏览器驱动再通过HTTP响应的消息返回给我们的自动化程序的客户端库。

自动化程序的客户端库 接收到响应后,将结果转化为 数据对象 返回给 我们的代码。

1.3 自动化流程

  1. 自动化程序调用Selenium客户端库函数
  2. 客户端库函数会发送Selenium命令给浏览器的驱动程序
  3. 浏览器驱动程序接受命令后,会驱动浏览器执行命令
  4. 浏览器执行命令
  5. 浏览器驱动程序获取命令执行的结果,返回自动化程序
  6. 自动化程序对返回结果进行处理

二.环境配置

2.1 浏览器驱动

  1. Edge驱动配置

    1. 自动安装

      from selenium import webdriverwd = webdriver.Edge() # 指定 Edge 浏览器,会自动下载驱动wd.get('https://www.byhy.net')input('按回车退出')
      
    2. 指定地址

      from selenium import webdriver# 指定驱动路径
      from selenium.webdriver.chrome.service import Service
      wd = webdriver.Chrome(service=Service(r"d:\tools\Edgedriver.exe"))wd.get('https://www.byhy.net')input('按回车退出')
      
      • wd = webdriver.Chrome():等号右边 返回的是 WebDriver 类型的对象,我们可以通过这个对象来操控浏览器,比如 打开网址、选择界面元素等。
      • wd.get(‘https://www.byhy.net’):执行上面这行代码时,自动化程序就发起了 打开百度网址的 请求消息 ,通过浏览器驱动, 给 Chrome浏览器
  2. Chrome 驱动配置

    1. 自动安装

      from selenium import webdriverwd = webdriver.Chrome() # 指定 Chrome 浏览器,会自动下载驱动wd.get('https://www.byhy.net')input('按回车退出')
      

2.2 关闭驱动日志

from selenium import webdriver# 加上参数,禁止 chromedriver 日志写屏
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])# 这里指定 options 参数
wd = webdriver.Chrome(options=options)
# wd = webdriver.Edge(options=options)用于Edge浏览器驱动

三.选择元素的基本方法

image-20251029095402512

如果我们想自动化输入 股票名称 ,怎么做呢?

这就是在网页中,操控界面元素。

web界面自动化,要操控元素,首先需要 选择 界面元素 ,或者说 定位 界面元素

就是 先告诉浏览器,你要操作 哪个 界面元素, 让它找到你要操作的界面元素。

我们必须要让浏览器 先找到元素,然后,才能操作元素


对应web自动化来说, 就是要告诉浏览器,你要操作的界面元素是什么。

那么,怎么告诉浏览器 呢?

方法就是:告诉浏览器,你要操作的这个 web 元素的 特征

就是告诉浏览器,这个元素它有什么与众不同的地方,可以让浏览器一下子找到它。

元素的特征怎么查看?

可以使用浏览器的 开发者工具栏 帮我们查看、选择 web 元素。

请大家用chrome浏览器访问百度,按F12后,点击下图箭头处的 Elements 标签,即可查看页面对应的HTML 元素

img

然后,再点击 最左边的图标,如下所示

img

之后,鼠标在界面上点击哪个元素,就可以查看 该元素对应的html标签 了。

比如,前面的图的高亮处,就是百度搜索输入框 对应的 input元素。

1.根据id属性选择元素

img

页面上有个输入股票名称的输入框,使用鼠标右键菜单 查看该 input元素,会发现它有一个属性叫id。

我们可以把 id 想象成元素的编号, 是用来在html中标记该元素的。

根据规范, 如果元素有id属性 ,这个id 必须是当前html中唯一的。

所以如果元素有id, 根据id选择元素是最简单高效的方式。

这里,股票名称输入框 元素的 id值为 kw

Eg.

下面的代码,可以自动化在浏览器中 访问我们的股票搜索网站,并且在输入框中搜索 通讯

from selenium import webdriver
from selenium.webdriver.common.by import By# 创建 WebDriver 对象
wd = webdriver.Chrome()# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.byhy.net/cdn2/files/selenium/stock1.html')# 根据id选择元素,返回的就是该元素对应的WebElement对象
element = wd.find_element(By.ID, 'kw')# 通过该 WebElement对象,就可以对页面元素进行操作了
# 比如输入字符串到 这个 输入框里
element.send_keys('通讯\n')
# **注意,这里的`\n`模拟了click**
input('按回车退出')
  • wd.find_element(By.ID, ‘kw’):使用了 WebDriver 对象 的方法 find_element。这行代码运行是,就会发起一个请求通过 浏览器驱动 转发给浏览器,告诉它,需要选择一个id为 kw 的元素。浏览器 找到id为kw的元素后,将结果通过 浏览器驱动 返回给 自动化程序, 所以 find_element 方法会 返回一个 WebElement 类型的对象。这个WebElement 对象可以看成是对应 页面元素 的遥控器。我们通过这个WebElement对象,就可以 操控 对应的界面元素

  • 用遥控器调用这个对象的 send_keys 方法就可以在对应的元素中 输入字符串。注意,这里的\n模拟了click,扮演了回车的作用

  • 用遥控器调用这个对象的 click 方法就可以 点击 该元素。

  • Selenium 升级到版本 4 以后,所以现在都要写成下面这种格式

    from selenium.webdriver.common.by import By# 初始化代码 ....wd.find_element(By.ID, 'username').send_keys('byhy')
    wd.find_element(By.CLASS_NAME, 'password').send_keys('sdfsdf')
    wd.find_element(By.TAG_NAME, 'input').send_keys('sdfsdf')
    wd.find_element(By.CSS_SELECTOR,'button[type=submit]').click()
    

2.根据class属性选择元素

web自动化的难点和重点之一,就是如何 选择 我们想要操作的web页面元素。

除了根据元素的id ,我们还可以根据元素的 class 属性选择元素。

就像一个 学生张三 可以定义类型为 中国人 或者 学生一样, 中国人 和 学生 都是 张三 的 类型。

元素也有类型, class 属性就用来标志着元素 类型

网址:白月黑羽测试网页1

image-20251029101814171

这个网址对应的html内容 有如下的部分

    <body><div class="plant"><span>土豆</span></div><div class="plant"><span>洋葱</span></div><div class="plant"><span>白菜</span></div><div class="animal"><span>狮子</span></div><div class="animal"><span>老虎</span></div><div class="animal"><span>山羊</span></div></body>

所有的植物元素都有个class属性 值为 plant。

所有的动物元素都有个class属性 值为 animal。

如果我们要选择 所有的 动物, 就像下面可以这样写,

wd.find_elements(By.CLASS_NAME,'animal') #注意element后面多了个s
find_elements 方法 —— 这是 WebElement 类自带的核心功能,用于在当前元素的 “内部范围” 查找子元素。

注意

find_elements 返回的是找到的符合条件的 所有 元素 (这里有3个元素), 放在一个 列表 中返回。

而如果我们使用 wd.find_element (注意少了一个s) 方法, 就只会返回 第一个 元素。

Eg.

取出网页中所有属性为animal的元素并打印

from selenium import webdriver
from selenium.webdriver.common.by import By# 创建 WebDriver 实例对象,指明使用chrome浏览器驱动
wd = webdriver.Chrome()# WebDriver 实例对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.byhy.net/cdn2/files/selenium/sample1.html')# 根据 class name 选择元素,返回的是 一个列表
# 里面 都是class 属性值为 animal的元素对应的 WebElement对象
elements = wd.find_elements(By.CLASS_NAME, 'animal')# 取出列表中的每个 WebElement对象,打印出其text属性的值
# text属性就是该 WebElement对象对应的元素在网页中的文本内容
for element in elements:print(element.text)input('按回车退出')
  • 通过 WebElement 对象的 text属性 可以获取该元素 在网页中的文本内容。

    所以 下面的代码,可以打印出 element 对应 网页元素的 文本

    print(element.text)
    

就像一个 学生张三 可以定义有 多个 类型: 中国人 和 学生 , 中国人 和 学生 都是 张三 的 类型。

元素也可以有 多个class类型 ,多就像一个 学生张三 可以定义有 多个 类型: 中国人 和 学生 , 中国人 和 学生 都是 张三 的 类型。

元素也可以有 多个class类型 ,多个class类型的值之间用 空格 隔开,比如个class类型的值之间用 空格 隔开,比如

<span class="chinese student">张三</span>
<--!
注意,这里 span元素 有两个class属性,分别  chinese  student, 而不是一个 名为 chinese student 的属性。
-->

我们要用代码选择这个元素,可以指定任意一个class 属性值,都可以选择到这个元素,如下

element = wd.find_elements(By.CLASS_NAME,'chinese')
element = wd.find_elements(By.CLASS_NAME,'student')
#但不能两个都写如下
element = wd.find_elements(By.CLASS_NAME,'chinese student')

3.根据tag选择元素

tag:标签,是用来定义网页内容结构和类型的 “标记符号”,是构成网页的基本单位。

类似的,我们可以通过指定 参数为 By.TAG_NAME ,选择所有的tag名为 div的元素,如下所示

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample1.html')# 根据 tag name 选择元素,返回的是 一个列表
# 里面 都是 tag 名为 div 的元素对应的 WebElement对象
elements = wd.find_elements(By.TAG_NAME, 'div')# 取出列表中的每个 WebElement对象,打印出其text属性的值
# text属性就是该 WebElement对象对应的元素在网页中的文本内容
for element in elements:print(element.text)input('按回车退出')
  • 通过 “标签名(tag name)” 查找网页中所有标签名为 div 的元素。
  • 这些元素会被收集到 elements 列表中,后续通过 element.text 可以获取每个 div 标签内的文本内容。
  • 使用 find_elements 选择的是符合条件的 所有 元素列表, 如果没有符合条件的元素, 返回空列表
  • 使用 find_element 选择的是符合条件的 第一个 元素(一个 WebElement 对象), 如果没有符合条件的元素, 抛出 NoSuchElementException 异常

4.通过WebElement选择对象

不仅 WebDriver对象有 选择元素 的方法, WebElement对象 也有选择元素的方法。

WebElement对象 也可以调用 find_elementsfind_element 之类的方法

  • WebDriver 对象 选择元素的范围是 整个 web页面,
  • WebElement 对象 选择元素的范围是 该元素的内部。(内部再选)

Eg.

限制 选择元素的范围是 id 为 container 元素的内部。

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample1.html')element = wd.find_element(By.ID,'container')# 限制 选择元素的范围是 id 为 container 元素的内部。
spans = element.find_elements(By.TAG_NAME, 'span')
for span in spans:print(span.text)input('按回车退出')

注意:

  • 列表(list)类型没有 find_elements 方法,只有单个 WebElement 对象才可以调用 find_elementsfind_element 方法(用于在该元素内部查找子元素)。
  • element = wd.find_element(By.ID, 'container') 拿到了 id="container"div 元素(一个 WebElement 对象element.find_elements(By.TAG_NAME, 'span') 只会在这个 div 内部查找 span

四.等待界面元素出现

4.1 等待过程会出现的问题

在我们进行网页操作的时候, 有的元素内容不是可以立即出现的, 可能会等待一段时间。

比如 我们的股票搜索示例页面, 搜索一个股票名称, 我们点击搜索后, 浏览器需要把这个搜索请求发送给服务器, 服务器进行处理后,再把搜索结果返回给我们。

所以,从点击搜索到得到结果,需要一定的时间,

只是通常 服务器的处理比较快,我们感觉好像是立即出现了搜索结果

搜索的每个结果 对应的界面元素 其ID 分别是数字 1, 2 ,3, 4 。。。

image-20251029110645863

我们可以先用如下代码 将 第一个搜索结果里面的文本内容 打印出来

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/stock1.html')element = wd.find_element(By.ID, 'kw')element.send_keys('通讯\n')# 返回页面 ID为1 的元素
element = wd.find_element(By.ID,'1')
# 打印该元素的文字内容
print(element.text)input('按回车退出')

抛异常:selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {“method”:“css selector”,“selector”:“[id=“1”]”}

NoSuchElementException 的意思就是在当前的网页上 找不到该元素, 就是找不到 id 为 1 的元素。

为什么呢?

因为我们的代码执行的速度比 网站响应的速度 快。

网站还没有来得及 返回搜索结果,我们就执行了如下代码

element = wd.find_element(By.ID, '1')

在那短暂的瞬间, 网页上是没有用 id为1的元素的 (因为还没有搜索结果呢)。自然就会报告错误 id为1 的元素不存在了。

4.2 解决方案

1.睡觉

初步解决:

  1. sleep 来 等待几秒钟, 等百度服务器返回结果后,再去选择 id 为1 的元素

    # 等待 1 秒
    from time import sleep
    sleep(1)element = wd.find_element(By.ID,'1')
    

但这样会有问题:设置等待多长时间合适呢?

这次百度网站反应可能比较快,我们等了一秒钟就可以了。但是谁知道下次他的反应是不是还这么快呢?百度也曾经出现过服务器瘫痪的事情。

2.implicitly_wait方法(隐式等待/全局等待)

Selenium提供了一个更合理的解决方案,是这样的:

当发现元素没有找到的时候, 并不立即返回 找不到元素的错误。

而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,

或者超出指定最大等待时长,这时才 抛出异常(如果是 find_elements 之类的方法, 则是返回空列表)。

该方法接受一个参数, 用来指定 最大等待时长。

如果我们 加入如下代码

wd.implicitly_wait(10)

那么后续所有的 find_element 或者 find_elements 之类的方法调用 都会采用上面的策略:

如果找不到元素, 每隔 半秒钟 再去界面上查看一次, 直到找到该元素, 或者 过了10秒 最大时长。

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()
wd.implicitly_wait(10)wd.get('https://www.byhy.net/cdn2/files/selenium/stock1.html')element = wd.find_element(By.ID, 'kw')element.send_keys('通讯\n')# 返回页面 ID为1 的元素
element = wd.find_element(By.ID,'1')print(element.text)input('按回车退出')

五.操控元素的基本方法

选择到元素之后,我们的代码会返回元素对应的 WebElement对象,通过这个对象,我们就可以 操控 元素了。

操控元素通常包括:

  1. 点击元素
  2. 在元素中输入字符串,通常是对输入框这样的元素
  3. 获取元素包含的信息,如文本内容,元素属性

5.1 点击元素

点击元素 非常简单,就是调用元素WebElement对象的 click方法。前面我们已经学过。

这里我们要补充讲解一点。

当我们调用 WebElement 对象的 click 方法去点击 元素的时候, 浏览器接收到自动化命令,点击的是该元素的 中心点 位置 。

例如,对于下面的这样一个元素

img

我们要点击 添加客户 这个按钮,既可以点击 右边对应的 绿色框子总的button 元素 ,也可以点击红色框子中的span元素 。

因为这两个元素的中心点都是 button 内部,都是有效点击区域

5.2 输入框

输入字符串 也非常简单,就是调用元素WebElement对象的send_keys方法。前面我们也已经学过。

如果我们要 把输入框中已经有的内容清除掉,可以使用WebElement对象的clear方法

image-20251029133628648

from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://www.byhy.net/cdn2/files/selenium/test3.html')
element = wd.find_element(By.ID, 'input1')
element.clear();
element.send_keys('王德法')
input('按回车退出')

5.3 获取元素信息

1.获取元素的文本内容

上一章,我们已经知道,通过WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容。

element = wd.find_element(By.ID, 'animal')
print(element.text)
2.获取元素属性

通过WebElement对象的 get_attribute 方法来获取元素的属性值

比如要获取元素属性class的值,就可以使用 element.get_attribute('class')

element = wd.find_element(By.ID, 'input_name')
print(element.get_attribute('class'))

执行完自动化代码,如果想关闭浏览器窗口可以调用WebDriver对象的 quit 方法,像这样 wd.quit()

3.获取整个元素对应的HTML
  1. 要获取整个元素对应的HTML文本内容,可以使用 element.get_attribute('outerHTML')(包括div标签本身及所有属性)
  2. 如果,只是想获取某个元素 内部 的HTML文本内容,可以使用 element.get_attribute('innerHTML')(不包含最外层的div标签)

Eg.

<div id="container" class="main">
<p class="intro">这是一段介绍文字</p>
<a href="https://example.com">示例链接</a>
</div>
from selenium import webdriver
from selenium.webdriver.common.by import By# 初始化浏览器并打开网页
wd = webdriver.Chrome()
wd.get("包含目标元素的网页地址")# 定位到id为container的div元素
container = wd.find_element(By.ID, 'container')# 获取整个元素的HTML文本(包括自身标签)
outer_html = container.get_attribute('outerHTML')
print("outerHTML结果:")
print(outer_html)# 获取元素内部的HTML文本(不包括自身标签)
inner_html = container.get_attribute('innerHTML')
print("\ninnerHTML结果:")
print(inner_html)
  • outerHTML结果:

    这是一段介绍文字

    示例链接
  • innerHTML结果:

    这是一段介绍文字

    示例链接
4.获取输入框里的文字

对于input输入框的元素,要获取里面的输入文本,用text属性是不行的,这时可以使用 element.get_attribute('value')

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
wd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/test3.html')element = wd.find_element(By.ID, 'input1')
element.clear();
element.send_keys('王德法')
print(element.get_attribute('id'))
print(element.get_attribute('outerHTML'))
time.sleep(2)
print(element.get_attribute('value')) # 获取输入框中的文本wd.quit()

输出结果:

input1
<input id="input1" value="请输入姓名">
王德法

通过WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容。

但是,有时候,元素的文本内容没有展示在界面上,或者没有完全完全展示在界面上。 这时,用WebElement对象的text属性,获取文本内容,就会有问题。

出现这种情况,可以尝试使用 element.get_attribute('innerText') ,或者 element.get_attribute('textContent')

使用 innerText 和 textContent 的区别:

  1. innerText 只显示元素可见文本内容
  2. textContent 显示所有内容(包括display属性为none的部分)

附录1:HTML标签大全

基本结构标签(定义网页骨架)

<html>整个 HTML 文档的根标签
<head>包含文档的元数据(如标题、样式、脚本)
<title>定义网页标题(显示在浏览器标签栏)
<body>包含网页的可见内容

文本与排版标签

<h1>-<h6>标题标签(h1 最大,h6 最小)
<p>段落标签
<br>换行标签(单标签)
<hr>水平线标签(单标签)
<strong>强调文本(粗体,语义化)
<em>强调文本(斜体,语义化)
<span>行内文本容器(无默认样式)
<blockquote>长引用文本(会缩进)

容器与布局标签(用于组织内容结构

<div>块级容器(常用作区域划分,默认占满一行)
<span>行内容器(用于包裹部分文本,不换行)
<header>页头 / 区域头部(语义化标签)
<footer>页脚 / 区域底部(语义化标签)
<nav>导航栏(语义化标签)
<main>主要内容区域(语义化标签)
<section>独立区块(如章节、栏目,语义化标签)
<article>独立文章内容(如博客、新闻,语义化标签)

列表标签

<ul>无序列表(项目前有圆点 / 方块等符号)
<ol>有序列表(项目前有数字 / 字母序号)
<li>列表项(包含在 <ul><ol> 中)
<dl>定义列表(由 “术语 + 解释” 组成)
<dt>定义列表中的 “术语”

链接与多媒体标签

标签作用
<a>超链接(href 属性指定链接地址)
<img>插入图片(src 属性指定图片路径,单标签)
<video>插入视频(src 指定视频路径)
<audio>插入音频(src 指定音频路径)
<iframe>内嵌另一个网页(如嵌入地图、视频)

表单标签(用于用户输入)

标签作用
<form>表单容器(包含所有表单元素)
<input>输入框(通过 type 属性指定类型)
- type="text":文本输入框
- type="password":密码框(输入内容隐藏)
- type="radio":单选按钮
- type="checkbox":复选框
- type="submit":提交按钮
- type="button":普通按钮
- type="file":文件上传
<select>下拉选择框
<option>下拉选择框中的选项(包含在 <select> 中)
<textarea>多行文本输入框(可输入大段文字)
<label>表单元素的标签(关联输入框,点击标签聚焦输入框)

表格标签

标签作用
<table>表格容器
<tr>表格的一行
<td>表格的一个单元格(包含在 <tr> 中)
<th>表格的表头单元格(默认加粗居中)
<thead>表格头部(语义化,包含表头行)
<tbody>表格主体(语义化,包含数据行)
<tfoot>表格底部(语义化,包含汇总行)

其他常用标签

标签作用
<comment>HTML 注释(内容不会显示在网页上)
<meta>元数据标签(定义编码、关键词等,在 <head> 中)
<style>内嵌 CSS 样式(在 <head> 中)
<script>内嵌或引用 JavaScript 脚本

六.CSS表达式(上)

前面我们看到了根据id、class属性、tag名选择元素

如果我们要选择的的元素没有id、class属性,或者有些我们不想选择的元素也有相同id、class属性值,这时怎么办呢?

这时候我们可以通过CSS selector(选择器)语法来选择元素


6.1 CSS selector语法原理

HTML中经常要 为 某些元素 指定 显示效果,比如 前景文字颜色是红色, 背景颜色是黑色, 字体是微软雅黑等。

那么CSS必须告诉浏览器:要 选择哪些元素 , 来使用这样的显示风格。

比如 ,下图中,为什么狮子老虎山羊会显示为红色呢?

image

因为蓝色框里面用css 样式,指定了class 值为animal的元素,要显示为红色。其中 蓝色框里面的 .animal 就是 CSS Selector ,或者说 CSS 选择器。

CSS Selector 语法就是用来选择元素的。

既然 CSS Selector 语法 天生就是浏览器用来选择元素的,selenium自然就可以使用它用在自动化中,去选择要操作的元素了。

只要 CSS Selector 的语法是正确的, Selenium 就可 以选择到该元素。

CSS Selector 非常强大,学习Selenium Web自动化一定要学习 CSS Selector

通过CSS Selector选择单个元素的方法

find_element(By.CSS_SELECTOR,CSS Selector参数)

选择所有元素的方法:

find_elements(By.CSS_SELECTOR,CSS Selector参数)

6.2 根据tag名、id、class选择元素

1.根据tag名选择元素

CSS Selector同样可以选择tag名、id属性和class属性来选择元素,根据tag名选择元素的CSS Selector语法很简单–>可以直接写上tag名即可

比如,要选择所有tag名为div的元素如下:

element = wd.find_elements(By.CSS_SELECTOR,'div')

等价于:

element = wd.find_elements(By.TAG_NAME,'div')

2.根据id号选择元素

根据id属性选择元素的语法是在id号前面加上一个井号:#id值

image-20251029153833043

就可以使用#searchtext的CSS Selector来选择

Eg.

比如,我们想在 id 为 searchtext 的输入框中输入文本 说来话长 ,完整的Python代码如下

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
wd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample1.html')element = wd.find_element(By.CSS_SELECTOR,'#searchtext')
element.send_keys('说来话长')
time.sleep(2)
wd.quit()

3.根据class属性选择元素

语法:在class值前面加上一个点 .class值

Eg.

还是上面的网站要选择所有 class 属性值为 animal的元素 动物 除了这样写

elements = wd.find_elements(By.CLASS_NAME, 'animal')

还可以

elements = wd.find_elements(CSS_SELECTOR,'.animal')

因为是选择 所有 符合条件的 ,所以用 find_elements 而不是 find_element


6.3 选择子元素和后代元素

CSS选择器可以限定选择的上级范围,也就是选择某个元素的子元素和后代元素,那么首先来学习子元素和后代元素

HTML中,元素内部可以包含其他元素,我们来分析下面的HTML片段

<div id='container'><div id='layer1'><div id='inner11'><span>内层11</span></div><div id='inner12'><span>内层12</span></div></div><div id='layer2'><div id='inner21'><span>内层21</span></div></div></div>
  1. id为container的div元素包含了id为layer1和layer2的两个div元素:这种包含是直接包含,中间没有其他层次的元素,所以我们吧id为layer1和layer2的两个div元素称之为id为container的div元素的直接子元素,简称子元素(子是孩子的意思),反之把 id 为 container 的div元素 称之为 id 为 layer1layer2 的两个div元素 的 父元素

  2. 而对于 id 为 container 的div元素来说, id 为 inner11inner12inner21 的元素 和 两个 span类型的元素 都不是 它的直接子元素, 因为中间隔了 几层。虽然不是直接子元素, 但是 它们还是在 container 的内部, 可以称之为它 的 后代元素。反之, 把 把 id 为 container 的div元素 称之为 id 为 inner11inner12inner21 的元素 的 祖先元素

  3. 后代元素也包括了直接子元素, 比如 id 为 layer1layer2 的两个div元素 也可以说 是 id 为 container 的div元素 的 直接子元素,同时也是后代子元素

  4. 如果 元素2元素1 的 直接子元素, CSS Selector 选择子元素的语法是这样的,这里的大于号可以理解为箭头号

    元素1 > 元素2
    

    注意,最终选择的元素是 元素2, 并且要求这个 元素2元素1 的直接子元素

    也支持更多层级的选择, 比如

    元素1 > 元素2 > 元素3 > 元素4
    

    就是选择 元素1 里面的子元素 元素2 里面的子元素 元素3 里面的子元素 元素4 , 最终选择的元素是 元素4

  5. 如果 元素2元素1 的 后代元素, CSS Selector 选择后代元素的语法是这样的,中间用一个或者多个空格隔开

    元素1   元素2
    

    最终选择的元素是 元素2 , 并且要求这个 元素2元素1 的后代元素。

    也支持更多层级的选择, 比如

    元素1   元素2   元素3  元素4
    

    最终选择的元素是 元素4

  6. CSS 支持 大于号和 空格 混合使用,比如

    元素1 >  元素2   元素3 > 元素4
    

    元素 1 的直接子元素(元素 2)内部,所有元素 3 的直接子元素(元素 4)

  7. 其中每个元素的写法可以是 复合写法,比如

    span.date //选择class值有date的sapn元素
    div#bottom //选择id为bottom的div元素
    div#bottom.date //选择id为bottom,class值有date的div元素
    

Eg.选出以下网页中所有的上将的名字(不要外号)

image-20251029164247043

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
wd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/shuihu.html')elements = wd.find_elements(By.CSS_SELECTOR,'#layer1 div.item > span.name')
for element in elements:print(element.text)
time.sleep(2)
wd.quit()

6.4 根据属性选择

id、class 都是web元素的 属性 ,因为它们是很常用的属性,所以css选择器专门提供了根据 id、class 选择的语法。

比如.animal和#id,那么其他属性如何选择?

image-20251029165234242

里面底部的这个元素也是可以用CSS选择器的

<a href="http://www.miitbeian.gov.cn">苏ICP备88885574</a>

css 选择器支持通过任何属性来选择元素,语法是用一个方括号 []

比如要选择上面的a元素,就可以使用 [href="http://www.miitbeian.gov.cn"]

这个表达式的意思是,选择 属性href值为 http://www.miitbeian.gov.cn 的元素。

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample1.html')# 根据属性选择元素
element = wd.find_element(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')# 打印出元素对应的html
print(element.get_attribute('outerHTML'))

当然,前面可以加上标签名的限制,比如 div[class='SKnet'] 表示 选择所有 标签名为div,且class属性值为SKnet的元素。

属性值用单引号,双引号都可以。

根据属性选择,还可以不指定属性值,

比如 [href] , 表示选择 所有 具有 属性名 为href 的元素,不管它们的值是什么。

CSS 还可以选择 属性值 包含 某个字符串 的元素

比如, 要选择a节点,里面的href属性包含了 miitbeian 字符串,就可以这样写

a[href*="miitbeian"]

还可以 选择 属性值 以某个字符串 开头 的元素

比如, 要选择a节点,里面的href属性以 http 开头 ,就可以这样写

a[href^="http"]

还可以 选择 属性值 以某个字符串 结尾 的元素

比如, 要选择a节点,里面的href属性以 gov.cn 结尾 ,就可以这样写

a[href$="gov.cn"]

如果一个元素具有多个属性

<div class="misc" ctype="gun">沙漠之鹰</div>

CSS 选择器 可以指定 选择的元素要 同时具有多个属性的限制,像这样 div[class=misc][ctype=gun]


6.5 验证CSS Selector

那么我们怎么验证 CSS Selector 的语法是否正确选择了我们要选择的元素呢?

当然可以像下面这样,写出Python代码,运行看看,能否操作成功

element = wd.find_element(By.CSS_SELECTOR, '#searchtext')
element.input('输入的文本')

如果成功,说明选择元素的语法是正确的。

但是这样做的问题就是:太麻烦了。

当我们进行自动化开发的时候,有大量选择元素的语句,都要这样一个个的验证,就非常耗时间。

由于 CSS Selector 是浏览器直接支持的,可以在浏览器 开发者工具栏 中验证。

比如我们使用Chrome浏览器打开 https://www.byhy.net/cdn2/files/selenium/sample1.html

按F12 打开 开发者工具栏

如果我们要验证 下面的表达式

#bottom > .footer2  a

能否选中 这个元素

<a href="http://www.miitbeian.gov.cn">苏ICP备88885574号</a>

可以这样做:

点击 Elements 标签后, 同时按 Ctrl 键 和 F 键, 就会出现下图箭头处的 搜索框

img

我们可以在里面输入任何 CSS Selector 表达式 ,如果能选择到元素, 右边的的红色方框里面就会显示出类似 2 of 3 这样的内容。

of 后面的数字表示这样的表达式 总共选择到几个元素

of 前面的数字表示当前黄色高亮显示的是 其中第几个元素

上图中的 1 of 1 就是指 : CSS 选择语法 #bottom > .footer2 a

在当前网页上共选择到 1 个元素, 目前高亮显示的是第1个。

如果我们输入 .plant 就会发现,可以选择到3个元素

img


七.CSS表达式(下)

7.1 组选择

Eg. 同时选择所有class 为 plant class 为 animal 的元素。

这种情况,css选择器可以 使用 逗号 ,称之为 组选择 ,像这样

.plant,.animal

再比如,我们要同时选择所有tag名为div的元素 id为BYHY的元素,就可以像这样写

div,#BYHY

对应的Selenium代码如下

elements = wd.find_elements(By.CSS_SELECTOR,'div,#BYHY')
for element in elements:print(element.text)

Eg. 选择所有唐诗里面的作者和诗名,也就是选择所有 id 为 t1 里面的 span 和 p 元素

image-20251029170948632

代码如下:

elements = wd.find_elements(By.CSS_SELECTOR,'#t1 > span,#t1 > p')

但是不能这样写:

#t1 > span,p
  • 这样写的意思是选择所有id为 t1里面的span 和 所有的P元素(不在t1里面的也会被选)

**注意:**组选择结果列表中,选中元素排序, 不是 组表达式的次序, 而是符合这些表达式的元素,在HTML文档中的出现的次序。


7.2 按次序选择子节点

image-20251029172102606

1.父元素的第n个子节点

我们可以指定选择的元素是父元素的第几个子节点

“所有父元素” 指的是HTML文档中所有拥有子元素的元素

即使用:nth-child

比如,我们要选择 唐诗 和宋词 的第一个 作者,也就是说 选择的是 第2个子元素,并且是span类型,就可以这样写:

span:nth-child(2)

div#t1 中:子元素依次是:<h3>唐诗</h3>(第 1 个)、<span>李白</span>(第 2 个)、<p>静夜思</p>(第 3 个)

如果你不加节点类型限制,直接这样写 :nth-child(2),就是选择所有位置为第2个的所有元素,不管是什么类型

2.父元素的倒数第n个子节点

也可以反过来, 选择的是父元素的 倒数第几个子节点 ,使用 nth-last-child

比如:

p:nth-last-child(1)

就是选择第倒数第1个子元素,并且是p元素

3.父元素的第几个某类型的子节点

我们可以指定选择的元素 是父元素的第几个 某类型的 子节点

使用 nth-of-type

比如,我们要选择 唐诗 和宋词 的第一个 作者,

可以像上面那样思考:选择的是 第2个子元素,并且是span类型

所以这样可以这样写 span:nth-child(2)

还可以这样思考,选择的是 第1个span类型 的子元素

所以也可以这样写 span:nth-of-type(1)

4.父元素的倒数第几个某类型的子节点

当然也可以反过来, 选择父元素的 倒数第几个某类型 的子节点,使用 nth-last-of-type

像这样

p:nth-last-of-type(2)
5.奇数节点和偶数节点

如果要选择的是父元素的 偶数节点,使用 nth-child(even)

比如

p:nth-child(even)

如果要选择的是父元素的 奇数节点,使用 nth-child(odd)

p:nth-child(odd)

如果要选择的是父元素的 某类型偶数节点,使用 nth-of-type(even)

如果要选择的是父元素的 某类型奇数节点,使用 nth-of-type(odd)

6.兄弟节点选择

相邻兄弟节点选择

上面的例子里面,我们要选择 唐诗 和宋词 的第一个 作者

还有一种思考方法,就是选择 h3 后面紧跟着的兄弟节点 span。

这就是一种 相邻兄弟 关系,可以这样写 h3 + span

表示元素 紧跟关系的 是 加号

后续所有兄弟节点选择

如果要选择是 选择 h3 后面所有的兄弟节点 span,可以这样写 h3 ~ span


七.frame切换/窗口切换

7.1 主窗口和嵌入的窗口

如果我们要 选择 下图方框中 所有的 蔬菜,使用css选择,怎么写表达式?

img

以下代码不行了:

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample2.html')# 根据 class name 选择元素,返回的是 一个列表
elements = wd.find_elements(By.CLASS_NAME, 'plant')for element in elements:print(element.text)

运行一下,你就会发现,运行结果打印内容为空白,说明没有选择到 class 属性值为 plant 的元素。

为什么呢?

因为仔细看,你可以发现, 这些元素是在一个叫 iframe的元素中的。

img

这个 iframe 元素非常的特殊, 在html语法中,frame 元素 或者iframe元素的内部 会包含一个 被嵌入的 另一份html文档。

在我们使用selenium打开一个网页时, 我们的操作范围 缺省是当前的(最外层的) html , 并不包含被嵌入的html文档里面的内容。

如果我们要 操作 被嵌入的 html 文档 中的元素, 就必须 切换操作范围 到 被嵌入的文档中。

怎么切换呢?

使用 WebDriver 对象的 switch_to 属性,像这样

wd.switch_to.frame(frame_reference)

其中, frame_reference 可以是 frame 元素的属性 name 或者 ID 。

比如这里,就可以填写 iframe元素的id ‘frame1’ 或者 name属性值 ‘innerFrame’,如下:

wd.switch_to.frame('frame1')
wd.switch_to.frame('innerFrame')

image-20251029175437909

也可以填写frame 所对应的 WebElement 对象。

我们可以根据frame的元素位置或者属性特性,使用find系列的方法,选择到该元素,得到对应的WebElement对象

比如,这里就可以写

wd.switch_to.frame(wd.find_element(By.TAG_NAME, "iframe"))

总结:修改后(正确的代码如下)

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample2.html')# 先根据name属性值 'innerFrame',切换到iframe中
wd.switch_to.frame('innerFrame')# 根据 class name 选择元素,返回的是 一个列表
elements = wd.find_elements(By.CLASS_NAME, 'plant')for element in elements:print(element.text)

7.2 窗口切换

1.切换回主窗口

如果我们已经切换到某个iframe里面进行操作了,那么后续选择和操作界面元素 就都是在这个frame里面进行的。

这时候,如果我们又需要操作 主html (我们把最外层的html称之为 主html ) 里面的元素了呢?

怎么切换回原来的 主html 呢?

很简单,写如下代码即可:

wd.switch_to.default_content()

例如,在上面 代码 操作完 frame里面的元素后, 需要 点击 主html 里面的按钮,就可以这样写

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()wd.get('https://www.byhy.net/cdn2/files/selenium/sample2.html')# 先根据name属性值 'innerFrame',切换到iframe中
wd.switch_to.frame('innerFrame')# 根据 class name 选择元素,返回的是 一个列表
elements = wd.find_elements(By.CLASS_NAME, 'plant')for element in elements:print(element.text)# 切换回 最外部的 HTML 中
wd.switch_to.default_content()# 然后再 选择操作 外部的 HTML 中 的元素
wd.find_element_by_id('outerbutton').click()wd.quit()
2.切换为新的窗口

在网页上操作的时候,我们经常遇到,点击一个链接 或者 按钮,就会打开一个 新窗口

image-20251029202302744

在打开的网页中,点击 链接 访问bing网站 , 就会弹出一个新窗口,访问bing网址。

如果我们用Selenium写自动化程序 在新窗口里面 打开一个新网址, 并且去自动化操作新窗口里面的元素,会有什么问题呢?

问题就在于,即使新窗口打开了, 这时候,我们的 WebDriver对象对应的 还是老窗口,自动化操作也还是在老窗口进行,

from selenium import webdriver
from selenium.webdriver.common.by import Bywd = webdriver.Chrome()
wd.implicitly_wait(10)wd.get('https://www.byhy.net/cdn2/files/selenium/sample3.html')# 点击打开新窗口的链接
link = wd.find_element(By.TAG_NAME, "a")
link.click()# wd.title属性是当前窗口的标题栏 文本
print(wd.title)

运行后,最后一行输出内容是:

白月黑羽测试网页3

说明, 我们的 WebDriver对象指向的还是老窗口,否则的话,运行结果就应该新窗口的标题栏 “微软Bing搜索”

3. 新窗口操作

那我们如何到新窗口进行操作呢

可以使用Webdriver对象的switch_to属性的 window方法,如下所示:

wd.switch_to.window(handle)

WebDriver对象有window_handles 属性,这是一个列表对象, 里面包括了当前浏览器里面所有的窗口句柄

所谓句柄,可以想象成对应网页窗口的一个ID

for handle in wd.window_handles:#先切换到该窗口wd.switch_to.window(handle)#得到该窗口的标题栏字符栏,判断是不是我们要操作的那个窗口if 'Bing' in wd.title:#如果是,那么这时候WebDriver对象就是对应的该窗口,跳出循环即可break;

我们依次获取 wd.window_handles 里面的所有 句柄 对象, 并且调用 wd.switch_to.window(handle) 方法,切入到每个窗口,

然后检查里面该窗口对象的属性(可以是标题栏,地址栏),判断是不是我们要操作的那个窗口,如果是,就跳出循环。


4. 回到原窗口

我们可以仍然使用上面的方法,依次切入窗口,然后根据 标题栏 之类的属性值判断。

还有更省事的方法。

因为我们一开始就在 原来的窗口里面,我们知道 进入新窗口操作完后,还要回来,可以事先 保存该老窗口的 句柄,使用如下方法

# mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle

切换到新窗口操作完后,就可以直接像下面这样,将driver对应的对象返回到原来的窗口

#通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switch_to.window(mainWindow)

八.选择框

常见的选择框包括:radio框、checkbox框、select框

8.1 radio框

radio框选择选项,直接用WebElement的click方法,模拟用户点击就可以了。

Eg.

在如下HTML页面中

image-20251029204230195

  1. 先打印当前选中的老师的名字
  2. 在选择小雷老师
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get('https://www.byhy.net/cdn2/files/selenium/test2.html')#获取当前选中的元素
element = wd.find_element(By.CSS_SELECTOR,'#s_radio input[name = "teacher"]:checked')
print("当前选中的是:"+ element.get_attribute('value'))
#点选小雷老师
wd.find_element(By.CSS_SELECTOR,'#s_radio input[value="小雷老师"]').click()
time.sleep(2)
  1. 其中#s_radio input[name="teacher"]:checked 里面的 :checked 是CSS伪类选择,表示选择 checked 状态的元素,对 radiocheckbox 类型的input有效

8.2 checkbox框

对checkbox进行选择,也是直接用WebElement的Click方法模拟用户进行选择

需要注意的是,要选中checkbox的一个选项,必须 先获取当前该复选框的状态 ,如果该选项已经勾选了,就不能再点击。否则反而会取消选择。

比如, 我们要在下面的html中:选中 小雷老师

<div id="s_checkbox"><input type="checkbox" name="teachers1" value="小江老师">小江老师<br><input type="checkbox" name="teachers1" value="小雷老师">小雷老师<br><input type="checkbox" name="teachers1" value="小凯老师" checked="checked">小凯老师
</div>

我们的思路可以是这样:

  • 先把 已经选中的选项全部点击一下,确保都是未选状态
  • 再点击 小雷老师
#先把已经选中的选项全部点击
elements= wd.find_elements(By.CSS_SELECTOR,'#s_checkbox input[name = 'teachers1']:checked')
for element in elements:element.click()
#再点击小雷老师
wd.find_element(By.CSS_SELECTOR,‘s_checkbox input[value = '小雷老师']).click()

8.3 select框

radio框及checkbox框都是input元素,只是里面的type不同而已。

select框 则是一个新的select标签,大家可以对照浏览器网页内容查看一下

对于Select 选择框, Selenium 专门提供了一个 Select类 进行操作,可以这样导入

from selenium.webdriver.support.select import Select

这个类实例化时传入 Select元素对应的 WebElement 对象,比如

select = Select(wd.find_element(By.ID, 'ss_single')

Select提供过了如下的方法和属性

  1. all_selected_options

    返回所有选中的option元素对应的WebElement对象

    for ele in select.all_selected_options:print(ele.text)
    
  2. select_by_value

    根据选项的value属性值,选择元素

    比如下面的HTML

    <option value="foo">Bar</option>
    

    就可以根据foo这个值选择该选项

    select.select_by_value('foo')
    
  3. select_by_index

    根据选项的次序选择元素

    现在Selenium是从0开始,第一个选项的index为0

    select_by_index(0),选择的是第一个选项

    select_by_index(0),选择的是第二个选项,以此类推

  4. select_by_visible_text

    根据选项的可见文本,选择元素。

    比如,如下的HTML

    <option value="foo">Bar</option>
    

    就可以根据Bar这个内容,选择该选项

    select.select_by_visible_text('Bar')
    
  5. deselect_by_value

    根据选项的value属性值,去除选中元素

  6. deselect_by_index

    根据选项的次序,去除 选中元素

  7. deselect_by_visible_text

    根据选项的可见文本,去除 选中元素

  8. deselect_all

    去除 选中所有元素

Select单选框

对于 select单选框,操作比较简单:

不管原来选的是什么,直接用Select方法选择即可。

例如,选择示例里面的小雷老师,示例代码如下

# 导入Select类
from selenium.webdriver.support.select import Select# 创建Select对象
select = Select(wd.find_element(By.ID, "ss_single"))# 通过 Select 对象选中小雷老师
select.select_by_visible_text("小雷老师")

Select多选框

对于select多选框,要选中某几个选项,要注意去掉原来已经选中的选项。

例如,我们选择示例多选框中的 小雷老师 和 小凯老师

可以用select类 的deselect_all方法,清除所有 已经选中 的选项。

然后再通过 select_by_visible_text方法 选择 小雷老师 和 小凯老师。

示例代码如下:

# 导入Select类
from selenium.webdriver.support.select import Select# 创建Select对象
select = Select(wd.find_element(By.ID, "ss_multi"))# 清除所有 已经选中 的选项
select.deselect_all()# 选择小雷老师 和 小凯老师
select.select_by_visible_text("小雷老师")
select.select_by_visible_text("小凯老师")

九.实战技巧

之前我们对web元素做的操作主要是:选择元素,然后 点击元素 或者 输入 字符串。

9.1 ActionChains操作元素

鼠标右键点击、双击、移动鼠标到某个元素、鼠标拖拽等。

这些操作,可以通过 Selenium 提供的 ActionChains 类来实现。

ActionChains 类 里面提供了 一些特殊的动作的模拟,我们可以通过 ActionChains 类的代码查看到,如下所示

image

我们以鼠标 光标悬停 到某个元素,和 拖放 为例。

可以把鼠标放在导航栏最右边的 更多 上,就会弹出更多的导航项目。

下方正文区域,可以拖动左边实战班课程 放到 右边的选中区域。

image-20251030165924235

image-20251030165945325

代码如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
wd = webdriver.Chrome()
wd.implicitly_wait(5)
wd.get('https://www.byhy.net/cdn2/files/selenium/sample4.html')
from selenium.webdriver.common.action_chains import ActionChains
ac = ActionChains(wd)#光标悬停到元素上
ac.move_to_element(wd.find_element(By.CSS_SELECTOR,'.navbar-nav > li.dropdown')
).perform()time.sleep(3)#拖放元素
for i in range(1,6):ac.drag_and_drop(wd.find_element(By.ID,f'course-{i}'),wd.find_element(By.ID,'selected-courses')).perform()time.sleep(0.5)input('\n\n按回车退出')

9.2 直接执行javascript

我们可以直接让浏览器运行一段javascript代码,并且得到返回值,如下

# 直接执行 javascript,里面可以直接用return返回我们需要的数据
nextPageButtonDisabled = driver.execute_script('''ele = document.querySelector('.soupager > button:last-of-type');return ele.getAttribute('disabled')''')# 返回的数据转化为Python中的数据对象进行后续处理
if nextPageButtonDisabled == 'disabled': # 是最后一页return True
else: # 不是最后一页return False

有时,自动化的网页内容很长,或者很宽,超过一屏显示,

如果我们要点击的元素不在窗口可见区内,新版本的selenium协议, 浏览器发现要操作(比如点击操作)的元素,不在可见区内,往往会操作失败,

出现类似下面的提示

element click intercepted: Element <span>这里是元素html</span> 
is not clickable at point (119, 10). 
Other element would receive the click: <div>...</div>

这时,可以调用 execute_script 直接执行js代码,让该元素出现在窗口可见区正中

driver.execute_script("arguments[0].scrollIntoView({block:'center',inline:'center'})", job) 

其中 arguments[0] 就指代了后面的第一个参数 job 对应的js对象,

js对象的 scrollIntoView 方法,就是让元素滚动到可见部分

block:'center' 指定垂直方向居中

inline:'center' 指定水平方向居中


9.3 冻结页面

有些网站上面的元素, 我们鼠标放在上面,会动态弹出一些内容。

比如,百度首页的右上角,有个 更多产品 选项,如下图所示

image-20251030170658328

如果我们把鼠标放在上边,就会弹出 下面的 糯米、音乐、图片 等图标。

如果我们要用 selenium 自动化 点击 糯米图标,就需要 F12 查看这个元素的特征。

但是 当我们的鼠标 从 糯米图标 移开, 这个 栏目就整个消失了, 就没法 查看 其对应的 HTML。

怎么办?

可以如下图所示:

img

在 开发者工具栏 console 里面执行如下js代码

setTimeout(function(){debugger}, 5000)

这句代码什么意思呢?

表示在 5000毫秒后,执行 debugger 命令

执行该命令会 浏览器会进入debug状态。 debug状态有个特性, 界面被冻住, 不管我们怎么点击界面都不会触发事件。

/html/body/div[4]/div/div[2]/a[1]

所以,我们可以在输入上面代码并回车 执行后, 立即 鼠标放在界面 右上角 更多产品处。

这时候,就会弹出 下面的 糯米、音乐、图片 等图标。

然后,我们仔细等待 5秒 到了以后, 界面就会因为执行了 debugger 命令而被冻住。

然后,我们就可以点击 开发者工具栏的 查看箭头, 再去 点击 糯米图标 ,查看其属性了。


9.4 弹出对话框

有的时候,我们经常会在操作界面的时候,出现一些弹出的对话框。

image-20251030170935544

分别点击界面的3个按钮,你可以发现:

弹出的对话框有三种类型,分别是 Alert(警告信息)、confirm(确认信息)和prompt(提示输入)

Alert

Alert 弹出框,目的就是显示通知信息,只需用户看完信息后,点击 OK(确定) 就可以了。

那么,自动化的时候,代码怎么模拟用户点击 OK 按钮呢?

selenium提供如下方法进行操作

driver.switch_to.alert.accept()

注意:如果我们不去点击它,页面的其它元素是不能操作的。

如果程序要获取弹出对话框中的信息内容, 可以通过 如下代码

driver.switch_to.alert.text
from selenium import webdriver
from selenium.webdriver.common.by import Bydriver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://www.byhy.net/cdn2/files/selenium/test4.html')# --- alert ---
driver.find_element(By.ID, 'b1').click()# 打印 弹出框 提示信息
print(driver.switch_to.alert.text) # 点击 OK 按钮
driver.switch_to.alert.accept()
Prompt

出现 Prompt 弹出框 是需要用户输入一些信息,提交上去。

比如:当管理员在网站上选择给某个账号延期时,就可能会弹出 Prompt 弹出框, 要求输入延期多长时间。

可以调用如下方法

driver.switch_to.alert.send_keys()
from selenium import webdriver
from selenium.webdriver.common.by import Bydriver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get('https://www.byhy.net/cdn2/files/selenium/test4.html')# --- prompt ---
driver.find_element(By.ID, 'b3').click()# 获取 alert 对象
alert = driver.switch_to.alert# 打印 弹出框 提示信息
print(alert.text)# 输入信息,并且点击 OK 按钮 提交
alert.send_keys('web自动化 - selenium')
alert.accept()# 点击 Cancel 按钮 取消
driver.find_element(By.ID, 'b3').click()
alert = driver.switch_to.alert
alert.dismiss()

有些弹窗并非浏览器的alert 窗口,而是html元素**,这种对话框,只需要通过之前介绍的选择器选中并进行相应的操作就可以了。**


9.5 其他技巧

窗口大小

有时间我们需要获取窗口的属性和相应的信息,并对窗口进行控制

  • 获取窗口大小
driver.get_window_size()
  • 改变窗口大小
driver.set_window_size(x, y)
窗口标题

浏览网页的时候,我们的窗口标题是不断变化的,可以使用WebDriver的title属性来获取当前窗口的标题栏字符串。

driver.title
获取当前窗口URL地址
driver.current_url

例如,访问网易,并获取当前窗口的标题和URL

from selenium import  webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(5)# 打开网站
driver.get('https://www.163.com')# 获取网站标题栏文本
print(driver.title) # 获取网站地址栏文本
print(driver.current_url) 
截屏

有的时候,我们需要把浏览器屏幕内容保存为图片文件。

比如,做自动化测试时,一个测试用例检查点发现错误,我们可以截屏为文件,以便测试结束时进行人工核查。

可以使用 WebDriver 的 get_screenshot_as_file方法来截屏并保存为图片。

from selenium import  webdriverdriver = webdriver.Chrome()
driver.implicitly_wait(5)# 打开网站
driver.get('https://www.baidu.com/')# 截屏保存为图片文件
driver.get_screenshot_as_file('1.png')
上传文件

有时候,网站操作需要上传文件。

通常,网站页面上传文件的功能,是通过 type 属性 为 file 的 HTML input 元素实现的。

如下所示:

<input type="file" multiple="multiple">

使用selenium自动化上传文件,我们只需要定位到该input元素,然后通过 send_keys 方法传入要上传的文件路径即可。

如下所示:

# 先定位到上传文件的 input 元素
ele = wd.find_element(By.CSS_SELECTOR, 'input[type=file]')# 再调用 WebElement 对象的 send_keys 方法
ele.send_keys(r'h:\g02.png')

如果需要上传多个文件,可以多次调用send_keys,如下

ele = wd.find_element(By.CSS_SELECTOR,  'input[type=file]')
ele.send_keys(r'h:\g01.png')
ele.send_keys(r'h:\g02.png')

但是,有的网页上传,是没有 file 类型 的 input 元素的。

如果是Windows上的自动化,可以采用 Windows 平台专用的方法:

执行

pip install pypiwin32

确保 pywin32 已经安装,然后参考如下示例代码

# 找到点击上传的元素,点击
driver.find_element(By.CSS_SELECTOR, '.dropzone').click()sleep(2) # 等待上传选择文件对话框打开# 直接发送键盘消息给 当前应用程序,
# 前提是浏览器必须是当前应用
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")# 输入文件路径,最后的'\n',表示回车确定,也可能时 '\r' 或者 '\r\n'
shell.Sendkeys(r"h:\a2.png" + '\n')
sleep(1)
http://www.dtcms.com/a/596295.html

相关文章:

  • 门户网站开发介绍上海华谊集团建设有限公司网站
  • 8. Linux-riscv内存管理35-40问
  • Vue3响应式系统中,对象新增属性、数组改索引、原始值代理的问题如何解决?
  • HTTP接口和Dubbo接口区别
  • K8S中ETCD高可用机制详解
  • jmeter发送数据到sasl加密的kafka
  • 【MATLAB代码】二维平面的TOA定位,GDOP(几何精度因子)和CRLB(克拉美罗下界)计算与输出
  • 【Hadoop】Hadoop核心基础——YARN 框架架构与运行机制(Hadoop 集群的 “资源管家”)
  • MI50运算卡使用llama.cpp的ROCm后端运行gpt-oss-20b的速度测试
  • 聊聊关于hive“中文乱码”问题
  • 一般建设网站需要多少预算酷站 网站
  • ASP.NET 实战:用 CSS 选择器打造一个可搜索、响应式的书籍管理系统
  • 消息队列防止数据丢失问题
  • Spring Cloud Bus 事件广播机制
  • 广州巨腾建网站公司郑州网站app开发
  • 银河麒麟服务器安装图形化界面
  • 【源码+文档+调试讲解】基于Spring Boot的考务管理系统设计与实现 085
  • LeetCode 421 - 数组中两个数的最大异或值
  • 【笔记】xFormers版本与PyTorch、CUDA对应关系及正确安装方法详解
  • 【GitHub每日速递 20251111】PyTorch:GPU加速、动态网络,深度学习平台的不二之选!
  • 多产品的网站怎么做seo做音乐网站之前的准备
  • 网站如何做h5动态页面设计万网备案初审过了后网站能访问吗
  • centos运维常用命令
  • 在CentOS 7.6系统中找回或重置 root 密码
  • 濮阳团购网站建设手机网站模板psd
  • 基于Spring Boot的电子犬证管理系统设计与实现
  • Spring Boot 中的定时任务:从基础调度到高可用实践
  • 家装设计师网站wordpress小清新模板
  • 用WordPress制作单页相城seo网站优化软件
  • wordpress主题wpmee江门网站优化排名