web自动化-selenium(一)

<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    option,select{
        width: 100px;
    }
    option{
        height: 20px;
    }
</style>

<body>
    <form action="" method="get">
        <input type="text" id="username" name="username" placeholder="username" class='input-text'>
        <br />
        <input type="password" id="password" name="password" placeholder="password" class="input-password">
        <br />
        <input type="text" name="password2" placeholder="确认密码"><br />
    </form>
    <H8>&nbsp;</H8>
    <div id='links'>
        <ul>
            <li><a>标签</a></li>
            <li><a>Genetic Algorithms in Search, Optimization, and Machine Learning</a></li>
            <li>hello</li>
            <li>world</li>
        </ul>
    </div>
    <H8>&nbsp;</H8>
    <div>
        <button id="button" onclick="click()">我是一个按钮</button>
        <span id="click_count">鼠标单击次数: 0</span>
    </div>
    <H8>&nbsp;</H8>
    <div>
        <select name="select" id="select-single">
            <option value="1" selected>zhangsan</option>
            <option value="2">lisi</option>
            <option value="3">wangwu</option>
            <option value="4">zhaoliu</option>
            <option value="5">tangli</option>
        </select>
    </div>
    <H8>&nbsp;</H8>
    <div>
        <select name="select" id="select-multiple" multiple>
            <option value="1" selected>zhangsan</option>
            <option value="2">lisi</option>
            <option value="3">wangwu</option>
            <option value="4">zhaoliu</option>
            <option value="5">tangli</option>
        </select>
    </div>
</body>
<script>

    let click_count = 0
    let button = document.getElementById('button')
    button.onclick = function click(event) {
        click_count++;
        document.getElementById('click_count').innerHTML = `鼠标单击次数: ${click_count}`;
    }
</script>

</html>

什么是Selenium

  • Selenium是一个用于Web应用程序测试的工具,可以直接调用浏览器,它支持所有主流的浏览器。

  • 最初是为网站自动化测试而开发的,但却被很多爬虫爱好者发扬光大

  • 官网:https://www.selenium.dev/

Selenium特点

  • 开源软件:源代码开放可以根据需要来增加工具的某些功能
  • 跨平台:linux 、windows 、mac
  • 核心功能:就是可以在多个浏览器上进行自动化测试
  • 多语言:Java、Python、C#、JavaScript、Ruby等
  • 成熟稳定:目前已经被google , 百度, 腾讯等公司广泛使用
  • 功能强大:能够实现类似商业工具的大部分功能,因为开源性,可实现定制化功能

什么是WebDriver?

Webdriver 是一种用于控制浏览器的程序,不同的浏览器有不同的 webdriver。

  • Chrome (ChromeDriver)

  • IE(InternetExplorerDriver)

  • Opera(OperaDriver)

  • Firefox (FirefoxDriver)

  • safari(SafariDriver)

  • HtmlUnit (HtmlUnit Driver)
    webdriver 提供了对外的接口,其他程序通过这些接口控制 webdriver 与浏览器的交互。例如:我们可以写 python 程序来调用 webdriver 的接口。实际上从其他程序的角度看,webdriver 就是充当了和浏览器交互的一个桥梁。

  • 提示:
    Firefox、Chrome:对元素定位和操作有良好的支持,同时对JavaScript支持也非常好。
    IE: 只能在windows平台运行,所有浏览器中运行速度最慢
    HtmlUnit:无GUI(界面)运行,运行速度最快;

Selenium 执行过程

python代码--> selenium 封装的 python 接口--> WebDriver 提供接口--> 浏览器

环境搭建

基于Python环境搭建

pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple

注意: 在安装selenium时,前提是Python3.5以上版本安装完毕且能正常运行

谷歌浏览器驱动安装

确认浏览器的版本


查看方式

下载驱动

下载与浏览器版本一致的驱动版本

谷歌浏览器驱动下载地址

国内不能直接访问Chrome官网,可以在ChromeDriver仓库中下载 或者 https://npm.taobao.org/mirrors/chromedriver

选择自己对应的平台版本

WebDriver 元素定位简单方式

selenium页面元素定位的方法,是在selenium中可以通过多种方式来定位标签,返回标签元素对象:

  • 通过 id 属性定位 : find_element_by_id
  • 通过 name 属性定位 : find_element_by_name
  • 通过 class 属性定位 : find_element_by_class_name
  • 通过标签名定位 : find_element_by_tag_name
  • 通过内容定位 a 标签(绝对匹配) : find_element_by_link_text
  • 通过内容定位 a 标签(模糊匹配) : find_element_by_partial_link_text
from selenium.webdriver import Chrome
import traceback
from selenium.webdriver.chrome.service import *

from selenium.webdriver.common.by import By

service = Service("./chromedriver")
driver = Chrome(service=service)
# 通过指定chromedriver的路径来实例化driver对象

# 控制浏览器访问url地址
# file://{本地文件绝对路径}
driver.get('file://./test.html')  # 打开本地 html 文件

try:
    print(driver.find_element_by_id('username')) # 通过 id 属性定位
    driver.find_element_by_name('password2')  # 通过 name 属性定位
    driver.find_element_by_class_name('input-password') # 通过 class 属性定位
    driver.find_element_by_tag_name('ul') # 通过标签名定位
    driver.find_element_by_link_text('标签') # 通过内容定位 a 标签(绝对匹配)
    driver.find_element_by_partial_link_text('Optimization')  # 通过内容定位 a 标签(模糊匹配)
except Exception:
    print(traceback.format_exc())
finally:
    # 退出浏览器
    driver.quit()
  • Chrome(executable_path='./chromedriver')中executable参数指定的是下载好的chromedriver文件的路径
  • 要在代码中尽量保证driver.quit()能够成功执行,进而关闭driver退出模拟浏览器;不然将在操作系统中残留进程,对系统造成不必要的压力
  • find_element_by_方式已不推荐使用,推荐使用find_element(By_,元素)

xpath 方式

  1. XPath 即为 XML Path 的简称,它是一种用来确定 XML/HTML 文档中某部分位置的语言。
  2. XPath文档:http://www.w3school.com.cn/xpath/index.asp
  3. HTML 可以看做是 XML 的一种实现,所以 Selenium 用户可以使用这种强大的语言在Web应用中定位元素。

xpath路径

  • html,xml 中的元素可以嵌套其他元素,但是根元素只有一个。我们可以这种嵌套关系看成路径。路径分绝对路径和相对路径:
  • 绝对路径:从根元素到指定元素之间所有经过元素层级路径,绝对路径以 "/" 开始,例如: input 的绝对路径是: /html/body/form/input
  • 相对路径:从任何元素开始到该元素的路径,相对路径以 "//" 开始,例如: 用户名输入框标签的相对路径有: //form/input,//body/form/input

xpath 定位

xpath 定位是结合路径来进行定位的,分为绝对定位和相对定位。定位过程中还可以结合元素的属性值。

定位方法是 find_element_by_xpath

纯路径定位

绝对定位: find_element_by_xpath("/html/body/form/input")

相对定位: find_element_by_xpath("//div/ul/li/a")

结合属性

单个属性: find_element_by_xpath("//input[@type='text']")

多个属性: driver.find_element_by_xpath("//input[@type='text' and @name='username']")

选择上一级元素

find_element_by_xpath("//input/..") 返回的是 form 元素

满足条件的多个元素,选择其中一个

driver.find_element_by_xpath("//ul/li") 有多个 li 满足条件,选择其中一个,通过下标来完成,下标从 1 开始

driver.find_element_by_xpath("//ul/li[1]")

可以结合特殊方法 last() 从后面开始选择 ,比如 //ul/li[last()] 选择最后一个 //ul/li[last()-1] 倒数第二个

from selenium.webdriver import Chrome
import traceback

# 通过指定chromedriver的路径来实例化driver对象
driver = Chrome(executable_path='./chromedriver')

# 控制浏览器访问url地址
# file://{本地文件绝对路径}
driver.get('file:///home/python/code/unit_testing/selenium_code/test.html')  # 打开本地 html 文件

try:
    print(driver.find_element_by_xpath('/html/body/form/input'))
    print(driver.find_element_by_xpath('//div/ul/li'))

    print(driver.find_element_by_xpath('//form/input[@name="password"]'))
    print(driver.find_element_by_xpath('//form/input[@name="password2" and @type="text"]'))

    print(driver.find_element_by_xpath('//li/..'))

    print(driver.find_element_by_xpath('//ul/li[1]'))
    print(driver.find_element_by_xpath('//ul/li[last()]'))
    print(driver.find_element_by_xpath('//ul/li[last()-1]'))
except Exception:
    print(traceback.format_exc())
finally:
    # 退出浏览器
    driver.quit()

CSS 方式

CSS 选择器

CSS 选择器参考手册

在Selenium中也可以使用这种选择器,通过 find_element_by_css_selector:

  1. 在selenium中极力推荐CSS定位,因为它比XPath定位速度要快
  2. CSS 选择器语法非常强大,在这里我们只学习在测试中常用的几个
选择器 例子 描述
#id #userA id选择器,选择id="userA"的所有元素
.class .telA class选择器,选择class="telA"的所有元素
element input 选择所有input元素
[attribute=value] [type="password"] 选择type="password"的所有元素
element>element p>input 选择所有父元素为p元素的input元素
driver.find_element_by_css_selector('#username') # 通过 id
driver.find_element_by_css_selector('.input-text') # 通过 class
driver.find_element_by_css_selector('form') # 通过标签名
driver.find_element_by_css_selector('input[type="password"]') # 通过标签属性
driver.find_element_by_css_selector('div>ul') # 通过父子元素

查询多个元素

  • 通过 id 属性定位 : find_elements_by_id
  • 通过 name 属性定位 : find_elements_by_name
  • 通过 class 属性定位 : find_elements_by_class_name
  • 通过标签名定位 : find_elements_by_tag_name
  • 通过内容定位 a 标签(绝对匹配) : find_elements_by_link_text
  • 通过内容定位 a 标签(模糊匹配) : find_elements_by_partial_link_text
  • 通过 xpath : find_elements_by_xpath
  • 通过 CSS 选择器: find_elements_by_css_selector
    和选择单个元素的字面区别就是多了个 s。
调用这类方法,会返回一个列表,没有找到元素则返回空列表,查找单个元素的方法会在找不到元素时抛出 NoSuchElementException 异常
driver.find_elements_by_id('#no-exist-id') # 返回空数组

driver.find_elements_by_tag_name('li') #  返回数组多个元素

什么是元素等待?

概念:WebDriver定位页面元素时如果未找到,会在指定时间内一直等待的过程。

为什么要设置元素等待?

当使用脚本定位元素或去验证程序的运行状态时,由于资源受限或网络延迟引起的响应速度太慢,导致要定位的元素还未加载到页面。

例如:页面是通过 Ajax 发起请求,但是网络有延迟,提交按钮点击完后,页面等待服务器的返回结果来更新页面,那么在这期间,测试代码是不能够直接去查找预期的元素的。

元素等待类型

显式等待
隐式等待

显式等待

概念:使 WebDriver 等待某个条件成立,否则在达到最大时长时抛出超时异常(TimeoutException)

WebDriverWait 类

from selenium.webdriver.support.wait import WebDriverWait

参数:

  • driver: webdriver对象
  • timeout: 等待多长时间
  • poll_frequency: 每次执行失败时休眠多长时间
调用方法

WebDriverWait.util(method, message=''):

参数说明:

  • method 函数,这个函数必须定义一个参数,接受 driver 对象。例如: def contain_title(driver)
  • message 如果等待失败,message 作为消息抛出
    返回值:如果找到,返回找到元素的对象
from selenium.webdriver import Chrome
import traceback
from selenium.webdriver.support.wait import WebDriverWait
driver = Chrome('./chromedriver')

# 3. 打开网址
# file://{本地网址绝对路径}
driver.get('http://www.baidu.com')


try:
    # time.sleep(2)
    # 1. 指定最长的等待时间,指定检测until函数的时间
    # driver对象,最长等待5s, 如果没有找到,每隔0.5s, 检测until()指定的函数,如果5s都没有找到,抛出异常
    wait_driver = WebDriverWait(driver, 5, 0.5)

    # WebDriverWait.until(), 需要传入一个函数名, 这个函数,参数为Chrome类型
    el = wait_driver.until(lambda temp: temp.find_element_by_tag_name('html'))
    print(el)

except Exception as e:
    # print(e) # 只打印错误信息
    print(traceback.format_exc()) # 有错误路径显示
finally:
    # 不管有没有异常,都保证driver可以关闭
    driver.quit()

隐式等待

隐式等待调用方法

driver.implicitly_wait(10)

隐式等待执行-说明

如果定位某一元素定位失败,那么就会触发隐式等待有效时长,如果在指定时长内加载完毕,则继续执行,否则抛出 NoSuchElementException 异常。

from selenium.webdriver import Chrome
from selenium.webdriver.support.wait import WebDriverWait
import traceback
import time

# 通过指定chromedriver的路径来实例化driver对象
driver = Chrome(executable_path='./chromedriver')

# 控制浏览器访问url地址
driver.get('https://www.baidu.com')

driver.implicitly_wait(5) # 隐式等待

try:
    driver.find_element_by_id('kw')

except Exception as e:
    print('type = ', type(e))
    # print(traceback.format_exc())
finally:
    # 退出浏览器
    driver.quit()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容