自动化笔记 selenium安装 选择元素

自动化测试

在这里插入图片描述
从上图可以看出:
我们写的自动化程序 需要使用 客户端库。客户端库从哪里来的? 是Selenium组织提供的。

Selenium组织提供了多种 编程语言的Selenium客户端库, 包括 java,python,js, ruby等,方便不同编程语言的开发者使用
程序的自动化请求都是通过这个库里面的编程接口发送给浏览器。

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

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

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

浏览器驱动接收到我们的自动化程序发送的界面操作请求后,会转发请求给浏览器, 让浏览器去执行对应的自动化操作。
浏览器执行完操作后,会将自动化的结果返回给浏览器驱动, 浏览器驱动再通过HTTP响应的消息返回给我们的自动化程序的客户端库。
自动化程序的客户端库 接收到响应后,将结果转化为 数据对象 返回给 我们的代码。

安装selenium库

打开 命令行程序,运行如下命令

pip install selenium

如果安装不了,可能是网络问题,可以指定使用国内的豆瓣源

pip install selenium -i https://pypi.douban.com/simple/

安装浏览器 驱动

谷歌浏览器驱动地址

谷歌浏览器驱动

edge浏览器驱动地址

省略浏览器驱动路径

一定要注意的是, 加入环境变量 Path 的,

不是浏览器驱动全路径,比如 d:\tools\chromedriver.exe

而是 浏览器驱动所在目录,比如 d:\tools

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

from selenium.webdriver.chrome.service import Service
wd = webdriver.Chrome(service=Service(r'd:\tools\chromedriver.exe'))

直接把浏览器驱动加入环境变量

wd = webdriver.Chrome()

选择元素

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')
# 根据 class name 选择元素,返回的是 一个列表
# 里面 都是class 属性值为 animal的元素对应的 WebElement对象
elements = wd.find_elements(By.CLASS_NAME, 'animal')
# 取出列表中的每个 WebElement对象,打印出其text属性的值
# text属性就是该 WebElement对象对应的元素在网页中的文本内容
for element in elements:
    print(element.text)

selenium 升级到版本 4 以后

注意

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

而如果我们使用 wd.find_element (注意少了一个s) 方法, 就只会返回 第一个 元素,如果没有符合条件的元素, 抛出 NoSuchElementException 异常

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()

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

WebElement对象 也可以调用 find_elements, find_element 之类的方法

WebDriver 对象 选择元素的范围是 整个 web页面, 而

WebElement 对象 选择元素的范围是 该元素的内部。

隐式等待/全局等待

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

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

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

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

Selenium 的 Webdriver 对象 有个方法叫 implicitly_wait ,可以称之为 隐式等待 ,或者 全局等待 。

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

from selenium import webdriver
from selenium.webdriver.common.by import By

wd = webdriver.Chrome()
wd.implicitly_wait(10)#加入隐式等待,那么后续所有的 find_element 或者 find_elements 之类的方法调用 都会采用

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)

操控元素的基本方法

element = wd.find_element(By.ID, "input1")

element.clear() # 清除输入框已有的字符串
element.send_keys('白月黑羽') # 输入新字符串
print(element.get_attribute('class'))#获取元素属性class的值
print(element.text) # WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容

属性

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

整个元素对应的HTML

要获取整个元素对应的HTML文本内容,可以使用 element.get_attribute(‘outerHTML’)
如果,只是想获取某个元素 内部 的HTML文本内容,可以使用 element.get_attribute(‘innerHTML’)

获取输入框里面的文字

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

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

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

使用 innerText 和 textContent 的区别是,前者只显示元素可见文本内容,后者显示所有内容(包括display属性为none的部分
属性,获取文本内容,就会有问题。

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

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

语法说明
标题文本样式列表图片链接目录代码片表格注脚注释自定义列表LaTeX 数学公式插入甘特图插入UML图插入Mermaid流程图插入Flowchart流程图插入类图快捷键
标题复制

CSS(CSS Selector ,或者说 CSS 选择器)表达式

选择单个元素

find_element(By.CSS_SELECTOR, CSS Selector参数)

选择所有元素

find_elements(By.CSS_SELECTOR, CSS Selector参数)

根据 tag名、id(#)、class(.) 选择元素


elements = wd.find_elements(By.TAG_NAME, 'div')
 #选择 所有的tag名为div的元素
elements = wd.find_elements(By.CSS_SELECTOR, 'div')
element=wd.find_element(By.CSS_SELECTOR, '#searchtext')
 #  css选择器选择 id为searchtext的元素
elements = wd.find_elements(By.CLASS_NAME, 'animal')   
elements = wd.find_elements(By.CSS_SELECTOR, '.animal') 
#css 选择元素的语法是在 class 值 前面加上一个点: .class值

直接子元素

元素1 > 元素2  #元素2是元素1的直接子元素

后代元素

元素1   元素2   #元素2是元素1后代元素

根据属性选择

element = wd.find_element(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')
# 选择 属性href值为 http://www.miitbeian.gov.cn 的元素
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[class=misc][ctype=gun]
div[class='SKnet'] 
#表示 选择所有 标签名为div,且class属性值为SKnet的元素,属性值用单引号,双引号都可以。
[href]
#表示选择 所有 具有 属性名 为href 的元素,不管它们的值是什么

选择语法联合使用

https://cdn2.byhy.net/files/selenium/sample1.html
我们要选择 网页 html 中的元素 版权

<div id='bottom'>
    <div class='footer1'>
        <span class='copyright'>版权</span>
        <span class='date'>发布日期:2018-03-03</span>
    </div>
    <div class='footer2'>
        <span>备案号
            <a href="http://www.miitbeian.gov.cn">苏ICP备88885574</a>
        </span>
    </div>        
</div>   
div.footer1 > span.copyright
# 选择 一个class 属性值为 copyright 的 span 节点, 并且要求其 必须是 class 
#属性值为 footer1 的 div节点 的子节点
.footer1 > .copyright
#一个class 属性值为copyright 的节点(不限类型), 并且要求其 必须是 class 属性值为 footer1
# 的节点的 子节点
.footer1  .copyright
#子元素同时也是后代元素

组选择

css选择器可以 使用 逗号 ,称之为 组选择

同时选择所有tag名为div的元素 和 id为BYHY的元素

div,#BYHY

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

父元素的第n个子节点 nth-child

也就是说 选择的是 第2个子元素,并且是span类型

所以这样可以这样写 span:nth-child(2) ,
如果你不加节点类型限制,直接这样写 :nth-child(2)

父元素的倒数第n个子节点 nth-last-child

p:nth-last-child(1)
就是选择第倒数第1个子元素,并且是p元素

父元素的第几个某类型的子节点 nth-of-type

span:nth-child(2) 选择的是 第2个子元素,并且是span类型
span:nth-of-type(1) 选择的是 第1个span类型 的子元素

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

nth-last-of-type

奇数节点和偶数节点

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

比如

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

p:nth-child(odd)

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

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

相邻兄弟节点选择这样写

h3 + span

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

后续所有兄弟节点选择

https://cdn2.byhy.net/files/selenium/sample1a.html

    <body>  
       <div id='t1'>
           <h3> 唐诗 </h3>
           <span>李白</span>
           <p>静夜思</p>
           <span>杜甫</span>
           <p>春夜喜雨</p>              
       </div>      
        
       <div id='t2'>
           <h3> 宋词 </h3>
           <span>苏轼</span>
           <p>赤壁怀古</p>
           <p>明月几时有</p>
           <p>江城子·乙卯正月二十日夜记梦</p>
           <p>蝶恋花·春景</p>
           <span>辛弃疾</span>
           <p>京口北固亭怀古</p>
           <p>青玉案·元夕</p>
           <p>西江月·夜行黄沙道中</p>
       </div>             

    </body>

frame切换/窗口切换

iframe 元素非常的特殊, 在html语法中,frame 元素 或者iframe元素的内部 会包含一个 被嵌入的 另一份html文档。我们要 操作 被嵌入的 html 文档 中的元素, 就必须 切换操作范围 到 被嵌入的文档中。

wd.switch_to.frame(wd.find_element(By.TAG_NAME, "iframe"))
#
wd.switch_to.default_content()
#切换回原来的主html

切换到新的窗口

切换到新的窗口在新窗口里面 打开一个新网址, 并且去自动化操作新窗口里面的元素

# 点击打开新窗口的链接
link = wd.find_element(By.TAG_NAME, "a")
link.click()

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

wd.switch_to.window(handle)

for handle in wd.window_handles:
    # 先切换到该窗口
    wd.switch_to.window(handle)
    # 得到该窗口的标题栏字符串,判断是不是我们要操作的那个窗口
    if 'Bing' in wd.title:
        # 如果是,那么这时候WebDriver对象就是对应的该该窗口,正好,跳出循环,
        break
# mainWindow变量保存当前窗口的句柄
mainWindow = wd.current_window_handle
#通过前面保存的老窗口的句柄,自己切换到老窗口
wd.switch_to.window(mainWindow)

冻结界面

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

如果我们要用 selenium 自动化 点击 糯米图标,就需要 F12 查看这个元素的特征。但是 当我们的鼠标 从 糯米图标 移开, 这个 栏目就整个消失了, 就没法 查看 其对应的 HTML。

在这里插入图片描述
在 开发者工具栏 console 里面执行如下js代码

setTimeout(function(){debugger}, 5000)
#表示在 5000毫秒后,执行 debugger 命令
#执行该命令会 浏览器会进入debug状态。 
#debug状态有个特性, 界面被冻住, 不管我们怎么点击界面都不会触发事件

弹出对话框

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

driver.switch_to.alert.accept()
注意:如果我们不去点击它,页面的其它元素是不能操作的。

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

driver.switch_to.alert.text
confirm(确认信息)

如果我们想点击 OK 按钮, 还是用刚才的 accept方法,如下

driver.switch_to.alert.accept()
如果我们想点击 Cancel 按钮, 可以用 dismiss方法,如下

driver.switch_to.alert.dismiss()

Xpath

xpath需要前面加 // , 表示从当前节点往下寻找所有的后代元素,不管它在什么位置。
[@属性名=‘属性值’]
//[@multiple] 属性值包含字符串具有multiple属性的所有页面元素
//[contains(@style,‘color’)] style属性值 包含 color 字符串的 页面元素
//
[starts-with(@style,‘color’)] style属性值 以 color 字符串 开头
//p[2] p类型第2个的子元素 , 不是 第2个子元素,并且是p类型
//div/p[2] 父元素为div 中的 p类型 第2个 子元素
//p[last()] 选取p类型倒数第1个子元素
//p[last()-1] 选取p类型倒数第2个子元素
//div/p[last()-2] 选择父元素为div中p类型倒数第3个子元素
//option[position()<=2]
//option[position()❤️]
选择class属性为multi_choice的前3个子元素
//[@class=‘multi_choice’]/[position()<=3]
选择class属性为multi_choice的后3个子元素
//[@class=‘multi_choice’]/[position()>=last()-2
//option | //h4 所有的option元素 和所有的 h4 元素*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值