Web自动化测试--selenium

 🔥 交流讨论:欢迎加入我们一起学习!

🔥 资源分享耗时200+小时精选的「软件测试」资料包

🔥 教程推荐:火遍全网的《软件测试》教程  

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

一、selenium介绍

Selenium 是支持web浏览器自动化的一系列工具和库的综合项目,能够进行自动化网页浏览器操作,广泛应用于测试和自动化行业。它可以模拟用户在浏览器中执行的操作,如点击按钮、填写表单、导航到不同页面等。Selenium 提供了一组强大的 API 和工具,使开发人员能够以编程方式控制浏览器,从而实现自动化测试、网页抓取和跨浏览器测试等任务。

官网:https://www.selenium.dev/zh-cn/documentation/

特点:

多语言支持:Selenium 提供了多种编程语言的 API,例如 Java、Python、C#、Ruby 等,使开发人员可以使用自己熟悉的语言编写测试脚本。
跨浏览器兼容性:Selenium 支持各种流行的浏览器,包括Chrome、Firefox、Safari 和 Edge等,可以在不同浏览器上执行测试并验证应用程序的一致性。
强大的定位机制:Selenium 提供了丰富的元素定位方法,如通过 ID、CSS、XPath 等定位方式,使得开发人员可以准确定位页面上的元素并与之交互。
自动化与集成:Selenium 可以与常见的集成工具和测试框架(如 TestNG、JUnit、Cucumber 等)无缝集成,使得测试和自动化过程更加灵活高效。
支持分布式测试:Selenium Grid 允许在多台计算机上并行执行测试,以加速测试执行和提高效率。
丰富的社区支持:Selenium 拥有庞大的开发者社区和活跃的维护者团队,提供了丰富的文档、教程和示例,方便开发人员学习和解决问题。

二、环境搭建

1、安装 Selenium 库

pip install selenium

2、获取浏览器的驱动程序

1.1 查看谷歌浏览器版本(以谷歌浏览器作为示例)
Chrome -> 右上角三个点-> 设置 -> 关于Google Chrome

1.2 下载对应版本的chromedriver
谷歌浏览器chromedriver:CNPM Binaries Mirror

3 配置 ChromeDriver 路径

下载解压后得到 chromedriver.exe,将其放入 Python 安装路径下的 Scripts 目录

4 编写 Selenium 脚本验证安装

新建python文件,命名open-web.py,使用 ChromeDriver 创建一个 Chrome 浏览器实例,打开 "https://www.example.com" 网页并最后关闭浏览器

from selenium import webdriver# 创建 ChromeDriver 实例
driver = webdriver.Chrome()
# 打开网页,填写你需要的网站
driver.get("https://www.example.com")
# 执行其他操作
# ...
# 关闭浏览器0...........
driver.quit()

三、基本组成

1. 使用驱动实例开启会话

from selenium import webdriver
driver = webdriver.Chrome()

2. 在浏览器上执行操作

导航到网页

driver.get("https://www.selenium.dev/selenium/web/web-form.html")

3. 请求浏览器信息

请求一系列关于浏览器的信息, 包括窗口句柄、浏览器尺寸/位置、cookie、警报等

title = driver.title

4. 建立等待策略

等待一段时间使元素处于可交互状态

driver.implicitly_wait(0.5)
time.sleep(0.5)

5. 发送命令查找元素

text_box = driver.find_element(by=By.NAME, value="my-text")
submit_button = driver.find_element(by=By.CSS_SELECTOR, value="button")

6. 操作元素

text_box.send_keys("Selenium")
submit_button.click()

7. 获取元素信息

value = message.text

8. 结束会话

driver.quit()

四、元素

1.查询

根据提供的定位值定位元素.

#评估DOM元素,查找匹配的第一个元素
driver.find_element(By.CLASS_NAME, "tomatoes")#评估DOM子集,缩小范围,通过父元素定位子元素
fruits = driver.find_element(By.ID, "fruits")
fruit = fruits.find_element(By.CLASS_NAME,"tomatoes")#使用 CSS 或 XPath 在单个命令中找到此元素
fruit = driver.find_element(By.CSS_SELECTOR,"#fruits .tomatoes")#获取所有匹配元素
plants = driver.find_elements(By.TAG_NAME, "li")#循环访问集合并确定所需的集合
elements = driver.find_elements(By.TAG_NAME, 'p')
for e in elements:print(e.text)

2. 定位器

在DOM中标识一个或多个特定元素的方法
新版本:

名称含义定位元素
类名定位class属性与搜索值匹配的元素(不允许使用复合类名)By.ID
CSS 选择器定位 CSS 选择器匹配的元素By.XPATH
编号定位 id 属性与搜索值匹配的元素By.LINK_TEXT
名字定位 name 属性与搜索值匹配的元素By.PARTIAL_LINK_TEXT
链接文本定位link text可视文本与搜索值完全匹配的锚元素By.NAME
部分链接文本定位link text可视文本部分与搜索值部分匹配的锚点元素。 如果匹配多个元素,则只选择第一个元素。By.TAG_NAME
标签名称定位标签名称与搜索值匹配的元素By.CLASS_NAME
xpath定位与 XPath 表达式匹配的元素By.CSS_SELECTOR

例:
单个元素:driver.find_element(By.CSS_SELECTOR, "#fname")
多个元素:driver.find_elements(By.CSS_SELECTOR, "#fname")

旧版本:

定位元素含义
find_element_by_id通过元素 id 进行定位
find_element_by_name通过元素名称进行定位
find_element_by_xpath通过 xpath 表达式进行定位
find_element_by_link_text通过完整超链接文本进行定位
find_element_by_partial_link_text通过部分超链接文本进行定位
find_element_by_tag_name通过标记名称进行定位
find_element_by_class_name通过类名进行定位
find_element_by_css_selector通过 css 选择器进行定位

例:
单个元素:driver.find_element_by_id('username')
多个元素:driver.find_elements_by_id('username')

3. 信息

3.1 是否显示

是否正确显示在网页上. 返回一个 Boolean 值, 如果连接的元素显示在当前的浏览器上下文中,则为True,否则返回false
is_email_visible = driver.find_element(By.NAME, "email_input").is_displayed()

3.2 是否启用

检查所连接的元素在网页上是启用还是禁用状态。 返回一个布尔值,如果在当前浏览上下文中是启用状态,则返回 true,否则返回 false。
value = driver.find_element(By.NAME, 'button_input').is_enabled()

3.3 是否被选定

此方法确认相关的元素是否已选定,常用于复选框、单选框、输入框和选择元素中。
该方法返回一个布尔值,如果在当前浏览上下文中 选择了 引用的元素,则返回 True,否则返回 False。
value = driver.find_element(By.NAME, "checkbox_input").is_selected()

3.4 获取元素标签名

此方法用于获取在当前浏览上下文中具有焦点的被引用元素的TagName。
attr = driver.find_element(By.NAME, "email_input").tag_name

3.5 位置和大小

用于获取参照元素的尺寸和坐标。
提取的数据主体包含以下详细信息:

元素左上角的X轴位置
元素左上角的y轴位置
元素的高度
元素的宽度

res = driver.find_element(By.NAME, "range_input").rect

3.6 获取元素CSS值

获取当前浏览上下文中元素的特定计算样式属性的值。
cssValue = driver.find_element(By.ID, "namedColor").value_of_css_property('background-color')

3.7 文本内容

获取特定元素渲染后的文本内容。
text = driver.find_element(By.ID, "justanotherlink").text

3.8 获取特性或属性

获取与 DOM 属性关联的运行时的值。 它返回与该元素的 DOM 特性或属性关联的数据。

email_txt = driver.find_element(By.NAME, "email_input")
value_info = email_txt.get_attribute("value")#获取链接
例:article.find_elements_by_xpath("/a")[j].get_attribute('href') 

五、交互

1. 元素交互

1.1 点击

元素点击命令执行在元素中央。如果元素中央由于某些原因被遮挡 , Selenium将返回一个元素点击中断错误。
driver.find_element(By.NAME, "input").click()

1.2 发送键位

元素发送键位命令将录入提供的键位到编辑的元素。通常, 这意味着元素是具有文本类型的表单的输入元素或具有内容可编辑属性的元素. 如果不可编辑, 则返回无效元素状态错误。
driver.find_element(By.NAME, "email_input").send_keys("abc")

1.3 清除

元素清除命令重置元素的内容. 这要求元素可编辑, 且可重置。 通常, 这意味着元素是具有文 类型的表单的输入元素或具有内容可编辑属性的元素. 如果不满足这些条件, 将返回无效元素状态错误.
driver.find_element(By.NAME, "email_input").clear()

2. 浏览器交互(获取浏览器信息)

2.1 获取标题

driver.title

2.2 获取当前url

driver.current_url

3. 浏览器导航

3.1 打开网站

driver.get("https://selenium.dev")

3.2 后退

driver.back()

3.3 前进

driver.forward()

3.4 刷新

driver.refresh()

4. 弹窗

4.1 Alerts 警告框

它显示一条自定义消息, 以及一个用于关闭该警告的按钮, 在大多数浏览器中标记为"确定"(OK). 在大多数浏览器中, 也可以通过按"关闭"(close)按钮将其关闭, 但这始终与“确定”按钮具有相同的作用

# 导入所需的模块和类
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 实例化浏览器驱动
driver = webdriver.Chrome()
# 点击链接以激活弹窗
driver.find_element(By.LINK_TEXT, "See an example alert").click()
# 等待弹窗显示并将其存储在变量中
wait = WebDriverWait(driver, 10)
alert = wait.until(EC.alert_is_present())
# 将弹窗文本存储在变量中
text = alert.text
# 点击确定按钮
alert.accept()
#点击取消按钮
alert.dismiss()

4.2 Confirm 确认框

确认框类似于警告框, 不同之处在于用户还可以选择取消消息

# 点击链接以激活确认框
driver.find_element(By.LINK_TEXT, "See a sample confirm").click()
# 等待确认框的出现,expected_conditions重命名为EC
wait = WebDriverWait(driver, 10)
wait.until(EC.alert_is_present())
# 将确认框存储在变量中以便复用
alert = driver.switch_to.alert
# 将确认框文本存储在变量中
text = alert.text
# 点击取消按钮
alert.dismiss()

4.3 Prompt 提示框

提示框与确认框相似, 不同之处在于它们还包括文本输入. 与处理表单元素类似, 您可以使用WebDriver的sendKeys来填写响应. 这将完全替换占位符文本. 按下取消按钮将不会提交任何文本

# 等待提示框的出现
wait = WebDriverWait(driver, 10)
wait.until(EC.alert_is_present())
# 将提示框存储在变量中以便复用
alert = Alert(driver)
# 输入消息
alert.send_keys("Selenium")
# 点击确定按钮
alert.accept()

5. 窗口和标签页

5.1 获取窗口句柄

WebDriver 没有区分窗口和标签页。如果你的站点打开了一个新标签页或窗口,Selenium 将允许您使用窗口句柄来处理它。 每个窗口都有一个唯一的标识符,该标识符在单个会话中保持持久性。你可以使用以下方法获得当前窗口的窗口句柄
driver.current_window_handle

5.2 切换窗口或标签页

单击在 <a href=“https://seleniumhq.github.io"target="_blank”>新窗口 中打开链接, 则屏幕会聚焦在新窗口或新标签页上,但 WebDriver 不知道操作系统认为哪个窗口是活动的。 要使用新窗口,您需要切换到它。 如果只有两个选项卡或窗口被打开,并且你知道从哪个窗口开始, 则你可以遍历 WebDriver, 通过排除法可以看到两个窗口或选项卡,然后切换到你需要的窗口或选项卡。

# 存储原始窗口的 ID
original_window = driver.current_window_handle
# 检查一下,我们还没有打开其他的窗口
assert len(driver.window_handles) == 1
# 单击在新窗口中打开的链接
driver.find_element(By.LINK_TEXT, "new window").click()
# 等待新窗口或标签页
wait.until(EC.number_of_windows_to_be(2))
# 循环执行,直到找到一个新的窗口句柄
for window_handle in driver.window_handles:if window_handle != original_window:driver.switch_to.window(window_handle)break
# 等待新标签页完成加载内容wait.until(EC.title_is("xxxx"))

5.3 创建新窗口或新标签页并且切换

创建一个新窗口 (或) 标签页,屏幕焦点将聚焦在新窗口或标签在上。您不需要切换到新窗口 (或) 标签页。如果除了新窗口之外, 您打开了两个以上的窗口 (或) 标签页,您可以通过遍历 WebDriver 看到两个窗口或选项卡,并切换到非原始窗口。

# 打开新标签页并切换到新标签页
driver.switch_to.new_window('tab')
# 打开一个新窗口并切换到新窗口
driver.switch_to.new_window('window')

5.4 关闭窗口或标签页

#关闭标签页或窗口
driver.close()
#切回到之前的标签页或窗口
driver.switch_to.window(original_window)

5.5 在会话结束时退出浏览器

完成了浏览器会话,应该调用 quit 退出,而不是 close 关闭
driver.quit()
退出将会:

  • 关闭所有与 WebDriver 会话相关的窗口和选项卡
  • 结束浏览器进程
  • 结束后台驱动进程
  • 通知 Selenium Grid 浏览器不再使用,以便可以由另一个会话使用它(如果您正在使用 Selenium Grid)

5.6 获取窗口大小

# 分别获取每个尺寸
width = driver.get_window_size().get("width")
height = driver.get_window_size().get("height")
# 或者存储尺寸并在以后查询它们
size = driver.get_window_size()
width1 = size.get("width")
height1 = size.get("height")

5.7 设置窗口大小

driver.set_window_size(1024, 768)

5.8 窗口位置

# 分别获取每个尺寸
x = driver.get_window_position().get('x')
y = driver.get_window_position().get('y')# 或者存储尺寸并在以后查询它们
position = driver.get_window_position()
x1 = position.get('x')
y1 = position.get('y')

5.9 设置窗口位置

# 将窗口移动到主显示器的左上角
driver.set_window_position(0, 0)

5.10 最大化窗口

driver.maximize_window()

5.11 最小化窗口

driver.minimize_window()

5.12 全屏窗口

填充整个屏幕,类似于在大多数浏览器中按下 F11
driver.fullscreen_window()

5.12 屏幕截图

用于捕获当前浏览上下文的屏幕截图. WebDriver端点屏幕截图 返回以Base64格式编码的屏幕截图
driver.save_screenshot('./image.png')

5.13 元素屏幕截图

ele = driver.find_element(By.CSS_SELECTOR, 'h1')
ele.screenshot('./image.png')

5.14 执行脚本

在当前frame或者窗口的上下文中,执行JavaScript代码片段

# 存储标题元素
header = driver.find_element(By.CSS_SELECTOR, "h1")
# 执行 JavaScript 代码以捕获标题元素的 innerText
inner_text = driver.execute_script('return arguments[0].innerText', header)
# 执行JavaScript代码,将页面滚动到底部
js = "window.scrollTo(0, document.body.scrollHeight);"
driver.execute_script(js)

5.15 打印页面

from selenium.webdriver.common.print_page_options import PrintOptions
# 实例化打印选项对象
print_options = PrintOptions()
print_options.page_ranges = ['1-2']
# 打开打印页的网址
driver.get("printPage.html")
# 执行打印操作,并获取打印后的页面内容的 Base64 编码
base64code = driver.print_page(print_options)

6 Cookies

Cookie是从网站发送并存储在您的计算机中的一小段数据. Cookies主要用于识别用户并加载存储的信息。

6.1 添加 Cookie

这个方法常常用于将cookie添加到当前访问的上下文中. 添加Cookie仅接受一组已定义的可序列化JSON对象. 这里是一个链接, 用于描述可接受的JSON键值的列表
首先, 您需要位于有效Cookie的域上. 如果您在开始与网站进行交互之前尝试预设cookie, 并且您的首页很大或需要一段时间才能加载完毕, 则可以选择在网站上找到一个较小的页面 (通常404页很小, 例如 http://example.com/some404page)
将 Cookie 添加到当前浏览器上下文中
driver.add_cookie({"name": "key", "value": "value"})

6.2 获取命名的 Cookie

此方法返回与cookie名称匹配的序列化cookie数据中所有关联的cookie.

# 将 Cookie 添加到当前浏览器上下文中
driver.add_cookie({"name": "key", "value": "value"})
# 使用命名的 cookie 'key' 获取 cookie 详细信息
print(driver.get_cookie("key"))

6.3 获取全部 Cookies

driver.get_cookies()

6.4 删除 Cookie

driver.delete_cookie("key")

6.5 删除所有 Cookies

driver.delete_all_cookies()

6.6 Same-Site Cookie属性

此属性允许用户引导浏览器控制cookie, 是否与第三方站点发起的请求一起发送. 引入其是为了防止CSRF(跨站请求伪造)攻击.
Same-Site cookie属性接受以下两种参数作为指令

  • Strict:当sameSite属性设置为 Strict, cookie不会与来自第三方网站的请求一起发送.
  • Lax:将cookie sameSite属性设置为 Lax, cookie将与第三方网站发起的GET请求一起发送.
driver.add_cookie({"name": "key", "value": "value", 'sameSite': 'Strict'})
driver.add_cookie({"name": "key1", "value": "value", 'sameSite': 'Lax'})

7. IFrames和Frame

遇到嵌套的 iframe(内联框架),需要定位和切换到 iframe

7.1 使用 WebElement切换

iframe_element = driver.find_element_by_xpath("//iframe[@id='iframe_id']")
driver.switch_to.frame(iframe_element)

7.2 使用 name 或 id切换

# 通过 id 切换框架
driver.switch_to.frame('buttonframe')

7.3 使用索引切换

# 基于索引切换到第 2 个 iframe
iframe = driver.find_elements(By.TAG_NAME,'iframe')[1]
# 切换到选择的 iframe
driver.switch_to.frame(iframe)

7.4 切回主文档

完成 iframe 内的操作后,可以使用该方法将焦点切回到主文档。这将恢复驱动器的默认上下文,使后续的操作在主文档中进行
driver.switch_to.default_content()

六、等待

我们在做WEB自动化时,一般要等待页面元素加载完成后,才能执行操作,否则会报错找不到元素的错误
三种等待方式:

  • 隐式等待
  • 显示等待
  • 强制等待

1. 隐式等待

Selenium有一种内置的方式来自动等待称为隐式等待的元素。 可以使用浏览器选项中的超时功能或使用驱动程序方法(如下所示)设置隐式等待值。
这是一个全局设置,适用于整个会话的每个元素位置调用。 默认值为 ,这意味着如果未找到该元素,它将 立即返回错误。如果设置了隐式等待,驱动程序将等待 返回错误之前所提供值的持续时间。请注意,只要元素定位,驱动程序将返回元素引用,代码将继续执行, 因此,较大的隐式等待值不一定会增加会话的持续时间。缺点:有时需要的元素早已加载完成,个别元素加载慢,仍要等待页面全部加载完成才能执行下一步。
警告:不要混合隐式和显式等待。 这样做可能会导致不可预测的等待时间。 例如,将隐式等待设置为 10 秒 并显式等待 15 秒 可能会导致 20 秒后发生超时
driver.implicitly_wait(2)

2. 显式等待

显式等待是一种条件触发式的等待方式,指定某一条件直到这个条件成立时才会继续执行,可以设置超时时间,如果超过这个时间元素依然没被加载,就会抛出异常。
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//div//input"))
或者例下:

revealed = driver.find_element(By.ID, "revealed")
wait = WebDriverWait(driver, timeout=2)
driver.find_element(By.ID, "reveal").click()
wait.until(lambda d : revealed.is_displayed())
revealed.send_keys("Displayed")

3. 强制等待

利用time模块的sleep方法来实现,使程序等待一段时间
time.sleep(time)

4. 其他

Selenium提供了一些内置的用于显式等待的方法,位于expected_conditions类中,方法名称如表所示:

内置方法功能
title_is判断当前页面的title 是否等于预期内容
title_contains判断当前页面的 title 是否包含预期字符串
presence_of_element_located判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见
visibility_of_element_located判断某个元素是否可见
visibility_of判断某个元素是否可见
presence_of_all_elements_located判断是否至少有 1个元素存在于 dom 树中
text_to_be_present_in_element判断某个元素中的 text 是否包含了预期的字符串
text_to_be_present_in_element_value判断某个元素中的 value 属性是否包含了预期的字符串
frame tobe availableand switch toit判断该 frame 是否可以切换进去,如果可以的话,返回 True并且切换进去,否则返回 False
invisibility_of_element_located判断某个元素中是否不存在于 dom 树或不可见
element_tobeclickable判断某个元素中是否可见并且是 enable 的
stalenessof等待某个元素从 dom树中移除
element_tobeselected判断某个元素是否被选中了,一般用于下拉列表
element_located to be_selected判断某个元素是否被选中了,一般用于下拉列表
element_selection_statetobe判断某个元素的选中状态是否符合预期
element_located_selection_state_to_be判断某个元素的选中状态是否符合预期
alert_is_present判断页面上是否存在 alert 框

七、Web自动化测试示例

这是本人空闲时间写的一个招标信息获取自动化测试,里面基本涵盖了上述selenium内容,附加了注释,日期、excel表格读取和写入,贴近日常工作。

import time
import pandas as pd
import glob
import openpyxl
import traceback
from openpyxl.styles import Border, Side, Alignment
from datetime import datetime,timedelta
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 指定桌面路径
keyword_path = Path.home() / '招标/关键词'
save_path = Path.home() / '招标/结果'
# 获取当日日期``````````
today = time.strftime("%Y-%m-%d", time.localtime())
# 获取昨天的日期时间
yesterday = datetime.now() - timedelta(days=1)
yesterday_start = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
# 获取今天的日期时间
thetoday = datetime.now()
today_start = thetoday.replace(hour=0, minute=0, second=0, microsecond=0)
# 格式化日期时间
yesterday_formatted = yesterday_start.strftime("%Y-%m-%d %H:%M:%S")
today_formatted = today_start.strftime("%Y-%m-%d %H:%M:%S")
# 创建空的case列表
case = []
# 创建空的结果列表
result_list = []def read_excel():global case# 查找以"关键词"开头的Excel文件file_pattern = str(keyword_path / '关键词*.xlsx')file_list = glob.glob(file_pattern)# 读取第一个匹配到的Excel文件if file_list:file_path = file_list[0]df = pd.read_excel(file_path)case = df['关键字'].values.tolist()else:print("未找到匹配的Excel文件")#网站1数据获取
def search_results():global result_listglobal case# 打开第一个网站driver.get("http://118.64.254.72/freecms/site/juncai//cggg/index.html")# 等待页面加载完全time.sleep(2)#进入采购大厅purchase_notice1 = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//ul[@class='nav-tab']//li/span[contains(text(),'采购大厅')]")))purchase_notice1.click()# 等待搜索结果加载完全time.sleep(1)driver.find_element_by_xpath("//div[@class='layui-input-inline']//input[@id='stateDate']").send_keys(yesterday_formatted)driver.find_element_by_xpath("//div[@class='layui-input-inline']//input[@id='endDate']").send_keys(today_formatted)driver.find_element_by_xpath("//div[@class='layui-col-md3']//div[@class='layui-form-select']//i[@class ='layui-edge']").click()time.sleep(1)driver.find_element_by_xpath("//div[@class='layui-input-inline layui-form']//dl/dd[contains(text(),'全部')]").click()driver.find_element_by_xpath("//div[@class='layui-col-md3']//div[@class='layui-form-select']//i[@class ='layui-edge']").click()for i, keyword in enumerate(case):# 在第一个网站中搜索关键词keyword_str = str(keyword)search_input1 = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='identity']")))search_input1.clear()search_input1.send_keys(keyword)search_button = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//button[contains(@class,'layui-btn-normal')]")))search_button.click()# 等待搜索结果加载完全time.sleep(1)# 循环处理每一页的搜索结果while True:# 获取当前页的搜索结果articles = driver.find_elements(By.XPATH, "//div[@class='searchBoxBottom']//ul/li/a/..")if articles:for j, article in enumerate(articles):# 获取搜索结果的信息Announcement_title =article.find_elements_by_xpath("//div[@class='searchBoxBottom']//ul/li/a/span/p[@class='ellipsis']")[j].textAnnouncement_type = article.find_elements_by_xpath("//div[@class='searchBoxBottom']//ul/li/a/span[contains(@style,'margin-left: 42px')]")[j].textAnnouncement_time = article.find_elements_by_xpath("//div[@class='searchBoxBottom']//ul/li/a/span[contains(@style,'margin-right: 15px')]")[j].textAnnouncement_link = article.find_elements_by_xpath("//div[@class='searchBoxBottom']//ul/li/a")[j].get_attribute('href')result_list.append([keyword_str, Announcement_type, Announcement_title, Announcement_time, Announcement_link])time.sleep(1)# 判断是否存在下一页按钮next_page_buttons = driver.find_elements(By.XPATH, "//div[@class='pagination' and not(contains(@style,'display: none'))]//li[contains(text(),'>') and not(@class='disabled')]")if len(next_page_buttons) > 0:# 点击下一页按钮next_page_button = next_page_buttons[0]next_page_button.click()# 等待搜索结果加载完全time.sleep(1)else:breaktime.sleep(1)return result_list#创建excel保存数据
def creat_excel(result_list):# 创建Excel工作簿wb = openpyxl.Workbook()sheet = wb.activelast_row = 0# 设置表头sheet['A1'] = '关键词'sheet['B1'] = '公告类型'sheet['C1'] = '标题'sheet['D1'] = '时间'sheet['E1'] = 'URL'# 遍历result_list中的数据,并逐个写入Excel单元格for i, result in enumerate(result_list):keyword_str, Announcement_type, Announcement_title, Announcement_time, Announcement_link = result# 从第二行开始写入,因为第一行是表头last_row = i + 2sheet.cell(row=last_row, column=1, value=keyword_str)sheet.cell(row=last_row, column=2, value=Announcement_type)sheet.cell(row=last_row, column=3, value=Announcement_title)sheet.cell(row=last_row, column=4, value=Announcement_time)sheet.cell(row=last_row, column=5, value=Announcement_link)# 创建边框样式border = Border(left=Side(border_style="thin", color="000000"),right=Side(border_style="thin", color="000000"),top=Side(border_style="thin", color="000000"),bottom=Side(border_style="thin", color="000000"))# 设置边框样式、对齐方式和行高for row in sheet.iter_rows(min_row=1, max_row=last_row, min_col=1, max_col=5):for cell in row:cell.border = bordercell.alignment = Alignment(wrap_text=True, vertical="center")sheet.row_dimensions[cell.row].height = 40# 设置列宽sheet.column_dimensions['A'].width = 19sheet.column_dimensions['B'].width = 10sheet.column_dimensions['C'].width = 21sheet.column_dimensions['D'].width = 12sheet.column_dimensions['E'].width = 40# 保存Excel文件file_name = f'结果_{today}.xlsx'file_path = save_path / file_namewb.save(file_path)wb.close()print("数据已写入Excel文件:", file_path)if __name__ == '__main__':try:read_excel()# 创建Chrome浏览器实例driver = webdriver.Chrome()driver.maximize_window()#调用函数search_results()# 关闭网站driver.quit()creat_excel(result_list=result_list)except Exception as e:print(traceback.format_exc())

八、总结

本文主要介绍了selenium的部署使用、组成元素、交互操作等基本内容,后续还有一些进阶内容,例如Actions接口,验证码识别、脚本执行等等,我也会结合python编写实用的程序供大家参考。至此,selenium的基础学习完结,但学无止境,继续加油

最后我邀请你进入我们的【软件测试学习交流群:785128166】, 大家可以一起探讨交流软件测试,共同学习软件测试技术、面试等软件测试方方面面,还会有免费直播课,收获更多测试技巧,我们一起进阶Python自动化测试/测试开发,走向高薪之路

作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:程序员二黑】自提!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/519685.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue的旅游管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

vcomp140.dll丢失如何修复,5种修复方法轻松搞定vcomp140.dll问题

vcomp140.dll文件的丢失可能会引发一系列系统运行与软件功能上的问题。具体来说&#xff0c;这个动态链接库文件是Visual C Redistributable的一部分&#xff0c;对于许多基于此环境开发的应用程序至关重要。一旦缺失&#xff0c;可能会导致部分应用程序无法正常启动或运行&…

外包干了3个月,技术倒退太明显...

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

【个人账号体系设计】偏个人功能类账号功能模块设计

本文讨论了针对以个人功能为主的业务系统的账号能力设计&#xff0c;包括账号管理的总体需求、关键属性和设计要点。重点在于如何通过细致的设计实现账号的有效管理和安全性&#xff0c;确保系统既便于用户操作又能维持管理的严密性。 文章目录 需求能力模块设计 需求能力 在进…

25考研资料PDF汇总

资料V馊public号ZL研知己 V馊public号ZL研知己 25考研资料PDF汇总

HarmonyOS—配置编译构建信息

在进行应用/服务的编译构建前&#xff0c;需要对工程和编译构建的Module进行设置。API Version 9、API Version 8与API Version 4~7的构建体系不同&#xff0c;因此在设置编译构建信息时也存在差异&#xff1a; API Version 9&#xff1a;需要对构建配置文件、构建脚本、应用依…

passwd: Authentication token manipulation error

passwd: Authentication token manipulation error 身份验证令牌操作错误。 可能原因&#xff1a; 1、密码文件无修改权限&#xff08;有i权限&#xff09; lsattr /etc/{passwd,shadow} 取消方法 chattr -i /etc/passwd chattr -i /etc/passwd 2、/文件系统无空间或者无inod…

基于MPPT的太阳能光伏电池simulink性能仿真,对比扰动观察法,增量电导法,恒定电压法

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 扰动观察法 (Perturb and Observe Method) 4.2 增量电导法 (Incremental Conductance Method) 4.3 恒定电压法 (Constant Voltage Method) 5.完整工程文件 1.课题概述 在simulink中&#xff0c;实…

noetic ros配置因时机械夹爪的驱动

noetic ros配置因时机械夹爪的驱动文件 配置编译教程解决方案 配置编译教程 1.inspire_robot 包支持因时机器人公司的机械夹爪在ROS平台上的使用&#xff0c;我们在ros noetic环境下进行了测试。 2.为了使程序能够正常运行&#xff0c;需要执行以下环境配置操作&#xff1a;&a…

Java定时调度

在Java应用程序中&#xff0c;定时调度是一项重要的任务。它允许你安排代码执行的时间&#xff0c;以便在将来的某个时刻自动执行任务。Java提供了多种方式来实现定时调度&#xff0c;其中最常用的是Java的Timer和ScheduledExecutorService。 在本教程中&#xff0c;我们将学习…

【CSP】201403-3-命令行选项

CSP-201403-3-命令行选项 关键点&#xff1a;将整行字符串按空格分割 在解析命令行时&#xff0c;一个常见的需求是将整个命令行字符串分割成多个部分&#xff0c;通常以空格为分隔符。这些部分包括命令行工具的名称、选项&#xff08;可能带有前缀-或--&#xff09;和这些选项…

Mock在接口测试中的实际应用

关于Mock测试 01、含义和目的 1、 什么是mock测试&#xff1f; Mock 测试就是在测试过程中&#xff0c;对于某些不容易构造&#xff08;如 HttpServletRequest 必须在Servlet 容器中才能构造出来&#xff09;或者不容易获取的比较复杂的对象&#xff08;如 JDBC 中的ResultSe…