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">鼠標單擊次數(shù): 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 = `鼠標單擊次數(shù): ${click_count}`;
    }
</script>

</html>

什么是Selenium

  • Selenium是一個用于Web應用程序測試的工具,可以直接調(diào)用瀏覽器,它支持所有主流的瀏覽器。

  • 最初是為網(wǎng)站自動化測試而開發(fā)的,但卻被很多爬蟲愛好者發(fā)揚光大

  • 官網(wǎng):https://www.selenium.dev/

Selenium特點

  • 開源軟件:源代碼開放可以根據(jù)需要來增加工具的某些功能
  • 跨平臺:linux 、windows 、mac
  • 核心功能:就是可以在多個瀏覽器上進行自動化測試
  • 多語言:Java、Python、C#、JavaScript、Ruby等
  • 成熟穩(wěn)定:目前已經(jīng)被google , 百度, 騰訊等公司廣泛使用
  • 功能強大:能夠?qū)崿F(xiàn)類似商業(yè)工具的大部分功能,因為開源性,可實現(xiàn)定制化功能

什么是WebDriver?

Webdriver 是一種用于控制瀏覽器的程序,不同的瀏覽器有不同的 webdriver。

  • Chrome (ChromeDriver)

  • IE(InternetExplorerDriver)

  • Opera(OperaDriver)

  • Firefox (FirefoxDriver)

  • safari(SafariDriver)

  • HtmlUnit (HtmlUnit Driver)
    webdriver 提供了對外的接口,其他程序通過這些接口控制 webdriver 與瀏覽器的交互。例如:我們可以寫 python 程序來調(diào)用 webdriver 的接口。實際上從其他程序的角度看,webdriver 就是充當了和瀏覽器交互的一個橋梁。

  • 提示:
    Firefox、Chrome:對元素定位和操作有良好的支持,同時對JavaScript支持也非常好。
    IE: 只能在windows平臺運行,所有瀏覽器中運行速度最慢
    HtmlUnit:無GUI(界面)運行,運行速度最快;

Selenium 執(zhí)行過程

python代碼--> selenium 封裝的 python 接口--> WebDriver 提供接口--> 瀏覽器

環(huán)境搭建

基于Python環(huán)境搭建

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

注意: 在安裝selenium時,前提是Python3.5以上版本安裝完畢且能正常運行

谷歌瀏覽器驅(qū)動安裝

確認瀏覽器的版本


查看方式

下載驅(qū)動

下載與瀏覽器版本一致的驅(qū)動版本

谷歌瀏覽器驅(qū)動下載地址

國內(nèi)不能直接訪問Chrome官網(wǎng),可以在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
  • 通過內(nèi)容定位 a 標簽(絕對匹配) : find_element_by_link_text
  • 通過內(nèi)容定位 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('標簽') # 通過內(nèi)容定位 a 標簽(絕對匹配)
    driver.find_element_by_partial_link_text('Optimization')  # 通過內(nèi)容定位 a 標簽(模糊匹配)
except Exception:
    print(traceback.format_exc())
finally:
    # 退出瀏覽器
    driver.quit()
  • Chrome(executable_path='./chromedriver')中executable參數(shù)指定的是下載好的chromedriver文件的路徑
  • 要在代碼中盡量保證driver.quit()能夠成功執(zhí)行,進而關(guān)閉driver退出模擬瀏覽器;不然將在操作系統(tǒng)中殘留進程,對系統(tǒng)造成不必要的壓力
  • 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 的一種實現(xiàn),所以 Selenium 用戶可以使用這種強大的語言在Web應用中定位元素。

xpath路徑

  • html,xml 中的元素可以嵌套其他元素,但是根元素只有一個。我們可以這種嵌套關(guān)系看成路徑。路徑分絕對路徑和相對路徑:
  • 絕對路徑:從根元素到指定元素之間所有經(jīng)過元素層級路徑,絕對路徑以 "/" 開始,例如: input 的絕對路徑是: /html/body/form/input
  • 相對路徑:從任何元素開始到該元素的路徑,相對路徑以 "http://" 開始,例如: 用戶名輸入框標簽的相對路徑有: //form/input,//body/form/input

xpath 定位

xpath 定位是結(jié)合路徑來進行定位的,分為絕對定位和相對定位。定位過程中還可以結(jié)合元素的屬性值。

定位方法是 find_element_by_xpath

純路徑定位

絕對定位: find_element_by_xpath("/html/body/form/input")

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

結(jié)合屬性

單個屬性: find_element_by_xpath("http://input[@type='text']")

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

選擇上一級元素

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

滿足條件的多個元素,選擇其中一個

driver.find_element_by_xpath("http://ul/li") 有多個 li 滿足條件,選擇其中一個,通過下標來完成,下標從 1 開始

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

可以結(jié)合特殊方法 last() 從后面開始選擇 ,比如 //ul/li[last()] 選擇最后一個 //ul/li[last()-1] 倒數(shù)第二個

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
  • 通過內(nèi)容定位 a 標簽(絕對匹配) : find_elements_by_link_text
  • 通過內(nèi)容定位 a 標簽(模糊匹配) : find_elements_by_partial_link_text
  • 通過 xpath : find_elements_by_xpath
  • 通過 CSS 選擇器: find_elements_by_css_selector
    和選擇單個元素的字面區(qū)別就是多了個 s。
調(diào)用這類方法,會返回一個列表,沒有找到元素則返回空列表,查找單個元素的方法會在找不到元素時拋出 NoSuchElementException 異常
driver.find_elements_by_id('#no-exist-id') # 返回空數(shù)組

driver.find_elements_by_tag_name('li') #  返回數(shù)組多個元素

什么是元素等待?

概念:WebDriver定位頁面元素時如果未找到,會在指定時間內(nèi)一直等待的過程。

為什么要設(shè)置元素等待?

當使用腳本定位元素或去驗證程序的運行狀態(tài)時,由于資源受限或網(wǎng)絡(luò)延遲引起的響應速度太慢,導致要定位的元素還未加載到頁面。

例如:頁面是通過 Ajax 發(fā)起請求,但是網(wǎng)絡(luò)有延遲,提交按鈕點擊完后,頁面等待服務器的返回結(jié)果來更新頁面,那么在這期間,測試代碼是不能夠直接去查找預期的元素的。

元素等待類型

顯式等待
隱式等待

顯式等待

概念:使 WebDriver 等待某個條件成立,否則在達到最大時長時拋出超時異常(TimeoutException)

WebDriverWait 類

from selenium.webdriver.support.wait import WebDriverWait

參數(shù):

  • driver: webdriver對象
  • timeout: 等待多長時間
  • poll_frequency: 每次執(zhí)行失敗時休眠多長時間
調(diào)用方法

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

參數(shù)說明:

  • method 函數(shù),這個函數(shù)必須定義一個參數(shù),接受 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. 打開網(wǎng)址
# file://{本地網(wǎng)址絕對路徑}
driver.get('http://www.baidu.com')


try:
    # time.sleep(2)
    # 1. 指定最長的等待時間,指定檢測until函數(shù)的時間
    # driver對象,最長等待5s, 如果沒有找到,每隔0.5s, 檢測until()指定的函數(shù),如果5s都沒有找到,拋出異常
    wait_driver = WebDriverWait(driver, 5, 0.5)

    # WebDriverWait.until(), 需要傳入一個函數(shù)名, 這個函數(shù),參數(shù)為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可以關(guān)閉
    driver.quit()

隱式等待

隱式等待調(diào)用方法

driver.implicitly_wait(10)

隱式等待執(zhí)行-說明

如果定位某一元素定位失敗,那么就會觸發(fā)隱式等待有效時長,如果在指定時長內(nèi)加載完畢,則繼續(xù)執(zhí)行,否則拋出 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()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容