上手Selenium

目录

介绍

Selenium 是一套 Web网站的程序自动化操作解决方案。通过它,我们可以写出自动化程序,像人一样在浏览器里操作web界面。 比如点击界面按钮,在文本框中输入文字等操作。

支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera和Edge等。这里我将以Chrome为例进行Selenium功能的演示~

准备工作

安装selenium库

不同的编程语言选择不同的Selenium客户端库,对应我们Python语言来说,Selenium客户端库的安装非常简单,用 pip 命令即可。

打开命令行程序,运行如下命令:pip install selenium

网络不好的话,可以使用豆瓣源:pip install selenium -i https://pypi.douban.com/simple/

安装浏览器驱动

浏览器驱动是和浏览器对应的。 不同的浏览器需要选择不同的浏览器驱动。
2.1 浏览器的选择

目前主流的浏览器中,谷歌 Chrome 浏览器对Selenium自动化的支持更加成熟一些。
2.2 检查浏览器版本

其实,有两种方式安装浏览器驱动:一种是常见的手动安装,另一种则是利用第三方库自动安装。

这里介绍手动安装,自动安装参见:https://mp.weixin.qq.com/s/_lsDLPpNI1zdSwaPgdTZHQ

首先需要查看浏览器版本(2种方式均可):

方式1:在浏览器的地址栏键入Chrome://version,即可查看浏览器版本号

方式2:点击"Chrome菜单"→"帮助"→"关于Google Chrome",查看浏览器版本号

相当于地址栏输入:chrome://settings/help

2.3 浏览器驱动的安装

下载地址:https://chromedriver.storage.googleapis.com/index.html

注意:驱动和浏览器的版本号越接近越好,但是略有差别,比如98和97 ,通常也没有什么问题。

初始化浏览器对象

通过调用浏览器驱动,可以打开浏览器,就可以了

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 创建 WebDriver 对象,指明使用chrome浏览器驱动
# 注意,等号右边 返回的是 WebDriver 类型的对象,我们可以通过这个对象来操控浏览器,比如 打开网址、选择界面元素等。
wb = webdriver.Chrome(service=Service(r'C:\Users\asuka\Downloads\Compressed\chromedriver.exe'))

# 添加 input,让程序保持运行状态
input()

在创建WebDriver对象时,需要指定浏览器驱动路径,这样写有2个问题:

  1. 比较麻烦, 每次写自动化代码都 要指定路径。
  2. 如果你的代码给别人运行,他的电脑上存放浏览器驱动的路径不一定和你一样(比如他的电脑是苹果Mac电脑),得改脚本。

有什么好办法呢?我们可以把浏览器驱动 所在目录加入环境变量Path , 写代码时,就可以无需指定浏览器驱动路径了,像这样:wd = webdriver.Chrome()

设置完环境变量后,别忘了重启IDE(比如 PyCharm) 新的环境变量才会生效。

其他报错、报毒问题,参见:原理与安装 | 白月黑羽

其他浏览器

其他浏览器,如:360、Edge,参见:https://mp.weixin.qq.com/s/0mCAEcdRdyVKzDrueMUlpw

操控浏览器的基本方法

访问页面

使用Get方法访问某网站

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 初始化浏览器为chrome浏览器
browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

# 访问百度首页
browser.get(r'https://www.baidu.com/')

# 关闭浏览器
browser.close()

设置浏览器大小

get_window_size()获取窗口大小
set_window_size()方法可以用来设置浏览器大小(就是分辨率)
maximize_window则是设置浏览器为全屏!

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

# 获取当前窗口大小
browser.get(r'https://www.baidu.com')
print(browser.get_window_size())  # {'width': 838, 'height': 892}
time.sleep(2)

# 设置浏览器大小:全屏
browser.maximize_window()
time.sleep(2)

# 设置分辨率 500*500
browser.set_window_size(500, 500)
time.sleep(2)

# 设置分辨率 1000*800
browser.set_window_size(1000, 800)
time.sleep(2)

# 关闭浏览器
browser.close()

设置代理

网上搜的结果不能用,问ChatGPT问出了答案。

代理类型:HTTP代理

方式1:为浏览器驱动设置了环境变量

python 复制代码
from selenium import webdriver

# 设置代理IP的地址和端口号,类型为 HTTP 代理
proxy_address = "127.0.0.1:8080"
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--proxy-server=http://" + proxy_address)

# 浏览器驱动访问网站
driver = webdriver.Chrome(options=chrome_options)
driver.get("https://www.baidu.com")

# 关闭浏览器
driver.quit()

方式2:指明浏览器驱动位置

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

# 设置代理IP的地址和端口号,类型为 HTTP 代理
proxy_address = "127.0.0.1:8080"
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--proxy-server=http://" + proxy_address)

# 浏览器驱动访问网站
driver = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'), options=chrome_options)
driver.implicitly_wait(10)
driver.get('https://cn.bing.com/')

# 关闭浏览器
driver.quit()

获取页面基础属性

一些基础属性如:网页标题、网址、浏览器名称、页面源码等信息。

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
browser.implicitly_wait(5)
browser.get(r'https://www.baidu.com')

# 获取当前窗口标题
print(browser.title)

# 获取当前窗口URL地址
print(browser.current_url)

# 浏览器名称
print(browser.name)

# 网页源码
print(browser.page_source)

# 关闭浏览器
browser.close()

无界面浏览器、截图

python 复制代码
from selenium import webdriver

# 无界面的浏览器
option = webdriver.ChromeOptions()
option.add_argument("headless")
browser = webdriver.Chrome(options=option)

# 访问百度首页
browser.get(r'https://www.baidu.com/')

# 截图预览
browser.get_screenshot_as_file('截图.png')

# 关闭浏览器
browser.close()

刷新页面

刷新页面是我们在浏览器操作时很常用的操作,这里refresh()方法可以用来进行浏览器页面刷新。

python 复制代码
from selenium import webdriver
import time

browser = webdriver.Chrome()

# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)

try:
    # 刷新页面
    browser.refresh()
    print('刷新页面')
except Exception as e:
    print('刷新失败')

# 关闭浏览器
browser.close()

前进后退

前进后退是我们在使用浏览器时非常常见的操作,这里forward()方法可以用来实现前进,back()可以用来实现后退。

python 复制代码
from selenium import webdriver
import time

browser = webdriver.Chrome()

# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)

# 打开必应页面
browser.get(r'https://cn.bing.com/')
time.sleep(2)

# 后退到百度页面
browser.back()
time.sleep(2)

# 前进的必应页面
browser.forward()
time.sleep(2)

# 关闭浏览器
browser.close()

浏览器窗口切换

测试网站:https://cdn2.byhy.net/files/selenium/sample3.html

实现目标:访问必应网站,执行一次搜索,然后返回到测试网站

这里主要涉及到窗口切换,可以使用:wd.switch_to.window(handle),这是一个列表对象,里面包括了当前浏览器里面所有的窗口句柄。所谓句柄,大家可以想象成对应网页窗口的一个ID。

此外,我们可以设置一个当前窗口让它记住,方便随时切回来。

python 复制代码
# mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle

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

得到如下代码:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/sample3.html')

# 点击按钮,打开必应
link = wd.find_element(By.TAG_NAME, 'a')
link.click()
time.sleep(3)

# 记住当前窗口
mainWindow = wd.current_window_handle

# 找到必应窗口
for hanle in wd.window_handles:
    wd.switch_to.window(hanle)  # 切窗口
    if 'Bing' in wd.title:  # 发现某窗口的网页标题中有"Bing"
        break  # 找到了
print(wd.title)  # 输出切到的新窗口的title
# 开始搜索
wd.find_element(By.ID, 'sb_form_q').send_keys('白月黑羽\n')
time.sleep(3)

# 回退到之前记住的窗口
wd.switch_to.window(mainWindow)

time.sleep(3)
wd.close()

弹出对话框

有些网站点击的时候,会弹出的对话框。那么如果点出弹框,获取弹框内容,以及关闭弹框呢?

测试网站:https://cdn2.byhy.net/files/selenium/test4.html
Alert弹框

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

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test4.html')

# --- alert ---
wd.find_element(By.ID, 'b1').click()

# 打印 弹出框 提示信息
print(wd.switch_to.alert.text)
time.sleep(3)

# 点击 OK 按钮
wd.switch_to.alert.accept()

time.sleep(3)
wd.quit()

Confirm弹框

Confirm弹出框,主要是让用户确认是否要进行某个操作

python 复制代码
# 如果我们想点击 OK 按钮,可以用 accept 方法
driver.switch_to.alert.accept()

# 如果我们想点击 Cancel 按钮, 可以用 dismiss 方法
driver.switch_to.alert.dismiss()
python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test4.html')

# --- confirm ---
wd.find_element(By.ID, 'b2').click()

# 打印 弹出框 提示信息
print(wd.switch_to.alert.text)

# 点击 OK 按钮
wd.switch_to.alert.accept()

# --- confirm ---
wd.find_element(By.ID, 'b2').click()

# 点击 取消 按钮
wd.switch_to.alert.dismiss()

time.sleep(3)
wd.quit()

Prompt弹框

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

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

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test4.html')

# --- prompt ---
wd.find_element(By.ID, 'b3').click()

# 获取 alert 对象
alert = wd.switch_to.alert

# 打印 弹出框 提示信息
print(alert.text)

# 输入信息,并且点击 OK 按钮 提交
alert.send_keys('web自动化 - selenium')
alert.accept()

# 点击 Cancel 按钮 取消
wd.find_element(By.ID, 'b3').click()
alert = wd.switch_to.alert
alert.dismiss()

time.sleep(3)
wd.quit()

冻结界面

当鼠标放到某个位置,会出现一些内容,如果想获取这些内容对应的位置,发现 F12不好用了,甚至有些时候通过"审查元素"都找不到(或者只能找到1个,不方便找其他的,如下图中的"影响推广"),这个时候就需要冻结界面了。

我们可以在控制台中输入debugger实现冻结效果。

那么,如果延迟数秒再冻结,就可以解决悬停显示问题了:

复制代码
# 在 5000毫秒后,执行 debugger 命令
# debug状态有个特性,界面被冻住,不管我们怎么点击界面都不会触发事件。
setTimeout(function(){debugger}, 5000)

操控元素的基本方法

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

操控元素通常包括:

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

点击元素

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

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

python 复制代码
element = wd.find_element(By.ID,'go')
element.click()

输入、点击、结果等待

演示如何输入一个内容,点击按钮,等待加载结果

假设要获取搜索结果中的第一个结果内容,这里要添加一个休眠时间,因为搜索出结果是需要时间的!

我想的是挺好的,但是代码一跑就出错了,抛了异常:NoSuchElementException,意思就是在当前的网页上 找不到该元素, 就是找不到 id 为 1 的元素。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

wd = webdriver.Chrome()
wd.get('https://www.byhy.net/_files/stock1.html')

element = wd.find_element(By.ID, 'kw')
element.send_keys('通讯\n')

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

wd.quit()

出现这个问题的原因在于网站还没有来得及返回搜索结果,代码就索要结果了。因此代码需要等待网站搜索出结果才行,那要等多久呢?直接设置个sleep休眠显然不好,不如让代码反复try:

python 复制代码
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

wd = webdriver.Chrome()
wd.get('https://www.byhy.net/_files/stock1.html')

element = wd.find_element(By.ID, 'kw')
element.send_keys('通讯\n')
while True:
    try:
        element = wd.find_element(By.ID, '1')
        print(element.text)
        break
    except:
        # 添加一个休眠,防止网站响应慢导致程序进入死循环
        time.sleep(1)

wd.quit()

# 结果
国美通讯
代码:600898

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

当发现元素没有找到的时候, 并不立即返回找不到元素的错误。而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,或者超出指定最大等待时长,这时才抛出异常(如果是 find_elements 之类的方法, 则是返回空列表)。

Selenium 的 Webdriver 对象有个方法叫implicitly_wait,可以称之为"隐式等待",或者"全局等待"。该方法接受一个参数,用来指定最大等待时长。如果我们加入如下代码:wd.implicitly_wait(10),那么后续所有的find_element或者find_elements之类的方法调用都会采用上面的策略。如果找不到元素, 每隔半秒钟再去界面上查看一次, 直到找到该元素, 或者过了10秒最大时长。

特别警告⚠:implicitly_wait是为了解决找不到的问题,但是找到的也有可能是错误的。

当你网购时选择收件地址,选择省、市、县......,你怎么切换都有结果,但是你需要等"市"加载完之后,才能选择"县",这个时候implicitly_wait就不好使了,还是需要sleep一下。

python 复制代码
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

wd = webdriver.Chrome()
wd.implicitly_wait(10)  # 最久等待10秒
wd.get('https://www.byhy.net/_files/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)

wd.quit()

# 结果
国美通讯
代码:600898

清空 & 输入

使用WebElement对象的clear方法清空输入框内容

使用WebElement对象的send_keys方法输入内容

测试靶场:https://cdn2.byhy.net/files/selenium/test3.html

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://cdn2.byhy.net/files/selenium/test3.html')

element = browser.find_element(By.ID, 'input1')
element.clear()  # 清除输入框已有的字符串
element.send_keys('白月黑羽\n')  # 输入新字符串

input()

获取元素的文本内容

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

python 复制代码
element = wd.find_element(By.ID, '1')
print(element.text)

获取输入框里面的文字

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

测试靶场:https://www.byhy.net/_files/stock1.html

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

browser.get(r'https://www.byhy.net/_files/stock1.html')

element = browser.find_element(By.ID, 'kw')

element.send_keys('白月黑羽')
print(element.get_attribute('value'))

browser.close()

# 结果
白月黑羽

但是,有时候,元素的文本内容没有展示在界面上,或者没有完全完全展示在界面上。这时,用WebElement对象的text属性,获取文本内容,就会有问题。出现这种情况,可以尝试使用 element.get_attribute('innerText') ,或者 element.get_attribute('textContent')。

使用 innerText 和 textContent 的区别是,前者只显示元素可见文本内容,后者显示所有内容(包括display属性为none的部分)。具体可以参考这里

获取元素属性

通过WebElement对象的 get_attribute 方法来获取元素的属性值,比如要获取元素属性class的值,就可以使用 element.get_attribute('class')

练习靶场:https://www.byhy.net/_files/stock1.html

练习目标:获取"包钢股份"的属性值

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.byhy.net/_files/stock1.html')

element = browser.find_element(By.ID, '1')
print(element.text + '\n')
print(element.get_attribute('class'))

input()

# 结果
包钢股份
代码:600010

result-item

获取整个元素对应的HTML

要获取整个元素对应的HTML文本内容,可以使用element.get_attribute('outerHTML')

如果,只是想获取某个元素内部的HTML文本内容,可以使用element.get_attribute('innerHTML')

测试靶场:https://www.byhy.net/_files/stock1.html

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))

browser.get(r'https://www.byhy.net/_files/stock1.html')

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

# 获取整个元素对应的HTML文本内容
print(element.get_attribute('outerHTML'))
# 获取某个元素内部的HTML文本内容
print(element.get_attribute('innerHTML'))

browser.close()

frame切入切出

获取frame元素或者iframe元素的内部数据时,需要先切入进去才能获取。

测试网站:https://cdn2.byhy.net/files/selenium/sample2.html

假设我们要获取所有的植物,但是会发现下面的代码运行结果为空。仔细观察源代码会发现,要找的植物位于iframe中。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')

# 根据 class name 选择元素,返回的是 一个列表
elements = wd.find_elements(By.CLASS_NAME, 'plant')

for element in elements:
    print(element.text)

在html语法中,frame元素或者iframe元素的内部会包含一个被嵌入的另一份html文档。在我们使用selenium打开一个网页时,我们的操作范围缺省是当前的html,并不包含被嵌入的html文档里面的内容。如果我们要操作被嵌入的html文档中的元素,就必须切换操作范围到被嵌入的文档中。

使用 WebDriver 对象的 switch_to 属性进行切换,像这样:wd.switch_to.frame(frame_reference)

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

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')

# 切换到iframe中
wd.switch_to.frame('frame1')

elements = wd.find_elements(By.CLASS_NAME, 'plant')
for element in elements:
    print(element.text)

# 结果
土豆
洋葱
白菜

还可以通过 frame 所对应的 WebElement 对象切换进去:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')

# 切换到iframe中
element = wd.find_element(By.CSS_SELECTOR, 'iframe[src="sample1.html"]')
wd.switch_to.frame(element)

elements = wd.find_elements(By.CLASS_NAME, 'plant')
for element in elements:
    print(element.text)


# 结果
土豆
洋葱
白菜

最后,演示切入和切出,并获取点击"外部按钮"点出来的内容

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')

# 切换到iframe中,获取植物
# element = wd.find_element(By.CSS_SELECTOR, 'iframe[src="sample1.html"]')
# wd.switch_to.frame(element)
wd.switch_to.frame('frame1')

elements = wd.find_elements(By.CLASS_NAME, 'plant')
for element in elements:
    print(element.text)

# 切出,回到最外部的HTML中
wd.switch_to.default_content()

# 点击外部的一个按钮
wd.find_element(By.ID, 'outerbutton').click()

# 获取点击出来的内容
elements = wd.find_elements(By.CSS_SELECTOR, '#add li')
for element in elements:
    print(element.get_attribute('outerHTML'))

time.sleep(2)
wd.quit()

# 结果
土豆
洋葱
白菜
<li>你点击了外部按钮</li>

高级方法1:模拟鼠标

这里需要导入ActionChains 类:

python 复制代码
from selenium.webdriver.common.action_chains import ActionChains

鼠标移动

目标:让鼠标移动到百度首页的"更多"那里。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://www.baidu.com/')

from selenium.webdriver.common.action_chains import ActionChains
ac = ActionChains(wd)

# 获取移动的位置 对应的元素
element = wd.find_element(By.CSS_SELECTOR, '[name="tj_briicon"]')
# 移动到指定位置
ac.move_to_element(element).perform()

time.sleep(3)

wd.quit()

鼠标左右键

左键就是click(),很多地方都有演示。

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)  # 最久等待10秒
wd.get('https://www.byhy.net/_files/stock1.html')
time.sleep(2)

# 输入
element = wd.find_element(By.ID, 'kw')
element.send_keys('通讯')
time.sleep(2)

# 点击
element = wd.find_element(By.ID, 'go')
element.click()

time.sleep(2)
wd.quit()

鼠标右键:

  • ActionChains(wd):调用ActionChains()类,并将浏览器驱动browser作为参数传入
  • context_click(right_click):模拟鼠标双击,需要传入指定元素定位作为参数
  • perform():执行ActionChains()中储存的所有操作,可以看做是执行之前一系列的操作
python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://www.baidu.com/')

# 定位到要右击的元素,这里选的新闻链接
right_click = wd.find_element(By.LINK_TEXT, '新闻')

# 执行鼠标右键操作
ActionChains(wd).context_click(right_click).perform()
time.sleep(2)

# 关闭浏览器
wd.close()

鼠标拖拽

使用方法:drag_and_drop(source,target)

演示靶场:https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.action_chains import ActionChains
import time

browser = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
browser.implicitly_wait(10)
browser.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
time.sleep(2)

# 切入 iframe
browser.switch_to.frame('iframeResult')

# 开始位置
source = browser.find_element(By.CSS_SELECTOR, '#draggable')

# 结束位置
target = browser.find_element(By.CSS_SELECTOR, "#droppable")

# 执行元素的拖放操作
ActionChains(browser).drag_and_drop(source, target).perform()
time.sleep(5)

# 关闭浏览器
browser.close()

元素的选择方法

在selenium自动化中,最最常用的操作就是点击和输入,要实现这个操作,经常会碰到的一个问题就是怎么找到点击和输入的位置?有以下几种方法帮助我们找到这些位置。

基本方法

记不全没关系,下面有好用的CSS表达式

根据 id属性 选择元素

我们可以把 id 想象成元素的编号, 是用来在html中标记该元素的。根据规范, 如果元素有id属性 ,这个id 必须是当前html中唯一的。所以如果元素有id, 根据id选择元素是最简单高效的方式。

练习靶场:https://www.byhy.net/_files/stock1.html

实现目标:查询股票代码

  1. 获取id属性
  1. 运行代码。这里一旦进入断点,页面中就会执行输入"通讯",并且执行回车键,于是就查询出了结果。

如果我不使用回车键,而是想点击"查询"按钮呢?

代码如下:

  • 第11行代码:发起一个请求通过浏览器驱动转发给浏览器,告诉它,需要选择一个idkw的元素。浏览器 找到idkw的元素后,将结果通过 浏览器驱动 返回给 自动化程序, 所以 find_element 方法会返回一个 WebElement 类型的对象。这个WebElement 对象可以看成是对应 页面元素的遥控器。我们通过这个WebElement对象,就可以 操控对应的界面元素。
python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

# 创建 WebDriver 对象
wd = webdriver.Chrome()

# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.byhy.net/_files/stock1.html')

# 根据id选择元素,返回的就是该元素对应的WebElement对象
element = wd.find_element(By.ID, 'kw')

# 通过该 WebElement对象,就可以对页面元素进行操作了
# 比如输入字符串到 这个 输入框里
element.send_keys('通讯')

element = wd.find_element(By.ID,'go')
element.click()

# 正常结束程序
wd.quit()

根据 class属性 选择元素

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

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

练习靶场:https://cdn2.byhy.net/files/selenium/sample1.html
练习根据class属性选择元素

可以看到,所有的植物元素都有个class属性值为 plant,所有的动物元素都有个class属性值为 animal。

假设我要获取所有的动物:

于是得到脚本:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

# 创建 WebDriver 实例对象,指明使用chrome浏览器驱动
wd = webdriver.Chrome()

# WebDriver 实例对象的get方法 可以让浏览器打开指定网址
wd.get('https://cdn2.byhy.net/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)

# 结果
狮子
老虎
山羊

注意事项:

如果把wd.find_elements(By.CLASS_NAME, 'animal')改为wd.find_element(By.CLASS_NAME, 'animal'),那么返回的就是第一个class 属性为 animal 的元素, 也就是"狮子"

根据 tag名 选择元素

练习靶场:https://cdn2.byhy.net/files/selenium/sample1.html

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

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By

wd = webdriver.Chrome()

wd.get('https://cdn2.byhy.net/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)
    

升级一下,混合 id 属性和 tag 属性,来获取结果。

目标:获取红框中的数据

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/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)

# 结果
内层11
内层12
内层21

在后面学习了CSS表达式后,可以通过获取后代元素的方式简化代码:

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

elements = wd.find_elements(By.CSS_SELECTOR, '#container  span')

for element in elements:
    print(element.text)

根据 link定位、partial定位

这种方法顾名思义就是用来定位文本链接的:

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://www.baidu.com/')

# 使用CSS表达式
# wd.find_element(By.CSS_SELECTOR, '[href="http://news.baidu.com"]').click()

# 使用基本方法
wd.find_element(By.LINK_TEXT, '新闻').click()

time.sleep(6)
wd.close()

有时候一个超链接的文本很长,我们如果全部输入,既麻烦,又显得代码很不美观,这时候我们就可以只截取一部分字符串,用这种方法模糊匹配了。

python 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://www.baidu.com/')

# 模糊匹配"新闻"中的部分字符
wd.find_element(By.PARTIAL_LINK_TEXT, '闻').click()

time.sleep(6)
wd.close()

CSS表达式

如果我们要选择的元素没有id、class属性,或者有些我们不想选择的元素也有相同的id、class属性值,怎么办呢?这时候我们通常可以通过CSS selector语法选择元素。这是一种很强大好用的选择方法。

练习靶场:https://cdn2.byhy.net/files/selenium/sample1.html

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

CSS Selector同样可以根据tag名、id属性和class属性来选择元素。
1.1 根据tag名选择元素的CSS Selector语法非常简单,直接写上tag名即可,比如要选择所有的tag名为div的元素,就可以是这样,下面第8行和第9行代码功能是一样的。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

# elements = wd.find_elements(By.TAG_NAME, 'div')
elements = wd.find_elements(By.CSS_SELECTOR, 'div')

for element in elements:
    print(element.text)

wd.close()

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

尝试在下面的输入框中输入内容

下面第8行和第9行代码功能是一样的。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

# element = wd.find_element(By.ID, 'searchtext')
element = wd.find_element(By.CSS_SELECTOR, '#searchtext')

element.send_keys('你好啊')

wd.close()

1.3 根据class属性 选择元素的语法是在 class 值 前面加上一个点: .class值

下面第8行和第9行代码功能是一样的。

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

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

for element in elements:
    print(element.text)

# 结果
狮子
老虎
山羊

根据属性选择

css选择器专门提供了常用属性 id、class 选择的语法,那么其他的属性呢?

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

举例:我想获取这个链接地址

测试代码如下:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

elements = wd.find_elements(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')

for element in elements:
    print(element.get_attribute('outerHTML'))
wd.quit()

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

CSS还可以选择属性值包含某个字符串的元素比如,要选择a节点,里面的href属性包含了miitbeian字符串,就可以这样写:a[href*="miitbeian"]

python 复制代码
# 还可以选择属性值以某个字符串开头的元素。
# 比如,要选择a节点,里面的href属性以http开头,就可以这样写
a[href^="http"]

# 还可以选择属性值以某个字符串结尾的元素。比如,
# 要选择a节点,里面的href属性以gov.cn结尾,就可以这样写
a[href$="gov.cn"]

子元素、后代元素、逻辑或

练习靶场:https://cdn2.byhy.net/files/selenium/sample1.html

网页代码如下所示:

  • id 为 container 的div元素直接包含了 id 为 layer1 和 layer2 的两个div元素
  • id 为 container 的div元素间接包含了id 为 inner11 、inner12 、inner22 的元素和三个span类型的元素
  • layer1 和 layer2是container的直接子元素
  • inner11 、inner12 、inner22、layer1、layer2是container的后代元素
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>

上面的说法看懂看不懂无所谓,代码演示一下就懂了:

使用右箭头获取直接子元素

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

elements = wd.find_elements(By.CSS_SELECTOR, '#container  div')

for element in elements:
    print(element.get_attribute('outerHTML'))
    print('-----------------')

wd.quit()

使用空格获取后代元素

现在尝试获取所有的植物:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1.html')

elements = wd.find_elements(By.CSS_SELECTOR, '.plant  span')

for element in elements:
    print(element.get_attribute('outerHTML'))
    print(element.text)
    print('-----------------')

wd.quit()

验证CSS Selector

通过在浏览器中输入CSS Selector语法,可以很方便的判断语法是否正确,是否符合效果。

避免了在开发工具中反复调试代码。F12 ➡ Ctrl+F

进一步精准定位:#bottom > .footer1 span.copyright

**逻辑或:**使用逗号进行分割,运行优先级低

案例1:获取所有的动物和植物

测试网站:https://cdn2.byhy.net/files/selenium/sample1.html

使用"逻辑或"直接获取:.plant,.animal

案例2:获取唐诗中的所有作品和作者

测试网站:https://cdn2.byhy.net/files/selenium/sample1a.html

由于"逻辑或"的优先级低,因此使用:#t1 span , #t1 p

父元素的第n个子节点

我们可以指定选择的元素是父元素的第几个子节点,使用nth-child

案例1:

测试网站:https://cdn2.byhy.net/files/selenium/sample1b.html

使用:span:nth-child(2),获取第2个子元素是span的数据

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/sample1b.html')

elements = wd.find_elements(By.CSS_SELECTOR, 'span:nth-child(2)')
for element in elements:
    print(element.get_attribute('outerHTML'))
wd.quit()

# 结果
<span>李白</span>
<span>苏轼</span>

案例2:由于没有指明第2个子节点的标签名,因此所有的第2个子节点都会被选上。:nth-child(2)

这个东西可以正着数,也可以倒着数,如:父元素的倒数第n个子节点

使用:nth-last-child

测试网站:https://cdn2.byhy.net/files/selenium/sample1b.html

目标:获取父元素倒数第1个子节点是p类型的:p:nth-last-child(1)

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

我们可以指定选择的元素是父元素的第几个某类型的子节点,使用nth-of-type

举例如下,p:nth-of-type(2)匹配的子节点类型是p,这个p是第二个。

可以通俗的理解为,要从闺女(span)、侄子(span)、儿子(p)中寻找二儿子。

这个东西可以正着数,也可以倒着数,如:父元素的倒数第几个某类型的子节点
p:nth-last-of-type(2):获取子节点是p的,倒数第二个p

奇数节点和偶数节点

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

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

兄弟节点选择

相邻兄弟节点选择,使用+进行选择
p + span:p后面的同级别节点,第一个是span的就选上

后续所有兄弟节点选择,使用~进行选择
h3 ~ span:h3后面的同级别节点,只要是span,就全选上

更多CSS选择器的介绍,可以参考 CSS 选择器参考手册

Xpath选择器

上面已经学习了CSS,为什么还要学习 Xpath呢? 因为:

  • 有些场景用 css 选择 web 元素 很麻烦,而xpath却比较方便。
  • 另外 Xpath 还有其他领域会使用到,比如爬虫框架 Scrapy, 手机App框架 Appium。

测试网站:https://cdn2.byhy.net/files/selenium/test1.html

绝对路径、相对路径

**绝对路径:**从根节点开始,到某个节点,每层都依次写下来,每层之间用 / 分隔的表达式。

可以通过浏览器直接复制出绝对路径,十分方便,假设我这里要获取所有的城市。


python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(5)
wd.get(r'https://cdn2.byhy.net/files/selenium/test1.html')

elements = wd.find_elements(By.XPATH,'/html/body/div/div/div//p')

for element in elements:
    print(element.text)

wd.close()

# 结果
北京
上海
纽约
休斯顿
芝加哥

**相对路径:**用//开始,选择内部直接子节点使用/,选择内部所有子节点使用//

我还是习惯使用绝对路径,然后微调获取所有的外国城市://div/span/p

通配符

如果要选择所有div节点的所有直接子节点,可以使用表达式//div/*
*是一个通配符,对应任意节点名的元素,等价于CSS选择器div > *

代码如下:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(5)
wd.get(r'https://cdn2.byhy.net/files/selenium/test1.html')

elements = wd.find_elements(By.XPATH, '//div/*')
for element in elements:
    print(element.get_attribute('outerHTML'))

wd.close()

根据属性选择

Xpath 可以根据属性来选择元素。

根据属性来选择元素是通过这种格式来的 [@属性名='属性值']

注意:

  • 属性名注意前面有个@
  • 属性值一定要用引号, 可以是单引号,也可以是双引号

方式1:根据id属性选择

选择 id 为 west 的元素,可以这样//*[@id='west']/p

方式2:根据class属性选择

选择所有 select 元素中 class 为 single_choice 的元素,可以这样//select[@class='single_choice']
方式3:其他属性

比如选择具有 multiple 属性的所有页面元素 ,可以这样//*[@multiple](因为没有值,所以只写属性)

方式4:包含某字符

要选择 style 属性值包含 color 字符串的页面元素,可以这样//*[contains(@style,'color')]

要选择 style 属性值以 color 字符串 开头 的页面元素 ,可以这样//*[starts-with(@style,'color')]

要选择 style 属性值以某个字符串结尾的页面元素,大家推测是 //*[ends-with(@style,'color')], 但是很遗憾,这是xpath 2.0 的语法 ,目前浏览器支持的是 xpath 1的语法。

选择第几个

  1. 要选择p类型第2个的子元素,就是://p[2]

注意,选择的是 p 类型第2个的子元素;并非选择第2个子元素类型是p。

  1. 选择父元素为div的第2个子元素,不管是什么类型://div/*[2]
  2. 选取p类型倒数第1个子元素://p[last()]
  3. 选取p类型倒数第2个子元素://p[last()-1]

范围选择

xpath还可以选择子元素的次序范围。

  1. 选取option类型第1到2个子元素://option[position()<=2]或者//option[position()<3]

  2. 选择class属性为multi_choice的前3个子元素://*[@class='multi_choice']/*[position()<=3]

  3. 选择class属性为multi_choice的后3个子元素:

    //[@class='multi_choice']/[position()>=last()-2]

    为什么不是 last()-3 呢? 因为:
    last() 本身代表最后一个元素
    last()-1 本身代表倒数第2个元素
    last()-2 本身代表倒数第3个元素

逻辑或、父节点、兄弟节点✨

逻辑或

css有组选择(这里我称为"逻辑或"),可以同时使用多个表达式,多个表达式选择的结果都是要选择的元素。

比如,要选所有的option元素 和所有的 h4 元素,可以使用:

复制代码
Xpath选择的语法
//option | //h4

等同于CSS选择器
option , h4

再比如,要选所有的 class属性为 single_choice 和 class属性为 multi_choice 的元素,可以使用:

复制代码
Xpath选择的语法
//*[@class='single_choice'] | //*[@class='multi_choice']

等同于CSS选择器
.single_choice , .multi_choice

选择父节点⭐

Xpath可以选择父节点, 这是css做不到的。某个元素的父节点用 /.. 表示。

如果某个元素没有特征,但是它的子节点有特征, 就可以采用这种方法。

比如,要选择 id 为 china 的节点的父节点,可以这样写//*[@id='china']/..
后续兄弟节点

前面学过css选择器,要选择某个节点的后续兄弟节点,用波浪线。

Xpath也可以选择后续兄弟节点,用这样的语法following-sibling::

比如,要选择 class 为 single_choice 的元素的所有后续兄弟节点

复制代码
Xpath选择的语法
//*[@class='single_choice']/following-sibling::*

等同于CSS选择器
.single_choice ~ *

前面兄弟节点

xpath还可以选择前面的兄弟节点,用这样的语法preceding-sibling::

复制代码
要选择 class 为 single_choice 的元素的 所有 前面的兄弟节点,这样写
//*[@class='single_choice']/preceding-sibling::*

要选择 class 为 single_choice 的元素的前面最靠近的兄弟节点 , 这样写
//*[@class='single_choice']/preceding-sibling::*[1]

前面第2靠近的兄弟节点 , 这样写
//*[@class='single_choice']/preceding-sibling::*[2]

而 CSS选择器 目前还没有方法选择 前面的 兄弟节点!

更多Xpath语法,参见:XPath 教程

元素的选择场景:选择框

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

测试网址:https://cdn2.byhy.net/files/selenium/test2.html

请注意,演示的网站存在问题,点选其他框后,check不会发生变化,因此不再获取点选之后的结果了。

radio框

目标:先打印当前选中的老师名字,再选择小雷老师

网页代码:

html 复制代码
<div id="s_radio">
  <input type="radio" name="teacher" value="小江老师">小江老师<br>
  <input type="radio" name="teacher" value="小雷老师">小雷老师<br>
  <input type="radio" name="teacher" value="小凯老师" checked="checked">小凯老师
</div>

开发代码如下:

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test2.html')

# 获取当前选中的元素
element = wd.find_element(By.CSS_SELECTOR, '#s_radio input[checked="checked"]')
print('当前选中的是:' + element.get_attribute('value'))
time.sleep(3)

# 点选 小雷 老师
wd.find_element(By.CSS_SELECTOR, '#s_radio input[value="小雷老师"]').click()
time.sleep(3)

wd.quit()

checkbox框

这种框可以多选。如果某个选项已经勾选了,再点击会取消选择。

目标:只勾选小雷老师

思路:先把已经选中的选项全部点击一下,然后再单独点击目标按钮

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test2.html')

# 获取当前选中的元素,由于可能有多个按钮被选中,因此使用 find_elements
elements = wd.find_elements(By.CSS_SELECTOR, '#s_checkbox input[checked="checked"]')
for element in elements:
    print('当前选中的是:' + element.get_attribute('value'))
    element.click()
time.sleep(3)

# 点选 小雷 老师
wd.find_element(By.CSS_SELECTOR, '#s_checkbox input[value="小雷老师"]').click()
time.sleep(3)

wd.quit()

select框

radio框及checkbox框都是input元素,只是里面的type不同而已。select框则是一个新的select标签,Selenium专门提供了一个Select类进行操作。Select类提供了如下的方法:

python 复制代码
# 根据选项的value属性值,选择元素
select_by_value

# 根据选项的次序(从1开始),选择元素
select_by_index

# 根据选项的可见文本,选择元素
select_by_visible_text
python 复制代码
# 根据选项的value属性值,去除选中元素
deselect_by_value

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

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

# 去除选中所有元素
deselect_all

Select单选框

Select单选框操作比较简单:不管原来选的是什么,直接用Select方法重新选择即可。

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

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import Select
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.implicitly_wait(10)
wd.get('https://cdn2.byhy.net/files/selenium/test2.html')

element = wd.find_element(By.ID, 'ss_single')
select = Select(element)  # 创建Select对象

# 通过 Select 对象选中小雷老师
select.select_by_visible_text("小江老师")
time.sleep(3)

wd.quit()

Select多选框

用select类的deselect_all方法,全部取消勾选

select_by_visible_text方法选择 小雷老师 和 小凯老师

python 复制代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import Select
import time

wd = webdriver.Chrome(service=Service(r'D:\tools\selenium\chromedriver.exe'))
wd.get('https://cdn2.byhy.net/files/selenium/test2.html')

# 创建Select对象
element = wd.find_element(By.CSS_SELECTOR, '#ss_multi')
select = Select(element)

# 清除所有 已经选中 的选项
select.deselect_all()

# 选择小雷老师 和 小凯老师
select.select_by_visible_text("小雷老师")
select.select_by_visible_text("小凯老师")

time.sleep(3)
wd.quit()

参考

2万字带你了解Selenium全攻略
2万字带你了解Selenium全攻略_selenium 2万字 教程_可以叫我才哥的博客-CSDN博客
原理与安装 | 白月黑羽

相关推荐
程序员三藏6 小时前
如何用Selenium实现自动化?
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
程序员三藏1 天前
Selenium无法定位元素的几种解决方案
自动化测试·软件测试·python·selenium·测试工具·职场和发展·测试用例
小陈的进阶之路2 天前
Selenium元素定位
python·selenium
紫丁香2 天前
Selenium自动化测试详解1
python·selenium·测试工具·ui
爱敲代码的菜菜3 天前
【测试】自动化测试
css·selenium·测试工具·junit·自动化·xpath
爱敲代码的菜菜3 天前
【测试】Selenium
selenium·测试工具·xpath·webdriver·cssselector
若惜4 天前
selenium自动化测试web自动化测试 框架封装Pom
前端·python·selenium
念越5 天前
自动化测试入门指南:Selenium环境搭建+第一个实战案例
自动化测试·selenium·测试工具·蓝桥杯