selenium
selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可以用于任何支持JavaScript的浏览器上。
selenium可以模拟真实浏览器,自动化测试工具,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题。
Chromedriver安装和配置
首先要安装好chrome浏览器,以及python3。
安装完成后,此时py并不能操作chrome,因为还需要安装chromedriver。
检查chrome版本
-
首先先查看本地chrome浏览器的版本
下载与chrome版本一致的ChromeDriver(Windows为例)
由于我的chrome浏览器版本为86,因此我选择的ChromeDriver就是为86版本的
-
zip解压后将 chromedriver.exe 放在谷歌安装目录下;将chromedriver.exe 放在python安装的目录下script下
-
安装配置完成后,运行代码
查看到此图的提示则成功啦~~
-
也可以打开cmd命令指示符,输入chromedriver --version
查看此时自己下载的版本是否已经与浏览器版本一致~~
selenium基本使用
web页面元素的6种定位方法
- id:元素的id属性; -- 唯一
- class:元素的classs属性
- name:元素的name属性
- tag:元素的标签名称,如 input,a等
- xpath--重点掌握
- css selector:css选择器
下面重点介绍xpath,其它都比较简单,这里忽略。
使用xpath实现页面元素的定位
我们需要简单的回顾一下html页面的组成:
- 在一个html页面中,存在很多的已经定义好的标签对,通常也称为元素;
- 标签一般包括:标签名、属性以及文本内容,即 <标签名 属性名=属性值>文本内容</标签名>。
根据标签对的构成(或者是元素的3个特征:标签名、属性以及文本内容),我们可以比较方便的实现对页面中元素的定位。
一、 元素定位分类
- 绝对定位
以“/”开头,从根结点开始,逐级定位到当前的结点。 -- 可以与绝对路径进行类比
- 相对定位 -- 推荐
2.1 不依赖结点的位置和顺序;
2.2 只要能够找到匹配的特征元素即可。
二、 辅助工具定位
在对页面中的元素进行定位时,可以使用浏览器中的F12开发者工具。
打开控制台,通过Ctrl+F键打开表达式输入框,输入xpath表达式,就可以定位到对应元素了。
三、 xpath表达式书写规则
说明:该规则仅针对相对定位而言。
-
使用单一属性实现对元素的定位(通常情况下,选取的这些属性的值相对固定)
1.1 //标签名[@属性名=值] -- 根据属性值进行定位
1.2 //标签名[text()=值] -- 根据文本内容进行定位
1.3 //标签名[contains(@属性名,值)] -- 根据属性值进行部分匹配
1.4 //标签名[contains(text(),值)] -- 根据文本内容进行部分匹配
1.5 在进行匹配时,* 表示可以匹配任意的标签名或者属性名。如 //* [contains[@*,"TopicDiscuss"]]
当单一属性无法唯一定位到元素时,可以使用组合条件进行定位
单一属性的组合
2.1 and:特征同时满足
//标签名[text()=值 and @属性名=值 and contains(@属性名,值)]
2.2 or:特征有一个满足即可
//标签名[text()=值 or @属性名=值 or contains(@属性名,值)]
当仅靠待定位元素本身的特征无法属性进行唯一定位时,可以考虑使用层级定位和轴定位层级定位:使用待查找的结点的“祖先”结点进行定位
//祖先结点//待查找的结点
如我们需要定义name=“tj_login”的结点,可以先找到其id="u1"的祖先结点,即 //div[@id="u1"]//a[@name="tj_login"]
元素操作之等待
在模拟操作过程中,经常出现no such element:Unable to locate elementd错误提示,一看就是没有准确定位到元素。
可能有几方面的原因:
- 元素定位表达式有误
定位方案:在html页面中,通过按F12后输入定位表达式确认是否有误
- 等待不到位
定位方案:在代码运行的过程中,通过自动截图查看页面的状态
- 元素在iframe中,即在当前的html页面中内嵌了另外一个html页面
解决方案:
3.1 分辨元素是否在iframe中;
3.2 若在,从当前的html页面中切换到iframe当中的html中,然后再进行元素的定位。
本节中,主要针对等待不到位导致元素无法定位的问题,给出相应的解决方案:在元素查找查找定位执行进行相应的等待,以确保页面加载完成。
等待主要可以划分为:强制等待和智能等待。
强制等待
sleep -- 强制方式,无论页面是否加载完成,等待时间未达到,无法进行其他业务操作。 (可以作为辅助)
智能等待
-
隐式等待 -- implicity_wait(了解即可)
1.1 每个会话只需调用一次;
1.2 找到元素后,执行元素操作。
补充说明:
假设隐式等待的时间设置为10秒,
首先,我们需要明确的是这10秒并非一个固定的等待时间,它并不影响脚本的执行速度;
其次,隐式并不是针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第6秒定位到了元素则继续执行,若直到超出设置的时长10秒还没有定位到元素,则抛出异常。
- 显示等待(掌握)
使用显示等待需要引入WebDriverWait类以及期望条件(expected_condition)
WebDriverWait(driver,timeout,查看周期=0.5).until(条件)
常见的条件有:
(1)元素存在:presence_of_element_located
(2)元素可见:visibility_of_element_located
(3)元素可点击:element_to_be_clickable
说明:
元素在页面中存在,但是不一定可见;但是元素可见,该元素一定在页面中存在。
比如我们在实际应用中可能会遇到元素可以定位成功,但是在对元素进行操作时报错提示元素没有找到的问题。
出现这种情况,可能是元素的什么属性导致了元素不可见,如hidden=“hidden”就能导致当前元素不可见。
因此在设置期望条件时要根据自己的业务需求进行合理的设置。一般情况下,设置元素可见就可以解决大部分的需求了。
- 元素可见
针对上面的情况,可以显示的操作元素属性变为可见,如下:
driver.execute_script("document.getElementById('web_qr_login').style.display='block';")
元素等待demo
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
wait = WebDriverWait(driver,20)
login_btn_loc = (By.ID,'s-top-loginbtn') # 登录元素定位
wait.until(EC.visibility_of_element_located(login_btn_loc)) # 等待元素可见
driver.find_element(*login_btn_loc).click() # 查找元素并进行点击操作
# 点击显示登录界面
login_loc = (By.XPATH,'//p[@title="用户名登录"]')
wait.until(EC.visibility_of_element_located(login_loc))
driver.find_element(*login_loc).click()
# 在登录页面输入用户名和密码,并提交登录信息
user_loc = (By.ID,"TANGRAM__PSP_11__userName")
pwd_loc = (By.ID,"TANGRAM__PSP_11__password")
submit_loc = (By.ID,"TANGRAM__PSP_11__submit")
wait.until(EC.visibility_of_element_located(submit_loc))
driver.find_element(*user_loc).send_keys("18272165137") # 输入用户名
driver.find_element(*pwd_loc).send_keys("12345678") # 输入密码
driver.find_element(*submit_loc).click() # 登录提交