【RPA开发】Selenium 实现网页自动化

news2024/10/6 5:59:58

开发时有时会遇到网页爬取限制的情况,那么此时可以通过 Selenium 来解决这个问题,因为 Selenium 是模拟浏览器执行网页爬取,相比 Request/API 操作更安全,服务器会完全认为是用户在用浏览器进行操作,如此可以实现网页自动化操作,由于 Selenium 是完全模拟浏览器操作,因此效率相比 API 更低。

1 Selenium 介绍

Selenium 简单来说是一个用于Web应用程序的自动化工具。

  • 官方网址:Selenium
  • 中文文档:Selenium with Python中文翻译文档
  • 安装:pip install selenium 

它允许用户使用各种编程语言(如Python, Java, C#等)来驱动自动化,实现模拟真实用户在浏览器中的操作,如点击、输入、选择、滚动等,可用于自动化测试或爬虫开发。

Selenium与各种浏览器(如Chrome,Firefox,IE等)兼容,并提供交互式界面便于开发和调试。

驱动下载及测试

浏览器驱动是 Selenium 构建浏览器对象的基础,它是一种可以让 Selenium 与特定的浏览器进行交互的组件,能将 Selenium 命令翻译成与特定浏览器对应的命令,以实现对浏览器的自动化操作。

因此浏览器驱动对于 Selenium 非常重要,同时针对不同的浏览器,需要安装不同的驱动。下面以下载 Chrome 驱动作为演示:

2.1 确定浏览器版本

首先点击 chrome 浏览器最右侧的“...”图标,然后点击弹出的“帮助”中的“关于Google Chrome”,查看自己的版本信息。

这里我的版本是112.0.5615,下载对应版本的 Chrome 驱动。

2.2 下载驱动

Chrome 驱动链接:https://chromedriver.storage.googleapis.com/index.html

打开该链接,选择对应的版本单机(二选一)

 由于我是使用 Window 环境进行开发,因此下载 window 版本驱动,按操作系统进行下载即可。

解压后有两个文件,我们需要的是 .exe 后缀的驱动。

2.3 测试驱动

接下来就是测试驱动成功与否了,我将其放到项目的根目录下(大家可自行选择放位置,Selenium 需要的是读取该驱动的路径)

# 导入webdriver
from selenium import webdriver

# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')

执行该文件,驱动成功启动 Chrome 浏览器 👇

3 模拟浏览器及页面相关操作

Selenium 实现网页自动化首先是从一个网站开始的,简单来说就是如何操作浏览器,有了浏览器对象,我们才可以针对请求页面进行操作。

3.1 创建及关闭浏览器对象

executable_path 指定的是浏览器驱动的路径,我这里是相对路径,绝对路径也可。

# 导入webdriver
from selenium import webdriver

# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')

#关闭浏览器
driver.close() #关闭当前页面,但浏览器驱动会残留影响内存
driver.quit() #关闭当前页面 + 浏览器驱动

3.2 设置浏览器大小

而maximize_window则是设置浏览器为全屏,set_window_size()方法用来设置浏览器大小(就是分辨率)

import time
# 导入webdriver
from selenium import webdriver
# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')

#1.浏览器最大化
driver.maximize_window()
time.sleep(2)

#2.获取当前浏览器尺寸
size = driver.get_window_size()
print(size)

#3.设置当前浏览器尺寸
driver.set_window_size(400, 400)
time.sleep(2)
size = driver.get_window_size()
print(size)

#关闭浏览器
driver.quit()

3.3 访问页面

通过 driver.get 方法进行页面访问,传入参数即为 url 地址。

# 导入webdriver
from selenium import webdriver
# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')

#打开网页地址
driver.get('https://www.baidu.com/')

#关闭浏览器
driver.quit()

3.4 获取页面相关属性

通过 Selenium 打开网页,可以获取网页标题、网址、页面源码等信息。

# 导入webdriver
from selenium import webdriver
# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#打开网页地址
driver.get('https://www.baidu.com/')

#1.获取当前页面标题
title = driver.title
print(title)

#2.获取当前页面地址
url = driver.current_url
print(url)

#3.获取当前页面标源代码
source = driver.page_source
print(source)

#关闭浏览器
driver.quit()

控制台输出:

 3.5 页面前进、后退、截图

import time
# 导入webdriver
from selenium import webdriver
# 创建一个浏览器对象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#1.打开 baidu
driver.get('https://www.baidu.com/')
time.sleep(2)

#2.打开bilibili页面
driver.get('https://www.bilibili.com/')
time.sleep(2)

#3.页面回退到 baidu
driver.back()

#4.页面前进
driver.forward()

#5.页面刷新
driver.refresh()

#6.页面截图
#(1)方式一
data = driver.get_screenshot_as_png()
with open('bi1.jpg','wb') as f:
    f.write(data)
#(2)方式二
driver.get_screenshot_as_file('bi2.png')

#关闭浏览器
driver.quit()

4 页面元素定位

通过 Selenium 进入对应的页面后,便可对页面中的元素(按钮、输入框等)进行操作,可分为两步:

  1. 定位元素信息,返回元素对象
  2. 调用方法完成元素的模拟操作

通过 Selenium 进行页面元素定位的前提是基本了解前端的页面布局及各种标签含义,首先我们简单地过一下。以百度官网为例,按【F12】或者右键检查进入开发者工具,红框中显示的就是页面元素代码(HTML样式),我们要做的就是从元素代码中定位获取我们需要的元素。

接下来我们来进行元素定位的学习,Selenium 对此提供了一系列的方法,主要包括以下这七种,一般来说 id 和 name 在当前页面是唯一的,xpath 使用也较为普遍。

webdriver 对象的find_element 方法用于定位单个元素,find_elements 方法用于定位元素集合(如find_elements_by_id('')  )。

4.1 id 属性定位

我们选择输入框并右键点击检查元素,即可定位到该输入框的元素信息。其中 input 是该元素的标签名(tag_name);id、name、calss 等键值对均为该元素的属性,可用于元素定位。因此该输入框元素的 id 属性为 'kw'

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#1.id属性定位,传回一个元素对象
element_input = driver.find_element_by_id('kw')
print(element_input) 

#关闭浏览器
driver.quit()

4.2 name 属性定位

同上,该输入框元素的 name 属性为 'wd'。

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#2.name属性定位,传回一个元素对象
element_input = driver.find_element_by_name('wd')
print(element_input)

#关闭浏览器
driver.quit()

4.3 class 属性定位

该输入框元素的 class 属性为 's_ipt',但是 class 属性经常会重复,需要保证其唯一方可正确定位,该页面的 class 属性正好唯一,因此可进行 class 属性定位。

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#3.class属性定位,传回一个元素对象
element_input = driver.find_element_by_class_name('s_ipt')
print(element_input)

#关闭浏览器
driver.quit()

4.4 tag 标签定位

tag 标签若要正确定位,也必须保证其唯一性,但是输入框元素的 tag name = input,不符合唯一性的要求,因此用 tag name = textarea 的元素进行测试~

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#4.tag标签定位,传回一个元素对象
element_input = driver.find_element_by_tag_name('textarea')
print(element_input)

#关闭浏览器
driver.quit()

4.5 link_text 链接文本定位

① find_element_by_link_text 全文本

如上图,标签的><之间存在文本,这种元素则可以通过链接文本定位的方式定位。

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#5.link_text 全链接文本定位,传回一个元素对象
element_input = driver.find_element_by_link_text('更多')
print(element_input)

#关闭浏览器
driver.quit()

② find_element_by_link_text 部分文本

 如图,我们通过链接文本形式进行元素定位有时会遇到文本过长的情况,此时可以通过部分文本匹配元素!

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#5.link_text 部分链接文本定位,传回一个元素对象
element_input = driver.find_element_by_partial_link_text('更')
print(element_input)

#关闭浏览器
driver.quit()

4.6 css 选择器定位

大家如果有了解前端的话,对css应该蛮熟悉,它用来描述THML和XML的元素显示样式,在css语言中有 css选择器,在Selenium中也可以使用这种选择器来定位元素。

① css结合基本属性定位

css选择器也支持基本属性(id、class、tag)定位方式。

语法:

  • driver.find_element_by_css_selector("#id值") #css+id定位
  • driver.find_element_by_css_selector(".class值") #css+class定位
  • driver.find_element_by_css_selector("标签名") #css+标签定位

参数说明:

  • #:井号代表id(类似 id = id值)
  • . : 点代表class(类似 class = class值)
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.1css结合基本属性定位(id,class,标签)
element_input1 = driver.find_element_by_css_selector('#kw') #id
element_input2 = driver.find_element_by_css_selector('.s_ipt') #class
element_input3 = driver.find_element_by_css_selector('textarea') #标签
print(element_input1)
print(element_input2)
print(element_input3)

#关闭浏览器
driver.quit()

② css结合其他属性定位

语法:

  • driver.find_element_by_css_selector('[属性名=属性值]') #css+其他属性
  • driver.find_element_by_css_selector('[属性名1=属性值1][属性名2=属性值2]') #css+多个其他属性

参数说明:

  • [] :用方括号来指定属性
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.2css其他属性定位
element_input = driver.find_element_by_css_selector("[id='kw'][name='wd']")
#其他属性定位
print(element_input)

#关闭浏览器
driver.quit()

③ css标签结合其他属性定位

我们也可以通过标签+属性来进行定位

语法:

  • driver.find_element_by_css_selector(‘标签名#id值’) #标签+id属性定位
  • driver.find_element_by_css_selector(‘标签名.class值’) #标签+class属性定位
  • driver.find_element_by_css_selector('标签名[属性名=属性值]') #标签+其他属性定位
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.3css标签结合其他属性定位
element_input1 = driver.find_element_by_css_selector('input#kw') #id
element_input2 = driver.find_element_by_css_selector('input.s_ipt') #class
element_input3 = driver.find_element_by_css_selector("input[name='wd']") #标签
print(element_input1)
print(element_input2)
print(element_input3)

#关闭浏览器
driver.quit()

④ css层级定位

在定位某个元素时,若无简洁标签属性可供参考,我们可以先定位到该元素的上级或上上级元素,随后通过层级关系获取该元素的位置。

语法:

  • driver.find_element_by_css_selector('标签1>标签2')

参数说明:

  • 标签1>标签2: 表示父级定位到子级
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.4css层级定位
element_input = driver.find_element_by_css_selector('form>span>input#kw')
print(element_input)

#关闭浏览器
driver.quit()

⑤ css索引定位

如上图,“新闻”按钮同级目录下存在6个与他一样的a标签,因此像这种有多个相同标签名的元素,可以使用索引定位,通过索引来指定具体哪个 a 标签的元素。

注:与python列表索引的概念不同,此处的标签索引是从1开始;python列表的索引是从0开始。

语法:

  • driver.find_element_by_css_selector('标签:nth-child(n)') #正着数第n个标签
  • driver.find_element_by_css_selector('标签:nth-last-child(n)') #倒着数第n个标签
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.5css索引定位
element_input1 = driver.find_element_by_css_selector('div#s-top-left>a:nth-child(1)') #正着数第1个a
element_input2 = driver.find_element_by_css_selector('div#s-top-left>a:nth-last-child(7)') #倒着数第7个a
print(element_input1)
print(element_input2)

#关闭浏览器
driver.quit()

⑤ css模糊匹配

有时也会遇到属性值过长的情况,此时我们可以通过模糊匹配来处理,只需要属性值的部分内容即可。

语法:

  • driver.find_element_by_css_selector("[属性名~='部分属性值']") #1.属性值由多个空格隔开,匹配其中一个值的方法
  • driver.find_element_by_css_selector("[属性名^='属性值开头']") #2.匹配字符串开头
  • driver.find_element_by_css_selector("[属性名$='属性值结尾']") #3.匹配字符串结尾
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#6.6css模糊匹配
element_input1 = driver.find_element_by_css_selector("input[class~='s_btn']")
element_input2 = driver.find_element_by_css_selector("input[class^='bg']")
element_input3 = driver.find_element_by_css_selector("input[class$='s_btn']")
print(element_input1)
print(element_input2)
print(element_input3)

#关闭浏览器
driver.quit()

4.7 xpath 表达式定位

其实 xpath 定位和 css 选择器类似,只是写法有所区别。Selenium 元素定位的基础方法(比如通过id、name、class_name等)局限性较大,首先各元素不一定都有 id 属性,其次元素的id属性也并非固定不变,因此我们真正需要熟练掌握的是通过 xpath 和 css 定位,一般掌握其中一种即可应对大部分定位工作,xpath 更为常用。

xpath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:

① xpath结合属性定位

语法:

  • driver.find_element_by_xpath(".//input[@id='kw']")  #单个属性定位
  • driver.find_element_by_xpath(".//input[@id='kw' and @name='wd']")  #多个属性定位

参数说明:

  • [] :表示要根据属性找元素
  • @ :后边跟属性的key,表示要通过哪个属性定位
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#7.1xpath结合属性定位
element_input1 = driver.find_element_by_xpath(".//input[@id='kw']")
element_input2 = driver.find_element_by_xpath(".//input[@id='kw' and @name='wd']")
print(element_input1)
print(element_input2)

#关闭浏览器
driver.quit()

② xpath文本定位

标签文本是><里边的字符串,非键值对。

语法:

  • driver.find_element_by_xpath(".//a[text()='更多']")
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#7.2xpath文本定位
element_input = driver.find_element_by_xpath(".//a[text()='更多']")
print(element_input)

#关闭浏览器
driver.quit()

③ xpath层级定位

实际开发时,若需求元素没有像 id、name、class 等基本属性,那么我们就需要借助相邻的元素定位,首先我们可以定位到相邻元素,然后通过层级关系来定位最终元素。

语法:

  • driver.find_element_by_xpath(".//form[@id='form']/span/input") #由上到下的层级关系
  • driver.find_element_by_xpath(".//input[@class='s_ipt']/parent::span") #父子元素定位
  • driver.find_element_by_xpath(".//input[@class='s_ipt']//preceding-sibling::span") #哥哥元素定位
  • driver.find_element_by_xpath(".//input[@class='s_ipt']//following-sibling::i") #弟弟元素定位

参数说明:

  • parent::span :向父级定位,父级的标签名为span
  • preceding-sibling::span :向哥哥级定位,哥哥级的标签名为span
  • following-sibling::span :向弟弟级定位,弟弟级的标签名为i
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#7.3 xpath层级定位
element_input1 =driver.find_element_by_xpath(".//form[@id='form']/span/input")#由上到下的层级关系
element_input2 =driver.find_element_by_xpath(".//input[@class='s_ipt']/parent::span")#父子元素定位
element_input3 =driver.find_element_by_xpath(".//input[@class='s_ipt']//preceding-sibling::span") #哥哥元素定位
element_input4 =driver.find_element_by_xpath(".//input[@class='s_ipt']//following-sibling::i") #弟弟元素定位
print(element_input1)
print(element_input2)
print(element_input3)
print(element_input4)

#关闭浏览器
driver.quit()

④ xpath索引定位

xpath 的标签索引也是从1开始的。

语法:

  • driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")  #根据索引选择标签
  • driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()]")  #最后一个标签
  • driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()-1]")  #倒数第二个标签

参数说明:

  • 1 :指同名标签的第一个标签
  • last() :指同名标签的最后一个标签
  • last()-1 :指同名标签的倒数第二个标签
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#7.4xpath索引定位
element_input1 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]") #根据索引选择标签
element_input2 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()]") #最后一个标签
element_input3 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()-1]") #倒数第二个标签
print(element_input1)
print(element_input2)
print(element_input3)


#关闭浏览器
driver.quit()

⑤ xpath模糊匹配

语法:

  • driver.find_element_by_xpath(".//span[start-with(@class, 'soutu-hover')]")  #匹配开头
  • driver.find_element_by_xpath(".//span[ends-with(@class, 'hover-tip')]")  #匹配结尾
  • driver.find_element_by_xpath(".//span[contains(text(), '搜索')]") #包含“搜索”

ends-with方法是xpath 2.0的语法,而浏览器只支持xpth 1.0,因此可能会出现报错。

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#7.5xpath模糊定位
element_input1 = driver.find_element_by_xpath(".//span[start-with(@class,'soutu-hover')]") #匹配开头
element_input2 = driver.find_element_by_xpath(".//span[ends-with(@class,'hover-tip')]") #匹配结尾
element_input3 = driver.find_element_by_xpath(".//span[contains(text(), '搜索')]") #包含匹配
print(element_input1)
print(element_input2)
print(element_input3)

#关闭浏览器
driver.quit()

5 模拟操作页面元素

定位元素后,我们将得到一个元素对象,接下来便是针对这个元素对象做模拟操作。

5.1 按钮点击操作

语法:

  • element.click() #对象.方法
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#1.按钮点击操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()

#关闭浏览器
driver.quit()

5.2 文本框操作

语法:

  • element.send_keys('python') #输入
  • element.clear() #清空文本框
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#2.文本框操作
element = driver.find_element_by_id("kw")
element.send_keys('python') #输入
element.clear() #清空文本框

#关闭浏览器
driver.quit()

5.3 获取元素文本

语法:

  • element.text  #text不是方法,不加括号
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#3.获取标签文本
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
s = element.text #获取文本
print(s)

#关闭浏览器
driver.quit()

5.4 获取元素属性

语法:

  • element.get_attribute(属性名) #入参为具体属性名,如 id、class 等
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

#4.获取标签属性值
element = driver.find_element_by_xpath(".//input[@id='su']")
s1 = element.get_attribute('class') #获取 class 属性值
s2 = element.get_attribute('value') #获取 value 属性值
print(s1)
print(s2)

#关闭浏览器
driver.quit()

6 切换页面的iframe、handlers

实际开发时,我们经常会遇到iframe和handler两种窗口切换。Iframe指的是在主html中嵌入子html页面,即一个页面中嵌套着一个或多个页面;Handler指的是新的页面选项卡,即浏览器上方增加了一个页面。在使用Handler切换后,我们的操作仍然在原来的窗口,如果需要在新的窗口中继续操作元素,则需要使用handle窗口切换方法。

6.1 iframe切换

图中阴影部分就是 iframe,可以理解为页面中嵌套着一个小页面,如果我们想要定位账号密码输入框,必须先切换到小页面才能定位,否则将会报错。

语法:

  • driver.switch_to.frame(value) #1.直接使用id值切换,如果iframe标签中有id属性,可以用这个方法直接传id的值
  • driver.switch_to.frame(driver.find_element_by_xxx(value)) #2.通过出入元素对象切换
  • driver.switch_to.parent_frame() #3.跳回上层的页面
  • driver.switch_to.default_content() #4.跳回最外层的页面
import time
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://mail.163.com/')
# 定位到iframe,并切换
el_iframe = driver.find_element_by_xpath(".//div[@id='loginDiv']/iframe")
driver.switch_to.frame(el_iframe)
# 先定位,输入用户名
el_username = driver.find_element_by_name("email")
el_username.send_keys('yinyu123')
time.sleep(2)
# 关闭浏览器
driver.quit()

6.2 handler切换

当我们点击百度首页的新闻按钮,会弹出一个新窗口。若要访问新闻页的元素,则需要先切换至该窗口,否则无法获取。

语法:

  • driver.window_handles #1.获取当前打开的所有窗口句柄,返回类型为一个列表,window_handles是对象属性,没有括号
  • driver.current_window_handle #2.获取当前窗口的句柄
  • driver.switch_to.window(handle_id) #3.切换窗口,handle_id参数代表的是一个窗口句柄
import time
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')
# 按钮点击操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]") #新闻按钮
element.click()
time.sleep(3)

#1.获取当前浏览器的全部窗体
all_handles = driver.window_handles
#2.切换到最新的窗体
driver.switch_to.window(all_handles[-1])
#3.获取当前标题
print(driver.title) #输出【百度新闻——海量中文资讯平台】,说明切换成功

# 关闭浏览器
driver.quit()

7 三种元素等待方式

实际开发中,定位元素时经常会碰到元素加载慢的情况(元素加载需要一个时间,比如我们平时用浏览器也会遇到网页加载慢情形)。如果元素还未加载完,此时进行点击操作则是无效的,前边有提到使用 time.sleep() 方法进行页面等待,这就是元素等待的一种。

测试流程 👇

7.1 强制等待

最简单粗暴的方式就是强制等待 sleep(xx),不论元素加载成功与否,都必须等待 xx 时间。但是该方式较为死板,严重影响执行速度。

语法:

  • time.sleep(3)

import time
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

# 按钮点击操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 强制等待3秒
time.sleep(3)
# 页面跳转
driver.switch_to.window(driver.window_handles[1])  # 此行代码用来定位新跳出的页面
print(driver.title)
# 获取输出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)

#关闭浏览器
driver.quit()

7.2 隐式等待

隐式等待设置了一个最长等待时间,若网页在规定时间内加载完成,程序执行下一步,否则一直等待直至时间截止,才执行下一步。然而,此方法存在一个缺陷,即程序会一直等待整个页面加载完成,即使有时页面所需元素早已加载完成,但是由于某些 js 等因素导致加载缓慢。

语法:

  • driver.implicitly_wait(5)
import time
# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')

# 按钮点击操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 页面跳转
time.sleep(1) #保证页面跳转成功
driver.switch_to.window(driver.window_handles[1])  # 此行代码用来定位新跳出的页面
#隐式等待
driver.implicitly_wait(5)
# 获取输出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)

#关闭浏览器
driver.quit()

7.3 显式等待

使用显式等待,结合WebDriverWait类的until()和until_not()方法,即可根据需求灵活等待。通俗来讲,程序每隔一定时间检查一次条件是否成立,如果成立则继续执行,否则持续等待直至超时,最后抛出TimeoutException异常。

① WebDriverWait 举例

语法:

  • WebDriverWait(driver,10,0.5).until(EC.presence_of_element_located(locator)) #最长时间10秒钟,每0.5秒判断该元素是否加载成功
import time
# 导入webdriver
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://www.baidu.com/')
# 按钮点击操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 页面跳转
time.sleep(1) #保证页面跳转成功
driver.switch_to.window(driver.window_handles[1])  # 此行代码用来定位新跳出的页面

# 显性等待
locator = (By.XPATH,".//a[@data-control='pane-news']")
WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located(locator))
# 获取输出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)

#关闭浏览器
driver.quit()

② 显性等待之EC模块

显示等待经常会使用 EC 模块,WebDriverWait的until和until_not方法中我们经常要用到,它会根据网页标题、网址以及元素是否可见等条件来决定我们是否需要继续等待。

引入相关模块:

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

判定方法汇总:

#1.判断当前页面的title是否完全等于(==)预期字符串,返回是布尔值
title_is

#2.判断当前页面的title是否包含预期字符串,返回布尔值
title_contains

#3.判断某个元素是否已被加载,并不代表该元素一定可见
presence_of_element_located

#4.判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of_element_located

#5.跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element
就好了
visibility_of

#6.判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
presence_of_all_elements_located

#7.判断某个元素中的text是否包含了预期的字符串
text_to_be_present_in_element

#8.判断某个元素中的value属性是否包含了预期的字符串
text_to_be_present_in_element_value

#9.判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
frame_to_be_available_and_switch_to_it

#10.判断某个元素中是否不存在于dom树或不可见
invisibility_of_element_located

#11.判断某个元素中是否可见并且是enable的,这样的话才叫clickable
element_to_be_clickable

#12.等某个元素从dom树中移除,注意,这个方法也是返回True或False
staleness_of

#13.判断某个元素是否被选中了,一般用在下拉列表>* element_selection_state_to_be:判断
某个元素的选中状态是否符合预期
element_to_be_selected

#14.跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
element_located_selection_state_to_be

#15.判断页面上是否存在alert弹出框
alert_is_present

8 实现163邮箱自动化登录

最后来实战下,通过 Selenium 实现163邮箱自动化登录!

# 导入webdriver
from selenium import webdriver
#获取驱动路径
driver_path = './chromedriver.exe'
#创建一个浏览器对象
driver = webdriver.Chrome(executable_path=driver_path)
#设置全屏
driver.maximize_window()
#请求某个url
driver.get('https://mail.163.com/')
#定位到iframe,并切换
el_iframe = driver.find_element_by_xpath(".//div[@id='loginDiv']/iframe")
driver.switch_to.frame(el_iframe)
#先定位,输入用户名
el_username = driver.find_element_by_name("email")
el_username.send_keys('yinyu123')
#先定位,输入密码
el_psw = driver.find_element_by_name("password")
el_psw.send_keys('xxxx')
#先定位,点击登录
el_login = driver.find_element_by_id("dologin")
el_login.click()
#切到最外层iframe
driver.switch_to.default_content()
#隐式等待
driver.implicitly_wait(5)
#断言是否登录成功
username_text = driver.find_element_by_xpath(".//div[@class='gWel-greet']/span/span[1]").text
assert username_text == 'yinyu123','断言失败:{}'.format(username_text)
print("登录成功")
#关闭浏览器
driver.quit()

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7环境下:DolphinScheduler3.1.5简介和伪集群模式安装部署

centos7环境下&#xff1a;DolphinScheduler3.1.5简介和伪集群模式安装部署 DolphinScheduler简介 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用…

Quartz定时任务

基本介绍 Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个、百个、甚至是好几万个Jobs这样复杂的日程序表&#xff0c;Jobs可以做成标准的Java组件或EJBs Qua…

android framework-ActivityManagerService(AMS)下

一、ActivityThread \frameworks\base\core\java\android\app\ActivityThread.java 1.1、main public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAnd…

java native 方法编写

目录 前言 1、创建 java native 方法 2、创建洞态链接库项目 3、加载 dll 文件 前言 Java 提供了调用 C 或 C 函数的方法&#xff0c;这种方法就是 native 方法&#xff0c;全称 Java Native Interface (JNI) 1、创建 java native 方法 1&#xff09;新建 java 类文件 …

【CMake】如何使用CMake构建一个工程

1.如何使用CMake构建一个工程 1. 使用 CMakelists.txt 构建工程 一个最简单 CMake 的项目是将某个源文件构建成为可执行文件&#xff0c;使用CMake 构建项目时&#xff0c;你需要创建一个 CMakeLists.txt 文件&#xff0c;通常情况下&#xff0c;下面三条命令在每个 CMakeLis…

四结4.20

这俩天实现了分离客服端和服务端&#xff0c; 先将对象序列化&#xff0c;通过socket从客户端发送到服务端&#xff0c;反序列化 进行数据库操作&#xff0c;最后向客户端返回结果&#xff0c;渲染javafx的画面 中途遇到俩种异常&#xff0c;因为一报错弹出一大段红色的英语…

力扣sql中等篇练习(九)

力扣sql中等篇练习(九) 1 电影评分 1.1 题目内容 1.1.1 基本题目信息1 1.1.2 基本题目信息2 1.1.3 示例输入输出 a 示例输入 b 示例输出 1.2 示例sql语句 # 只要一个 可以考虑order by加上 limit的组SELECT子句中子查询的结果 # 电影名称和姓名不可能重复,所以直接Union a…

【RecyclerView】同时刷新和滚动导致,滚动位置异常(一)

前置&#xff1a; 被选中item高度与非选中item高度不一致&#xff0c;且硬件有点卡&#xff0c;运行会有一定卡顿。 可视界面的item为三个&#xff0c;总数据为十个。 期望效果&#xff1a; 》 实际上效果&#xff1a; 代码&#xff1a; mListAdapter.setSelectedPosition(…

学成在线笔记+踩坑(6)——【媒资模块】视频处理。FFmpeg+XXL-JOB

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 1 视频转码需求 1.1 视频编码格式和文件格式 1.2 windows使用编码工具FFmpeg 1.3 视频处理工具类 1.3.1 拼装FFmpeg命令的各工具类 1…

复旦MOSS大模型开源了「中国版ChatGPT」,Github和Hugging Face同时上线

最近&#xff0c;ChatGPT非常火&#xff0c;从ChatGPT3到ChatGPT4&#xff0c;都非常火。无论是否为互联网行业的&#xff0c;多少都听到过关于ChatGPT的消息。虽然百度、阿里等互联网巨头都已经宣布将会推出相关的类ChatGPT产品。但目前还未有成型的产品上线。 而昨日&#x…

94. 二叉树的中序遍历【119】

难度等级&#xff1a;容易 上一篇算法&#xff1a; 102. 二叉树的层序遍历【206】 力扣此题地址&#xff1a; 94. 二叉树的中序遍历 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序…

AlgoC++第四课:逻辑回归

目录 逻辑回归前言1. 鸢尾花分类问题1.1 基于线性回归的思考1.2 损失函数 2. 伯努利分布3. 示例代码3.1 数据可视化3.2 日志信息打印3.3 数据读取和处理3.4 逻辑回归模型3.5 完整示例代码3.6 python实现 4. 思考总结 逻辑回归 前言 手写AI推出的全新面向AI算法的C课程 Algo C&…

InnoDB中必须要了解的几个关键特性

InnoDB引擎在设计中使用了很多技术思想。下面我们主要介绍一些InnoDB的关键特性&#xff0c;帮助你去更好了解 InnoDB。 关键特性 1.预读&#xff08;1&#xff09;预读的两种算法&#xff08;2&#xff09;在InnoDB中相关配置 2.插入缓冲2.1 Insert Buffer2.2 Change Buffer2…

跨域的五种最常见解决方案

这是一篇笔记 什么是跨域&#xff1f; 跨域不是问题&#xff0c;是一种安全机制。浏览器有一种策略名为同源策略&#xff0c;同源策略规定了部分请求不能被浏览器所接受。 值得一提的是&#xff1a;同源策略导致的跨域是浏览器单方面拒绝响应数据&#xff0c;服务器端是处理…

C#基于asp.net的企业人事管理系统的研究与实现

&#xff08;一&#xff09;任务 1.本课题的任务是对人事管理系统的管理过程进行分析&#xff0c;列出逻辑实现过程&#xff0c;对系统进行逻辑设计和数据库设计&#xff1b; 2.主要实现系统管理、档案管理、考勤管理、薪水管理等功能&#xff1b; 3.实现企业员工的相关信息&am…

一篇文章教你解决node-sass 4.12.0 安装失败,一劳永逸

已知&#xff1a; 使用mac电脑使用的node版本是v14.20.0 问题&#xff1a;在安装node-sass 4.12.0的时候报错如下 看到这一堆错误&#xff0c;千万不要立马复制粘贴到浏览器去搜&#xff0c;感觉像无头苍蝇乱撞&#xff0c;好歹稍微看一下什么意思。 显而易见是有一个文档40…

浅析低代码开发的典型应用构建场景v

在数字经济蓬勃发展的大势之下&#xff0c;企业软件开发人员供给不足、开发速度慢、开发成本高、数字化和智能化成效不明显等问题日益凸出&#xff0c;阻碍了企业的数字化转型。 而近年来&#xff0c;低代码的出现推动了经济社会的全面提效&#xff0c;也成为人才供求矛盾的润…

【Docker】限制已运行容器的Cpu和内存

docker限制已运行容器的Cpu和内存 本文首发于 慕雪的寒舍 1.问题描述 最近云服务器的内存经常不够用&#xff0c;而且是莫名其妙的增多&#xff0c;在腾讯云的控制台里面看&#xff0c;4g的内存占用了3.2g&#xff0c;就卡到连ssh都连不上了 PS: 已换过网络和设备&#xff0c…

只要10分钟,零代码基础搞定炫酷大屏设计(内附详细教程)

近几年可视化大屏再次被推上热搜&#xff0c;无论是已经结束的疫情时代指挥中心大屏&#xff0c;还是每年购物节的大屏数据成交额&#xff0c;或者是日常会议中的大屏分析&#xff0c;到处都是可视化大屏的身影。 有人会说&#xff0c;这种大屏一定需要大量的财力、技术顶端的…

开源构建系统Buck2发布

看来最近 Meta 的工程师是一点都没有闲着&#xff0c;前两天刚开源 AI 图像分割模型&#xff0c;这不就又发布了名为 Buck2 的开源构建系统。 Buck2 是一个已经在 Meta 内部使用了一段时间的大型构建系统&#xff0c;目前 Meta 有数千名开发人员正在使用该构建系统&#xff0c;…