web常用自動化庫——selenium總結


 

概述

selenium是一個模擬控制瀏覽器操作的自動化庫,它可以做到元素定位,鼠標事件,瀏覽器事件,js腳本執行等操作

與request不同的是,request是單獨請求一個http,而selenium則是以瀏覽器方式加載整個頁面流,所以那些異步的請求也不用像request一樣去分析接口,一切都像瀏覽器一樣,所見即所得。

優點是:

1.所見即所得,不用考慮cookie,ajax,重定向等等,方便數據的查取

2.平時在我們在瀏覽器上做的操作(鼠標,瀏覽器操作等),基本都可以用這個實現,並且步驟動態可視

3.多平台支持,不僅語言多平台支持,支持瀏覽器driver也很多

缺點是:

1.慢,由於加載了整個頁面的數據流,資源開銷大,所以對於只想獲取關鍵數據來說肯定沒有請求接口來的快

2.不穩定,腳本維護成本高等,比如你用xpath去找元素,但是前端改其他問題影響到了你這個元素的路徑,那么這個腳本就gg

主要作用:

1.用於前端自動化測試,總的來說算集成測試,更關注用戶端的測試

2.模擬登錄等,爬蟲的模擬登錄常用到,同時使用這種時要開開發者模式,因為已經有很多網站能識別了

3.個人辦公用途,減少重復勞動力。舉個栗子:百度雲離線下載多個鏈接

 

安裝

庫安裝

pip install selenium

WebDriver安裝

WebDriver是W3C的一個標准,由Selenium主持,主要目的就是通過這套WebDriverAPI控制你電腦上的瀏覽器,相當於一個selenium與瀏覽器之間的驅動,需要注意的是,不同瀏覽器,需要安裝不同的WebDriver,常見的如下

Firefox瀏覽器 https://github.com/mozilla/geckodriver/releases
Chrome瀏覽器 https://sites.google.com/a/chromium.org/chromedriver/downloads
IE瀏覽器 http://selenium-release.storage.googleapis.com/index.html
Edge瀏覽器 https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
Opera瀏覽器 https://github.com/operasoftware/operachromiumdriver/releases
PhantomJS瀏覽器 https://phantomjs.org/

其中PhantomJS是一個無窗口的WebDriver,現在已經停更了

根據你電腦所裝瀏覽器版本來安裝WebDriver(至少需要大版本相同,不然會有一些問題),安裝WebDriver很簡單,將可執行文件放到腳本目錄或者python安裝目錄即可

 

WebDriver

創建WebDriver對象

創建WebDriver對象,相當於啟動了瀏覽器

#導入webdriver模塊
from selenium import webdriver

#創建對象,根據你選擇的瀏覽器創建

driver = webdriver.Chrome()
driver = webdriver.Firefox()
driver = webdriver.Ie()
driver = webdriver.Edge()
driver = webdriver.Opera()
driver = webdriver.PhantomJS()

 

WebDriver對象操作

對WebDriver對象的操作可以抽象成你怎么去控制瀏覽器,主要方法有:

1.訪問URL

driver.get("http://www.python.org")

2.窗口大小調整

#設置寬800px 高600px
driver.set_window_size(800,600)

#設置最大,最小
driver.maximize_window()
driver.minimize_window()

3.刷新頁面

driver.refresh()

4.前進后退

driver.forward()
driver.back()

5.關閉瀏覽器或窗口

#關閉瀏覽器
driver.quit()
#關閉窗口
driver.close()

6.返回當前的一些屬性

#當前url
driver.current_url
#返回窗口句柄
driver.current_window_handle  #當前
driver.window_handles #所有
#返回title
driver.title

7.查找元素,返回Element對象,之后會詳細講

find_element_by_name()
find_element_by_id()
find_element_by_xpath()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_tag_name()
find_element_by_class_name()
find_element_by_css_selector()

8.切換窗口

driver.switch_to_window(handle)

9.切換frame

#切換框架,直接輸入iframe的name或id屬性,或者傳入定位的元素
driver.switch_to_frame(frame_reference)

10.截圖保持為文件

#img_path_name為文件路徑,只支持.png格式,文件名注意帶上后綴,如“/Screenshots/foo.png”
driver.get_screenshot_as_file(img_path_name)

11.執行js

#簡單執行
driver.execute_script(script, *args)
    -script:要執行的JavaScript。
    -*args:JavaScript的所有適用參數。

#異步執行
driver.execute_async_script(script, *args)

12.操作cookie

#獲取cookies
driver.get_cookies()

#添加cookie
driver.add_cookie(cookie_dict) 

#刪除cookie
driver.delete_all_cookies()  #所有
driver.delete_cookie(name) #一個,指明key

 

元素Element

查找元素Element

在我們使用driver.get(url)方法后,driver會加載整個頁面,如果我們要操作比如點擊頁面中的某個元素,則首先需要定位到這個元素,再進行操作

注意的是這部分需要HTML CSS XPATH基礎,不熟悉的可以查看W3C教程,這里不做多訴

示例

<html>
 <body>
  <h1>Welcome</h1>
  <p class="content">Site content goes here.</p>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
  </form>
  <a href="continue.html">Continue</a>
</body>
<html>

1.通過id屬性定位

driver.find_element_by_id(‘loginForm’)

#定位<form id="loginForm">

2.通過name屬性定位

driver.find_element_by_name(‘username’)

#定位<input name="username" type="text" />

3.通過class名定位

driver.find_elements_by_class_name(‘content’)

#定位<p class="content">Site content goes here.</p>

4.通過TagName標簽名定位

driver.find_element_by_tag_name(‘input’)

#定位<input name="username" type="text" />,如果匹配了多個,只選第一個

5.通過link text定位,就是通過a標簽的text內容定位

driver.find_elements_by_link_text(‘Continue’) #全匹配 
driver.find_element_by_partial_link_text(‘Cont’) #部分text匹配

#定位<a href="continue.html">Continue</a>

6.通過xpath定位

driver.find_element_by_xpath("//from[input/@name='username']")

#定位<input name="username" type="text" />

 簡單說一句:/ 代表選取直接子節點,// 代表選擇所有子孫節點,. 代表選取當前節點,.. 代表選取當前節點的父節點,@ 則是加了屬性的限定並選取匹配屬性的特定節點,[]是謂語的意思。

7.通過css選擇器定位

driver.find_element_by_css_selector('p.content')

#定位<p class="content">Site content goes here.</p>

8.定位多個元素

將1~7中的find_element_by_xxx改成find_elements_by_xxx則可以返回所有匹配的元素為list

driver.find_elements_by_tag_name(‘input’)

定位[<input name="username" type="text" />
   <input name="password" type="password" />]

9.串聯查找

Element對象也是有find_element_by_xxx這些方法的,所以可以在第一次定位的元素下查找子節點等

driver.find_element_by_id(‘loginForm’).find_element_by_name(‘username’)

10.簡潔方法

find_element(by='id', value=None)與find_elements(by='id', value=None)實際是實現find_element_by_xxx這個的底層實現,只是簡潔些,當然我們也可以用

#導入By模塊,實際里面就是id,class,name這些常量
from selenium.webdriver.common.by import By

driver.find_element(By.NAME,username)

 

元素Element事件

Element對象有一系列的方法,來讓我們操作定位的元素

1.Element.click() 點擊元素

driver.find_elements_by_link_text(‘Continue’).click()

2.輸入文本

#有些輸入框中原有的文本不會被自動清除掉,需要使用clear()方法清除
driver.find_element_by_name(‘username’).clear()

#輸入內容
driver.find_element_by_name(‘username’).send_keys("username")

3.獲取參數

#獲取對應特性值
Element.get_attribute(name)

#獲取對應屬性值
Element.get_property(name)

#property是DOM中的屬性,是JavaScript里的對象;attribute是HTML標簽上的特性,它的值只能夠是字符串。一般用attr就行

#獲取當前元素的內容
Element.text

#獲取當前元素標簽名
Element.tag_name

#獲取當前元素尺寸
Element.size

#獲取當前元素坐標
Element.location

4.判斷方法

#判斷當前元素是否可見
Element.is_displayed()

#判斷當前元素是否被啟用
Element.is_enabled()

#判斷當前元素是否被選中
Element.is_selected()

 

等待

現在的網頁,基本都是使用ajax異步的加載各種資源的,所以可能我們需要定位的元素不會第一時間就加載出來,這時候是無法定位的,也就會拋出異常。而解決這個問題的方法,就是等待。

1.硬性等待

使用time.sleep(sec)實現,需要自己估計網頁加載的時間,硬性地等待,無論網頁加載快慢,都會強制等待這么多時間

import time

time.sleep(10)

2.顯式等待

就是設定一個條件,同時設置一個時間,在這個時間范圍內,如果網頁出現符合的條件,就不等待繼續執行,如果沒有則循環直到超時報錯

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delay_loading")
try:
    element = WebDriverWait(driver,10).until(
        EC.presence_of_element_located((By.ID,"myDynamicElement"))
    )
finally:
    driver.quit()

這段代碼主要講的是:

  1. 實例化WebDriverWait類,傳入driver與最大等待時長,默認poll_frequency(掃描頻率)為500毫秒
  2. until()是WebDriverWait類的一個方法,參數是一個等待條件(expected_conditions),如果滿足等待條件,則WebDriverWait類停止等待,並且返回expected_conditions的值,否則當等待時間到將拋出TimeoutException異常
  3. 除了until()還有個until_not(),看語義就明白
  4. 等待條件(expected_conditions)如果成功則返回element對象,或有些是返回布爾值,或者其它不為null的值

等待條件(expected_conditions)內置的方法主要有:

title_is : #驗證 driver 的 title 是否與傳入的 title 一致,返回布爾值
title_contains : #驗證 driver 的 title 中是否包含傳入的 title,返回布爾值
presence_of_element_located :# 驗證頁面中是否存在傳入的元素,傳入元素的格式是 locator 元組,如 (By.ID, "id1"),返回element對象
visibility_of_element_located : #驗證頁面中傳入的元素( locator 元組格式 )是否可見,這里的可見不僅僅是 display 屬性非 None ,還意味着寬高均大於0,返回element對象或false
visibility_of : #驗證頁面中傳入的元素( WebElement 格式 )是否可見。返回element對象或false
presence_of_all_elements_located : #驗證頁面中是否存在傳入的所有元素,傳入元素的格式是 locator 元組構成的 list,如 [(By.ID, "id1"), (By.NAME, "name1"),返回element或false
text_to_be_present_in_element : #驗證在指定頁面元素的text中是否包含傳入的文本,返回布爾值
text_to_be_present_in_element_value : #驗證在指定頁面元素的value中是否包含傳入的文本,返回布爾值
frame_to_be_available_and_switch_to_it : #驗證frame是否可切入,傳入 locator 元組 或 WebElement,返回布爾值
invisibility_of_element_located : #驗證頁面中傳入的元素( locator 元組格式 )是否可見,返回布爾值
element_to_be_clickable : #驗證頁面中傳入的元素( WebElement 格式 )是否點擊,返回element
staleness_of : #判斷傳入元素(WebElement 格式)是否仍在DOM中,返回布爾值
element_to_be_selected : #判斷傳入元素(WebElement 格式)是否被選中,返回布爾值
element_located_to_be_selected :# 判斷傳入元素(locator 元組格式)是否被選中,返回布爾值
element_selection_state_to_be :# 驗證傳入的可選擇元素(WebElement 格式)是否處於某傳入狀態,返回布爾值
element_located_selection_state_to_be : #驗證傳入的可選擇元素(WebElement 格式)是否處於某傳入狀態,返回布爾值
alert_is_present : #驗證是否有 alert 出現。返回alert對象

3.隱式等待

一種全局的設置,設置一個最大時長,如果定位的元素沒有出現就會循環的查詢直到超時或者元素出現,相比於硬性等待,這個更加彈性,元素出現了就不會等待了

rom selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id('myDynamicElement')

 

行為鏈

ActionChains可以完成簡單的交互行為,例如鼠標移動,鼠標點擊事件,鍵盤輸入,以及內容菜單交互。這對於模擬那些復雜的類似於鼠標懸停和拖拽行為很有用

使用方法:

實例化一個ActionChains對象並在對象上調用行為方法時,這些行為會存儲在ActionChains對象的一個隊列里。只有調用perform()時,這些動作就以他們隊列的順序來觸發

導入類

from selenium.webdriver import ActionChains

鏈式模型操作:

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

隊列順序操作:

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
action.perform()

主要的行為方法有

click(on_element=None)
#點擊一個元素。參數:on_element:要點擊的元素,如果是None,點擊鼠標當前的位置

click_and_hold(on_element=None)
#鼠標左鍵點擊一個元素並且保持。參數:on_element:同click()類似

double_click(on_element=None)
#雙擊一個元素

drag_and_drop(source, target)
#鼠標左鍵點擊source元素,然后移動到target元素釋放鼠標按鍵

drag_and_drop_by_offset(source, xoffset,yoffset)
#拖拽目標元素到指定的偏移點釋放。參數: source:點擊的參數 xoffset:X偏移量 * yoffset:Y偏移量

key_down(value,element=None)
#只按下鍵盤,不釋放。我們應該只對那些功能鍵使用(Contril,Alt,Shift)。參數: value:要發送的鍵,值在Keys類里有定義 element:發送的目標元素,如果是None,value會發到當前聚焦的元素上

key_up(value,element=None)
#釋放鍵。參考key_down的解釋

move_by_offset(xoffset,yoffset)
#將當前鼠標的位置進行移動

move_to_element(to_element)
#把鼠標移到一個元素的中間

move_to_element_with_offset(to_element,xoffset,yoffset)
#鼠標移動到元素的指定位置,偏移量以元素的左上角為基准。參數: to_element:目標元素 xoffset:要移動的X偏移量 * yoffset:要移動的Y偏移量

perform()
#執行所有存儲的動作

release(on_element=None)
#釋放一個元素上的鼠標按鍵

send_keys(*keys_to_send)
#向當前的焦點元素發送鍵

send_keys_to_element(element,*keys_to_send)
#向指定的元素發送鍵

參考的key值在這里

 

彈窗操作

目前主流彈窗就三種,alert,window,div封裝的

alert彈窗

alert彈窗主要是js中alert()、confirm()、prompt()方法實現的,雖然這三種在js中不同,但對selenium都可以統一實例化Alert對象處理,首先查看Alert對象的主要方法

#接受和忽略彈框:

Alert(driver).accept()
Alert(driver).dismiss()

#prompt里輸入字符:

Alert(driver).send_keys("text")

#讀取prompt的提示字符:

Alert(driver).text

#向一個認證的對話框發送用戶名和密碼,會自動點擊確認

Alert(driver).authenticate('user','passwd')

對於彈窗生成Alert對象主要有兩種方法

1.使用driver的API切換至彈窗操作

alert = driver.switch_to_alert() #底層實際就是Alert(driver),返回Alert對象

2.直接使用Alert類實例化

from selenium.webdriver.common.alert import Alert

alert = Alert(driver)

window類型

window類型實際就是那種點擊界面元素后,瀏覽器新開的一個窗口,我們可以用driver的API直接切換到這個窗口進行一般的定位元素那些操作

#選擇對應的window_handle切換
driver.switch_to_window(window_handle)

#window_handle獲取
driver.current_window_handle
driver.window_handles

div封裝的

div封裝的彈窗就是使用瀏覽器F12查看HTML源代碼時,彈窗的代碼由div標簽封裝在頁面中,所以這種彈窗可以直接find_element_by_xxx直接定位

可能還有網頁中使用frame標簽的,這就需要先切換到新的frame,上面driver的方法有介紹

如果對JavaScript熟悉的,這些彈窗都可以用js處理

 

 

參考:

https://python-selenium-zh.readthedocs.io/zh_CN/latest

https://selenium-python.readthedocs.io/api.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM