Python+Selenium详解(超全)

Python与机器学习 徐 自远 1002℃

 

 

一、Selenium+Python环境搭建及配置

1.1 selenium 介绍

selenium 是一个 web 的自动化测试工具,不少学习功能自动化的同学开始首选 selenium ,因为它相比 QTP 有诸多有点:

  • 免费,也不用再为破解 QTP 而大伤脑筋
  • 小巧,对于不同的语言它只是一个包而已,而 QTP 需要下载安装1个多 G 的程序。
  • 这也是最重要的一点,不管你以前更熟悉 C、 java、ruby、python、或都是 C# ,你都可以通过 selenium 完成自动化测试,而 QTP 只支持 VBS
  • 支持多平台:windows、linux、MAC ,支持多浏览器:ie、ff、safari、opera、chrome
  • 支持分布式测试用例的执行,可以把测试用例分布到不同的测试机器的执行,相当于分发机的功能。

1.2 selenium+Python环境配置

前提条件:已安装好Python开发环境(推荐安装Python3.5及以上版本)

安装步骤

  1. 安装selenium
    Win:pip install selenium
    Mac:pip3 install selenium
  2. 安装webdriver
    :webdriver需要和对应的浏览器版本以及selenium版本对应
  1. webdriver安装路径
    Win:复制webdriver到Python安装目录下
    Mac:复制webdriver到/usr/local/bin目录下

二、元素定位及浏览器基本操作

2.1 启动浏览器

2.1.1 普通方式启动

启动Chrome浏览器:

启动Firefox浏览器:

启动IE浏览器:

2.1.2 Headless方式启动

Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。相比于现代浏览器,Headless Chrome 更加方便测试 web 应用,获得网站的截图,做爬虫抓取信息等。相比于较早的 PhantomJS,SlimerJS 等,Headless Chrome 则更加贴近浏览器环境。

Headless Chrome 对Chrome版本要求
官方文档中介绍,mac和linux环境要求chrome版本是59+,而windows版本的chrome要求是60+,同时chromedriver要求2.30+版本。

2.1.3 加载配置启动浏览器

Selenium操作浏览器是不加载任何配置的,下面是关于加载Chrome配置的方法:

用Chrome地址栏输入chrome://version/,查看自己的“个人资料路径”,然后在浏览器启动时,调用这个配置文件,代码如下:

而加载Firefox配置的方法有些不同:

打开Firefox点右上角设置>?(帮助)>故障排除信息>显示文件夹,打开后把路径复制下来就可以了


2.2 元素定位

对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象。一个对象就是一个人一样,他会有各种的特征(属性),如比我们可以通过一个人的身份证号,姓名,或者他住在哪个街道、楼层、门牌找到这个人。那么一个对象也有类似的属性,我们可以通过这个属性找到这对象。

webdriver 提供了一系列的对象定位方法,常用的有以下几种:

  • id定位:find_element_by_id()
  • name定位:find_element_by_name()
  • class定位:find_element_by_class_name()
  • link定位:find_element_by_link_text()
  • partial link定位:find_element_by_partial_link_text()
  • tag定位:find_element_by_tag_name()
  • xpath定位:find_element_by_xpath()
  • css定位:find_element_by_css_selector()

2.2.1 class含有空格时解决方法:

在实际进行元素定位时,经常发现class name是有多个class组合的复合类,中间以空格隔开。如果直接进行定位会出现报错,可以通过以下方式处理:

  • class属性唯一但是有空格,选择空格两边唯一的那一个
  • 若空格隔开的class不唯一可以通过索引进行定位
    self.driver.find_elements_by_class_name(‘table-dragColumn’)[0].click()
  • 通过css方法进行定位(空格以‘.’代替)

参考代码:


2.3 selenium三种等待方式

有时候为了保证脚本运行的稳定性,需要脚本中添加等待时间。

2.3.1 强制等待

第一种也是最简单粗暴的一种办法就是强制等待sleep(xx),需要引入“time”模块,这种叫强制等待,不管你浏览器是否加载完了,程序都得等待3秒,3秒一到,继续执行下面的代码,作为调试很有用,有时候也可以在代码里这样等待,不过不建议总用这种等待方式,太死板,严重影响程序执行速度。

2.3.2 隐性等待

第二种办法叫隐性等待,通过添加 implicitly_wait() 方法就可以方便的实现智能等待;implicitly_wait(30) 的用法应该比 time.sleep() 更智能,后者只能选择一个固定的时间的等待,前者可以 在一个时间范围内智能的等待。

隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。注意这里有一个弊端,那就是程序会一直等待整个页面加载完成,也就是一般情况下你看到浏览器标签栏那个小圈不再转,才会执行下一步,但有时候页面想要的元素早就在加载完成了,但是因为个别js之类的东西特别慢,我仍得等到页面全部完成才能执行下一步,我想等我要的元素出来之后就下一步怎么办?有办法,这就要看selenium提供的另一种等待方式——显性等待wait了。
需要特别说明的是:隐性等待对整个driver的周期都起作用,所以只要设置一次即可,我曾看到有人把隐性等待当成了sleep在用,走哪儿都来一下…

2.3.3 显性等待

第三种办法就是显性等待,WebDriverWait,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了。它主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。

wait模块的WebDriverWait类是显性等待类,先看下它有哪些参数与方法:

selenium.webdriver.support.wait.WebDriverWait(类)

init

until

until_not

看了以上内容基本上很清楚了,调用方法如下:

WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)

这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id(‘kw’)) # 错误

这是错误的用法,这里的参数一定要是可以调用的,即这个对象一定有 call() 方法,否则会抛出异常:

TypeError: ‘xxx’ object is not callable

在这里,你可以用selenium提供的 expected_conditions 模块中的各种条件,也可以用WebElement的 is_displayed() 、is_enabled()、**is_selected() **方法,或者用自己封装的方法都可以。


2.4 浏览器操作

2.4.1 浏览器最大化、最小化

将浏览器最大化显示

browser.maximize_window()

将浏览器最小化显示

browser.minimize_window()

2.4.2 浏览器设置窗口大小

设置浏览器宽480、高800显示

browser.set_window_size(480, 800)

2.4.3 浏览器前进后退

前进

browser.forword()

后退

browser.back()


2.5 操作测试对象

一般来说,webdriver 中比较常用的操作对象的方法有下面几个:

  • click——点击对象
  • send_keys——在对象上模拟按键输入
  • clear——清除对象的内容,如果可以的话
  • submit——提交对象的内容,如果可以的话
  • text——用于获取元素的文本信息

2.6 键盘事件

要想调用键盘按键操作需要引入 keys 包:
from selenium.webdriver.common.keys import Keys通过 send_keys()调用按键:
send_keys(Keys.TAB) # TAB
send_keys(Keys.ENTER) # 回车

参考代码:

键盘组合键的用法:


2.7 鼠标事件

鼠标事件一般包括鼠标右键、双击、拖动、移动鼠标到某个元素上等等。
需要引入ActionChains类。
引入方法:
from selenium.webdriver.common.action_chains import ActionChains

鼠标双击示例:

鼠标拖放示例:


2.8 多层框架/层级定位

定位元素过程中经常会遇到找不到元素的问题,出现该问题一般都是以下因素导致:

  • 元素定位方法不对
  • 页面存在iframe或内嵌窗口
  • 页面超时

webdriver 提供了一个 switch_to_frame 方法,可以很轻松的来解决这个问题。
用法:

同样的,如果是内嵌窗口:
browser.switch_to_window(“f1”)


2.9 Expected Conditions解析

Expected Conditions的使用场景有2种:

  • 直接在断言中使用
  • 与WebDriverWait配合使用,动态等待页面上元素出现或者消失

相关方法:

  • title_is: 判断当前页面的title是否精确等于预期
  • title_contains: 判断当前页面的title是否包含预期字符串
  • presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
  • visibility_of_element_located:判断某个元素是否可见.可见代表元素非隐藏,并且元素的宽和高都不等于0
  • visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
  • presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是’column-md-3’,那么只要有1个元素存在,这个方法就返回True
  • text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串
  • text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
  • frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
  • invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
  • element_to_be_clickable:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
  • staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
  • element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
  • element_selection_state_to_be:判断某个元素的选中状态是否符合预期
  • element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
  • alert_is_present:判断页面上是否存在alert,这是个老问题,很多同学会问到

示例:
判断title:title_is()、title_contains()

  1. 首先导入expected_conditions模块
  2. 由于这个模块名称比较长,所以为了后续的调用方便,重新命名为EC了(有点像数据库里面多表查询时候重命名)
  3. 打开博客首页后判断title,返回结果是True或False


三、Selenium速查表

3.1 Python Webdriver Exception速查表

webdriver在使用过程中可能会出现各种异常,我们需要了解该异常并知道如何进行异常处理。

异常 描述 WebDriverException 所有webdriver异常的基类,当有异常且不属于下列异常时抛出 InvalidSwitchToTargetException 下面两个异常的父类,当要switch的目标不存在时抛出 NoSuchFrameException 当你想要用switch_to.frame()切入某个不存在的frame时抛出 NoSuchWindowException 当你想要用switch_to.window()切入某个不存在的window时抛出 NoSuchElementException 元素不存在,一般由find_element与find_elements抛出 NoSuchAttributeException 一般你获取不存在的元素属性时抛出,要注意有些属性在不同浏览器里是有不同的属性名的 StaleElementReferenceException 指定的元素过时了,不在现在的DOM树里了,可能是被删除了或者是页面或iframe刷新了 UnexpectedAlertPresentException 出现了意料之外的alert,阻碍了指令的执行时抛出 NoAlertPresentException 你想要获取alert,但实际没有alert出现时抛出 InvalidElementStateException 下面两个异常的父类,当元素状态不能进行想要的操作时抛出 ElementNotVisibleException 元素存在,但是不可见,不可以与之交互 ElementNotSelectableException 当你想要选择一个不可被选择的元素时抛出 InvalidSelectorException 一般当你xpath语法错误的时候抛出这个错 InvalidCookieDomainException 当你想要在非当前url的域里添加cookie时抛出 UnableToSetCookieException 当driver无法添加一个cookie时抛出 TimeoutException 当一个指令在足够的时间内没有完成时抛出 MoveTargetOutOfBoundsException actions的move操作时抛出,将目标移动出了window之外 UnexpectedTagNameException 获取到的元素标签不符合要求时抛出,比如实例化Select,你传入了非select标签的元素时 ImeNotAvailableException 输入法不支持的时候抛出,这里两个异常不常见,ime引擎据说是仅用于linux下对中文/日文支持的时候 ImeActivationFailedException 激活输入法失败时抛出 ErrorInResponseException 不常见,server端出错时可能会抛 RemoteDriverServerException 不常见,好像是在某些情况下驱动启动浏览器失败的时候会报这个错


3.2 Xpath&Css定位方法速查表

描述 Xpath Css 直接子元素 //div/a div > a 子元素或后代元素 //div//a div a 以id定位 //div[@id=’idValue’]//a div#idValue a 以class定位 //div[@class=’classValue’]//a div.classValue a 同级弟弟元素 //ul/li[@class=’first’]/following- ul>li.first + li 属性 //form/input[@name=’username’] form input[name=’username’] 多个属性 //input[@name=’continue’ and input[name=’continue’][type=’button 第4个子元素 //ul[@id=’list’]/li[4] ul#list li:nth-child(4) 第1个子元素 //ul[@id=’list’]/li[1] ul#list li:first-child 最后1个子元素 //ul[@id=’list’]/li[last()] ul#list li:last-child 属性包含某字段 //div[contains(@title,’Title’)] div[title*=”Title”] 属性以某字段开头 //input[starts-with(@name,’user’)] input[name^=”user”] 属性以某字段结尾 //input[ends-with(@name,’name’)] input[name$=”name”] text中包含某字段 //div[contains(text(), ‘text’)] 无法定位 元素有某属性 //div[@title] div[title] 父节点 //div/.. 无法定位 同级哥哥节点 //li/preceding-sibling::div[1] 无法定位

 

 

Python+Selenium详解(超全)http://t.zijieimg.com/CYvC4Y/

转载请注明:徐自远的乱七八糟小站 » Python+Selenium详解(超全)

喜欢 (1)

苏ICP备18041234号-1 bei_an 苏公网安备 32021402001397号