(一)Selenium基礎
入門教程:Selenium官網教程
1.Selenium簡介
Selenium是一個用於測試網站的自動化測試工具,支持各種瀏覽器包括Chrome、Firefox、Safari等主流界面瀏覽器,同時也支持phantomJS無界面瀏覽器。
2.支持多種操作系統
如Windows、Linux、IOS、Android等。
3.安裝Selenium
pip install selenium
4.安裝瀏覽器驅動
Selenium3.x調用瀏覽器必須有一個webdriver驅動文件
- Chrome驅動文件下載:https://npm.taobao.org/mirrors/chromedriver/(需要下載和我們電腦中Chrome瀏覽器同樣的版本,如果沒有同樣的版本,下載距離最近的版本,電腦是64位,下載32位的是可以正常使用的),下載后,進入壓縮包,點擊【解壓到】,放到“Python”的【類似Python38】安裝目錄下
- Firefox驅動文件下載:https://github.com/mozilla/geckodriver/releases
5、與瀏覽器建立連接
Selenium原理:通過http接口請求的方式進行的數據的傳遞
from selenium import webdriver browser = webdriver.Chrome()
#執行代碼時遇到報錯,找不到瀏覽器路徑,可加上參數、chromedriver路徑
browser= webdriver.Chrome(executable_path=r'user/xxxx/chromedriver')
browser.get("http://www.baidu.com") #打開百度
6、查找元素
對於操作瀏覽器中的頁面的自動化測試框架來說,肯定少不了 去發現網頁中的元素,你只有發現那些元素實時存在了才能做出下一步的操作。Selenium中提供了眾多的方法供我們去找到網頁中的元素,這給我們帶來了很大的便利,那么都有哪些方法了,我們可以通過Python快速獲取到這些方法:
#9種單數形式
find_element(‘id’,‘kw’) #根據所需指定:如‘id’、‘xpath’等,第二個參數為:對應的屬性值——這個方法了常用,以下的其他都是通過這個方法封裝的,這個會靈活一點 find_element_by_class_name #通過Class name查找指定的一個元素 find_element_by_css_selector #通過CSS選擇器查找指定的一個元素(和xpath定位找到類似),優先使用,日后查找問題會方便快捷 find_element_by_id #通過ID查找指定的一個元素 find_element_by_link_text #通過a標簽鏈接文本獲取指定的一個超鏈接(精確匹配) find_element_by_name #通過Name查找指定的一個元素 find_element_by_partial_link_text #通過鏈接文本獲取指定的一個超鏈接(模糊匹配) find_element_by_tag_name #通過標簽名查找指定的一個元素(如:div、span),默認找到第一個頁面元素 find_element_by_xpath #通過Xpath語法來指定的一個元素
#9種復數形式:
find_elements #通過指定方法查找所有元素(需指定兩個參數) find_elements_by_class_name #通過Class name查找所有元素 find_elements_by_css_selector #通過CSS選擇器查找所有元素 find_elements_by_id #通過ID查找所有元素 find_elements_by_link_text #通過鏈接文本獲取所有超鏈接(精確匹配) find_elements_by_name #通過Name查找所有元素 find_elements_by_partial_link_text #通過鏈接文本獲取所有超鏈接(模糊匹配) find_elements_by_tag_name #通過標簽名查找所有元素 find_elements_by_xpath #通過Xpath語法來查找所有元素,前端是一個‘樹形’結構的頁面,xpath是以文件路徑的形式一級一級查找元素,如:/html/body/div[2],
單數形式:獲取到的是符合一個元素
復數形式:獲取到的是符合的所有元素,定位一個元素,可使用下邊的方式定位
Copy出有時候是“相對路徑”,有時候是“絕對路徑”,機器來獲取的不一定。
注:Copy_Copy full xpath——絕對路徑
因復制的,有時候會不盡人意,一般使用手寫xpath,如://*[@id='su'],屬性可以自定義,如:name、class,maxlens等都可以
如遇到,如有2個name是“wd”,我們可以加 and條件,可以這樣寫://*[@name=“wd” and id=“1”]
//: 獲取所有內容
* : 任意一個元素,可以替換為任意指定標簽屬性,如:div、input;例://span[@name=“wd”],這樣子會查找的不是所有元素,而是sapn標簽中的所有
@ : 表示篩選類型是【屬性】
id: 指定的元素key
su: 指定元素的value
可以看到輸入框的ID為KW,Name為WD,這里我們選擇ID,選擇ID有三種方法,如下:
from selenium import webdriver from selenium.webdriver.common.by import By c= webdriver.Chrome() c.get('https://www.baidu.com') kw1=c.find_element(By.ID,'kw') kw2=c.find_element_by_id('kw') kw3=c.find_elements_by_id('kw')[0] print(kw1) print(kw2) print(kw3)
可以看到我們成功使用三種方法獲取到了這個元素,其它方法差不多,都是一通百通,喜歡哪種方法就使用哪種方法。
- a標簽中文本類型(text)怎么定位
//a[text()=“文本名稱”]#a可以為任意的標簽名稱
- 只寫屬性名查詢,不寫屬性值
//input[@id]#查詢到input標簽中含有id的所有元素,默認在從上到下第一元素位置
- 一切正常,元素無法定位到的主要原因:
- 等待時間不夠
- 等待的方式有問題(隱形等待、顯性等待、強制等待)
- 有iframe
- 句柄的切換(如:快捷登錄,點擊QQ登錄后,進入到了新的瀏覽器窗口,但我們所能識別的只是我們操作中的一個瀏覽器窗口,就需要切換句柄操作后,在切換回來)
- 頁面沒有聚焦(最大化),會導致有些元素沒被顯示出來,或是需要滑輪下滑后才可看到,或是有被其他的欄位遮擋
- 有重復元素,且被優先選中
7、瀏覽器操作
(1)獲取本頁面URL
c.current_url
(2)獲取日志
c.log_types #獲取當前日志類型 c.get_log('browser')#瀏覽器操作日志 c.get_log('driver') #設備日志 c.get_log('client') #客戶端日志 c.get_log('server') #服務端日志 ##3.窗口操作 c.maximize_window()#最大化 c.fullscreen_window() #全屏 c.minimize_window() #最小化 c.get_window_position() #獲取窗口的坐標 c.get_window_rect()#獲取窗口的大小和坐標 c.get_window_size()#獲取窗口的大小 c.set_window_position(100,200)#設置窗口的坐標 c.set_window_rect(100,200,32,50) #設置窗口的大小和坐標 c.set_window_size(400,600)#設置窗口的大小 c.current_window_handle #返回當前窗口的句柄 c.window_handles #返回當前會話中的所有窗口的句柄
(3)設置延時
【等待的作用】: 在系統的功能運行過程中,所有的內容需要一定的時間來實現展示(需要從服務端獲取到返回回來)
- 時間消耗的長短相關: 網絡速度、系統的框架設定、接口的復雜程度、sql語句的編寫等等。
- 在自動化中,我們做UI測試,主要是基於系統的流程來實現自動化,往往一些下一步需要上一步的特定操作完成后才可以繼續執行(如:需要登錄后才可以進入首頁操作)。在下一步准備執行時,上一步必須是已經執行完,且已生成了實際結果。
- 考慮到運行時間的問題,以及流程的步驟問題,所以我們在實際執行自動化的時候,需要設置下緩沖時間。如果沒有設置緩沖時間,會導致還沒等頁面加載完,就會操作,會找不到此元素,自然就會報錯了。
c.set_script_timeout(5) #設置腳本延時五秒后執行 c.set_page_load_timeout(5)#設置頁面讀取時間延時五秒
三大等待時間:
1. 強制等待: 通過導入“time”模塊中的sleep方法,等待x秒以后,在繼續執行后續的代碼,無所謂當前處於什么階段,執行了什么操作,后續是否已經准備就緒,反正就是要等待x秒,一般是剛學習自動化的過程中使用,實際中基本不使用
【缺點】: 無法精准的把握等待時間(無法判斷是否達到下一步可以操作/無法判定頁面是否已經加載完),如果一直使用強制等待,會嚴重影響自動化效率,浪費好多時間。
【優點】: 一般在調試的時候使用,簡單使用,可一下清楚是不是頁面緩沖需要加等待時間。
import time sleep(5) #等待5秒
2. 隱式等待: 純粹基於webdriver進行調用的,每一個腳本執行時,都會調用隱式等待;不操作quit()釋放,隱式等待是一直起作用的,釋放后才會沒有了隱式等待。
設置一個隱形的等待,設置最長的等待時間,如果在這個時間內完成了頁面內容的全部加載,則進行下一步,否則一直等待到時間結束,再執行下一步
【優點】: 對整個Webdriver周期都會起到作用,只需要設置一次。
【缺點】必須要等待頁面全部加載完成,才可以進行下一步,有些時候特定的元素已經被加載出來,但是頁面本身還沒被加載完,就會等待到設置的等待時間完了,才會進行下一步,應用上會不太靈活
driver.implicitly_wait(10) #隱式等待10秒,設置到一開始的位置
3.顯示等待: 專門對於指定的條件進行等待,在設置的最大時長內,依照查找的時間頻率來進行搜索,查找指定的對象,until表示如果找到,則進行下一步,否則超時后的拋出異常信息,默認拋出NoSuchElementExeception異常。until_not()方法則相反。
如:百度關鍵字查詢出來后點擊第一個搜索內容,設置顯示等待后,只要第一個內容有被加載出來,就會點擊操作,不會繼續等待其他的加載內容了
from selenium.webdriver.support.wait import WebDriverWait #導入模塊 WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None) ''' driver:瀏覽器驅動 timeout:最長超時時間,默認以秒為單位 poll_frequency:檢測的間隔步長,默認為0.5s ignored_exceptions:超時后的拋出的異常信息,默認拋出NoSuchElementExeception異常。 與until()或者until_not()方法結合使用 WebDriverWait(driver,10).until(method,message="") 調用該方法提供的驅動程序作為參數,直到返回值為True WebDriverWait(driver,10).until_not(method,message="") 調用該方法提供的驅動程序作為參數,直到返回值為False 在設置時間(10s)內,等待后面的條件發生。如果超過設置時間未發生,則拋出異常。在等待期間,每隔一定時間(默認0.5秒),調用until或until_not里的方法,直到它返回True或False. WebDriverWait與expected_conditions結合使用 ''' from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By wait = WebDriverWait(driver,10,0.5) element =wait.until(EC.presence_of_element_located((By.ID,"kw")),message="") # 此處注意,如果省略message=“”,則By.ID外面是三層()
(4)關閉
c.close() #關閉當前標簽頁,不會關閉“webdrive”進程,有多個標簽頁時,只會關閉當前標簽頁 c.quit() #關閉瀏覽器並關閉驅動,腳本最后加上,不加上“webdriver”進程一直是沒關閉的狀態,再次執行腳本會再次新打開一個webdriver進程
(5)打印網頁源代碼
c.page_source
(6)屏幕截圖操作
c.save_screenshot('1.png')#截圖,只支持PNG格式 c.get_screenshot_as_png() #獲取當前窗口的截圖作為二進制數據 c.get_screenshot_as_base64() #獲取當前窗口的截圖作為base64編碼的字符串 driver.get_screenshot_as_file('1.png') #獲取當前窗口截圖保存在當前運行路徑下
實操:
from selenium import webdriver driver = webdriver.Chrome() driver.get('http://baidu.com') driver.save_screenshot('./test.png')
結果:
(7)前進后退刷新
c.forward() #前進 c.back() #后退 c.refresh()#刷新
(8)執行JS代碼
在Selenium中也可以自定義JS代碼並帶到當前頁面中去執行,如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time
c=webdriver.Chrome() c.get('https://www.baidu.com') kw1=c.find_element(By.ID,'kw') c.execute_script("alert('hello')") time.sleep(3) c.quit()
driver.execute_script('window.scrollTo(0,0)') #滾動條到頂部
這里我使用一個JS中的函數來執行屏幕提示的功能,成功被執行。
(9)Cookies操作
c.get_cookie('BAIDUID') #獲取指定鍵的Cookies c.get_cookies() #獲取所有的Cookies for y in c.get_cookies(): x=y if x.get('expiry'): x.pop('expiry') c.add_cookie(x) #添加Cookies c.delete_cookie('BAIDUID') #刪除指定鍵的Cookies內容 c.delete_all_cookies() #刪除所有cookies
(10)獲取瀏覽器窗口標題名稱
c.title
(11)獲取當前瀏覽器名
c.name
(12)全局超時時間
c.implicitly_wait(5)
(13)鼠標懸停
——基於Actionchains類實現懸停,操作時,不要手動鼠標
el = driver.find_element('id','kw') ActionChains(driver).move_to_element(el).perform()
(14)自定義瀏覽器窗口大小(一般不會使用,會影響性能,有可能會導致報錯)
driver.set_window_size(1500,800)#自定義設置窗口大小 driver.maximize_window() #窗口最大化 driver.get.window_size() #獲取當前窗口大小
(15)不自動關閉瀏覽器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach",True) driver = webdriver.Chrome(chrome_options=option)
(二)元素操作
對我們找到的元素進行二次操作,不僅可以再次選擇子元素還可以進行其它操作。如下:
kw1.clear() #清除元素的值(單元框、復選框也可用) kw1.click() #點擊元素(下拉框中,使用select類,只能用於select標簽,其他的用不了) clickAndWait() #點擊並等待 kw1.id #Selenium所使用的內部ID kw1.get_property('background') #獲取元素的屬性的值 kw1.get_attribute('id') #獲取元素的屬性的值 kw1.location #不滾動獲取元素的坐標 kw1.location_once_scrolled_into_view #不滾動且底部對齊並獲取元素的坐標 kw1.parent #父元素 kw1.send_keys('') #向元素內輸入值 kw1.size #大小 kw1.submit #提交 kw1.screenshot('2.png') #截取元素形狀並保存為圖片 kw1.tag_name #標簽名 kw1.text #內容,如果是表單元素則無法獲取 kw1.is_selected() #判斷元素是否被選中 kw1.s_enabled() #判斷元素是否可編輯 kw1.is_displayed #判斷元素是否顯示 kw1.value_of_css_property('color') #獲取元素屬性的值 kw1._upload('2.png') #上傳文件 kw1.send.keys(r'c:/圖片.jpg') #上傳文件(只能基於“input”標簽操作,非input標簽,需要用到autoIT庫)
-
Select類操作
select = Select(driver_find_element('xpsth','//*[@id='kw'])) select.select_by_value(標簽會有一個value屬性,基於這個屬性進行選擇) select.select_by_index(基於option的下標進行選擇) select.select_by_visible_text(基於option的文本信息進行選擇)
-
句柄操作
- selenium默認是聚焦在第一個頁面
- 在selenium體系中不同的標簽頁,被認定為不同的句柄,如果要切換頁面,本質上就是切換句柄,可以理解為每個頁面有id,我們切換到第二個id頁面
- 當你在測試執行中,需要操作新的標簽頁執行業務流程時,就需要切換句柄,在進行操作
- 切換原則:永遠是標簽頁最多保留2個,特殊情況最多是3個(因標簽頁名稱是被處理過密文,過多時或有刪除時不利於管理,)
handles = driver.window_handles #獲取到頁面所有句柄 driver.switch_to.window(handles[1]) #指定切換到第幾個句柄(0代表當前頁面,1是第二個頁面)
- 根據屬性獲取頁面文案
element = driver.element('id','kw') #定位到元素 data = element.get_attribute('innerText') #根據標簽屬性獲取到文案
- 判斷CheckBox值是否勾選
driver.find_element('id','kw').is_selected() #返回布爾值,勾選:True,不勾選:False
- 判斷頁面display隱藏欄是否顯示
driver.find_element('id','kw').is_displayed() #返回布爾值,顯示: True 不顯示: False
-
Selenium4
(1)相對定位器
——不太好用,比較出名,Selenium4新出的定位方法,依據人的習慣來定位(根據上下左右和附近五種方法定位,一般用於表單填寫會好點)
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.relative_locator import locate_with driver = webdrive.Chrome() driver.get('http://www.baidu.com') el = driver.elment('id','kw') #相對定位器,定位是有距離限制,是50px還是多少,具體參考官方文檔
driver.find_element(locate_with(By.TAG_NAME,'input').to_right_of(el)).click #點擊 id ='input' 右邊的元素
driver.find_element(locate_with(By.TAG_NAME,'input').to_left_of(el)).click #點擊 id ='input' 左邊的元素
driver.find_element(locate_with(By.TAG_NAME,'input').above(el)).click #點擊 id ='input' 上邊的元素
driver.find_element(locate_with(By.TAG_NAME,'input').above(el)).below #點擊 id ='input' 下邊的元素
driver.find_element(locate_with(By.TAG_NAME,'input').near(el)).click #點擊 id ='input' 附近的元素
(2)頁面加載策略:normal/eager/none
from selenium import webdriver chrome_options = webdriver.ChromeOptions() #normar: 頁面正常加載模式,整個頁面全部加載完,會打開頁面的靜態文件,包括:css樣式、js函數等全部加載完,才會繼續執行 chrome_options.page_load_strategy = 'normal' #eager: 會放棄加載頁面的“樣式”、“靜態資源”等,減少了一些不必要的加載,只會加載基本的html,其他的靜態資源不會加載了 chrome_options.page_load_strategy = 'eager' #none: 只把初始頁面加載完就會操作 chrome_options.page_load_strategy = 'none' driver = webdriver.Chrome(options=chrome_options) try: driver.get("http://www.baidu.com") finally: driver.quit()
(3)創建新的標簽頁和瀏覽器,創建新的標簽頁、瀏覽器之后,都會把句柄切換過去
#打開新的標簽頁 driver.switch_to.new_window('tab') #打開新的瀏覽器頁 driver.switch_to.new_window('window')
(4)Selenium 4.0版本重大改變:
——selenium grid 4.0完全翻新了原有的自動化分布式部署實現的框架技術體系。
• 3.0 版本:是基於MS形態實現的自動化測試框架部署
• 4.0 版本:原有基礎上新增event_bus、session queue等一系列內容,優化成了一個偏向於“分布式異步”形態處理的框架架構體系的自動化易用技術。
• 分布式技術體系:如幾萬條自動化測試用例,可拆分成幾千條為一組,每幾千條為一組的放到一台機器上執行,同步開啟多台機器來執行,變成了不同組數的測試用例,在不同的電腦進行,原本要很多個小時執行完的,幾個小時甚至更快就可以執行完了。
(三)鍵盤鼠標操作
1.模擬鍵盤輸入和按鍵
from selenium.webdriver.common.keys import Keys c.find_element(By.ID,'kw').send_keys('python')#輸出Python c.find_element(By.ID,'kw').send_keys(Keys.ENTER)#回車鍵 c.find_element(By.ID,'kw').click()#點擊
這里列舉出了一個最簡單的鍵盤輸入和鼠標點擊的例子,不過我們在Selenium中可以使用更為高逼格的操作,那么是什么了?當然是咱們的鼠標鍵盤監聽事件來觸發事件啦,而且它里面的方法的確也很多樣化,滿足小編日常的騷操作不在話下,如下所示:
click(on_element=None) #鼠標左鍵單擊 click_and_hold(on_element=None) #單擊鼠標左鍵,不松開 context_click(on_element=None) #單擊鼠標右鍵 double_click(on_element=None) #雙擊鼠標左鍵 drag_and_drop(source,target) #拖拽到某個元素然后松開 drag_and_drop_by_offset(source,xoffset,yoffset) #拖拽到某個坐標然后松開 key_down(value,element=None) #按下鍵盤上的某個鍵 key_up(value, element=None) #松開鍵盤上的某個鍵 move_by_offset(xoffset, yoffset) #鼠標從當前位置移動到某個坐標 move_to_element(to_element) #鼠標移動到某個元素 move_to_element_with_offset(to_element, xoffset, yoffset) #移動到距某個元素(左上角坐標)多少距離的位置 pause(seconds) #暫停所有輸入(指定持續時間以秒為單位) perform() #執行所有操作 reset_actions() #結束已經存在的操作並重置 release(on_element=None) #在某個元素位置松開鼠標左鍵 send_keys(*keys_to_send) #發送某個鍵或者輸入文本到當前焦點的元素 send_keys_to_element(element, *keys_to_send) #發送某個鍵到指定元素
以上就是咱們鼠標和鍵盤的全部操作了,小編將用一個例子帶大家零基礎入門。如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains c=webdriver.Chrome() c.get('https://www.baidu.com') a=ActionChains(c) kw1=c.find_element(By.ID,'kw') tj=c.find_element(By.ID,'su') tj.send_keys(Keys.CONTROL,'c') #復制 a.drag_and_drop(kw1,tj).perform()#從輸入框拖動到搜索按鈕 kw1.send_keys(Keys.CONTROL,'v')#粘貼 tj.send_keys(Keys.ENTER) time.sleep(3) c.close() c.quit()
這里我們通過對事件的監控,進行復制和粘貼,這里涉及到一個組合鍵的知識,大家注意。
(四)、選項操作
我們可以通過給當前操作的對象一些選項來增強交互能力,如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time from selenium.webdriver.chrome.options import Options o=Options() o.add_argument('--headless')#無界面瀏覽 c=webdriver.Chrome(executable_path=r'C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe',chrome_options=o) c.get('https://www.baidu.com') kw1=c.find_element(By.ID,'kw') print(c.title) time.sleep(3) c.close() c.quit()
這個時候就實現了咱們的無界面瀏覽了,也就是不用打開瀏覽器即可自動返回執行的結果。不過你可別以為選項就那么一兩個,那可是多到你懷疑人生的,例如:
o.add_argument('--window-size=600,600') #設置窗口大小 o.add_argument('--incognito') #無痕模式 o.add_argument('--disable-infobars') #去掉chrome正受到自動測試軟件的控制的提示 o.add_argument('user-agent="XXXX"') #添加請求頭 o.add_argument("--proxy-server=http://200.130.123.43:3456")#代理服務器訪問 o.add_experimental_option('excludeSwitches', ['enable-automation'])#開發者模式 o.add_experimental_option("prefs",{"profile.managed_default_content_settings.images": 2})#禁止加載圖片 o.add_experimental_option('prefs', {'profile.default_content_setting_values':{'notifications':2}}) #禁用瀏覽器彈窗 o.add_argument('blink-settings=imagesEnabled=false') #禁止加載圖片 o.add_argument('lang=zh_CN.UTF-8') #設置默認編碼為utf-8 o.add_extension(create_proxyauth_extension( proxy_host='host', proxy_port='port', proxy_username="username", proxy_password="password" ))# 設置有賬號密碼的代理 o.add_argument('--disable-gpu') # 這個屬性可以規避谷歌的部分bug o.add_argument('--disable-javascript') # 禁用javascript o.add_argument('--hide-scrollbars') # 隱藏滾動條 o.binary_location=r"C:\Users\Administrator\AppData\Local\Google\Chrome\Application" #指定瀏覽器位置 o.add_argument('--no-sandbox') #解決DevToolsActivePort文件不存在的報錯
其實選項的添加無非就是分為以下這幾種,如下:
o.set_headless() #設置啟動無界面化 o.binary_location(value) #設置chrome二進制文件位置 o.add_argument(arg) #添加啟動參數 o.add_extension(path) #添加指定路徑下的擴展應用 o.add_encoded_extension(base64) #添加經過Base64編碼的擴展應用 o.add_experimental_option(name,value) #添加實驗性質的選項 o.debugger_address(value) #設置調試器地址 o.to_capabilities() #獲取當前瀏覽器的所有信息
雖然選項很多,但是我們真正能用到的不多,一般就是無痕模式或者禁用JavaScript和圖片來快速獲取到相關信息。雖然我們上面使用的是Options方法,但是在實際應用中建議大家使用的ChromeOptions方法。
(五)、框架操作(Frame/IFrame)
我們還可以操作框架里的東西,比如IFrame,Frame等等,雖然都是框架,但是這兩者操作起來還是有很大差別的。下面我們就來看看吧,如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time c=webdriver.Chrome(executable_path=r'C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe') c.implicitly_wait(10) c.get('https://hao.360.com/?a1004') #ss=c.find_element(By.CLASS_NAME,'NEWS_FEED_VIDEO_1595850774217HPA70')#不容易找到標簽 c.switch_to.frame(0)#索引 c.switch_to.frame('NEWS_FEED_VIDEO_1595850774217HPA70-VideoIframe') #ID c.switch_to.frame('NEWS_FEED_VIDEO_1595850774217HPA70')#Class c.switch_to.frame(c.find_element_by_tag_name("iframe"))#標簽 time.sleep(3) c.close() c.quit()
這里小編是以360瀏覽器的主頁為例子,對它里面的IFrame進行訪問,最有效的方法一般就是我上面提到的四種了。這里我們有時候因為這個框架需要加載才可以出來,所以很多時候是無法獲取到的,因此我們只有使用滑動加載到出現這個標簽或者ID,Class為可以獲取到,這在剛才小編是說了的,大家可以往前看看,不過這個方法不推薦使用,為啥?因為開發者文檔上是這樣寫的。我們的Frame由於是IFrame里的子集,所以上面的方法便是可以層層遍歷的好方法,但是如果我們遍歷到最后了如何返回主框架了,可以這樣做,如下所示:
c.switch_to.default_content()
這樣就可以回到主框架繼續進行操作了。如果我們由里往外遍歷的話,那么可以這樣來做,如下:
c.switch_to.parent_frame()
#iframe,當你遇到方法用盡還是定位不到元素,檢查下是否有iframe driver.swith_to.frame(id/name/webElement) #定位方法 #iframe操作完成后,需要切換回默認窗體 driver.switch_to.default.content()
(六)、Alert
在彈窗處理中,我們會遇到三種情況,如下:
瀏覽器彈出框
新窗口彈出框
人為彈出框
那么我們該怎么分辨了?下面跟我一起看看吧。
1.瀏覽器彈出框
首先說說瀏覽器彈出框,想必大家對JavaScript中的Alert,Confirm,Prompt應該不是很陌生,就是彈出框,確認框,輸入框;基本方法我們來看下,如下:
from selenium.webdriver.common.alert import Alert c=webdriver.Chrome(executable_path=r'C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe') c.implicitly_wait(10) c.get('https://www.baidu.com') a1=Alert(c) a1.accept() #確定 a1.dismiss() #取消 a1.authenticate(username,password) #用戶身份驗證 a1.send_keys('') #輸入文本或按鍵 a1.text #獲取彈窗內容
這里我們應對每種情況它上面的方法的對應位置都是會有所變化的,所以我們需要根據具體情況來進行操作,而且還可以使用另一種方法,如下:
c=webdriver.Chrome(executable_path=r'C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe') c.implicitly_wait(10) c.get('https://www.baidu.com') a1=c.switch_to_alert() a1.accept() #確定 a1.dismiss() #取消 a1.authenticate(username,password) #用戶身份驗證 a1.send_keys('') #輸入文本或按鍵 a1.text #獲取彈窗內容
注:該類方法必須在有彈框的情況下才有作用,如沒有會報錯。
2.新窗口彈出框
上面就是瀏覽器彈出框的處理方法了,如果是新窗口彈出的話那么就不一樣了,我們需要通過句柄來定位,前面我們提到過這兩個方法。下面我們來看看它們的具體用法,如下:
from selenium import webdriver from selenium.webdriver.common.by import By import time c=webdriver.Chrome(executable_path=r'C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe') c.implicitly_wait(10) c.get('https://www.baidu.com') kw1=c.find_element(By.ID,'kw') tj=c.find_element(By.ID,'su') hwnd=c.window_handles #所有窗口句柄 for h in hwnd: if h !=c.current_window_handle: #如果句柄不是當前窗口句柄則切換 c.switch_to_window(h) #切換窗口 else: print('無需切換窗口') time.sleep(3) c.close() c.quit()
注:如果有多個窗口,當你關閉了當前窗口想切換到另一個窗口,你需要把沒關閉的窗口切換成當前活動窗口,因為Selenium是不會為你做這件事的。
3.人為彈出框
這類彈出框是我們自己開發的,一般都是使用Div包裹一些其它的元素標簽然后形成一個整體,當我們觸發某個事件的時候就會出現,否則消失。這種彈出框使用我們的眾多Find前綴的方法就能遍歷到,很方便,這里不一一細說。
(七)、判斷
在Selenium中我們在做自動化測試時常無法判斷一個元素是否真的顯示出來了,因此會各種報錯,接下來我們對這些操作進行判斷,如果顯示出了我們預期的值,那么就進行下一步操作,否則就關閉或者暫停幾秒然后再判斷,這里我要跟大家說Selenium中的一個模塊-----Expected_Conditions,簡稱為EC,如下所示:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC import time c=webdriver.Chrome() c.implicitly_wait(10) c.get('https://baidu.com') t=EC.title_is('百度一下,你就知道') print(t(c)) time.sleep(3) c.close() c.quit()
這里其實就是判斷當前頁面的標題是否是我們給定的文本,可以看出這里為True,說明是。它不光就一個方法哦,還有其它的,小編在這里大致說下,如下所示:
EC.title_contains('')(c)#判斷頁面標題是否包含給定的字符串 EC.presence_of_element_located('')(c) #判斷某個元素是否加載到dom樹里,該元素不一定可見 EC.url_contains('')(c) #判斷當前url是否包含給定的字符串 EC.url_matches('')(c) #匹配URL EC.url_to_be('')(c) #精確匹配 EC.url_changes('')(c) #不完全匹配 EC.visibility_of_element_located('')(c) #判斷某個元素是否可見,可見代表元素非隱藏元素 EC.visibility_of('')(c) #跟上面一樣,不過是直接傳定位到的element EC.presence_of_all_elements_located('')(c) #判斷是否至少有1個元素存在於dom樹中 EC.visibility_of_any_elements_located('')(c) #判斷是否至少一個元素可見,返回列表 EC.visibility_of_all_elements_located('')(c) #判斷是否所有元素可見,返回列表 EC.text_to_be_present_in_element('')(c) #判斷元素中的text是否包含了預期的字符串 EC.text_to_be_present_in_element_value('')(c)#判斷元素中value屬性是否包含預期的字符串 EC.frame_to_be_available_and_switch_to_it('')(c) # 判斷該frame是否可以switch進去 EC.invisibility_of_element_located('')(c) #判斷某個元素是否不存在於dom樹或不可見 EC.element_to_be_clickable('')(c) #判斷某個元素中是否可見並且可點擊 EC.staleness_of('')(c) #等某個元素從dom樹中移除 EC.element_to_be_selected('')(c) #判斷某個元素是否被選中了,一般用在下拉列表 EC.element_located_to_be_selected('')(c) #判斷元組中的元素是否被選中 EC.element_selection_state_to_be('')(c) #判斷某個元素的選中狀態是否符合預期 EC.element_located_selection_state_to_be('')(c) #跟上面一樣,只不過是傳入located EC.number_of_windows_to_be('')(c) #判斷窗口中的數字是否符合預期 EC.new_window_is_opened('')(c) #判斷新的窗口是否打開 EC.alert_is_present('')(c) #判斷頁面上是否存在alert
這就是它全部的方法了,簡直不要多簡單。
(八)、選擇
剛剛講過判斷,現在我們來說說選擇,選擇無非就是挑好的扔爛的,順着思路來不會錯,總體來講還是挺簡單的,如下:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.select import Select import time c=webdriver.Chrome() c.implicitly_wait(10) c.get('http://www.juliwz.cn/forum.php') s=Select(c.find_element_by_id('ls_fastloginfield'))#實例化 res=s.all_selected_options#全部選中子項 res1=s.options#全部子項 print(res) print(res1) time.sleep(3) c.close() c.quit()
發覺主流網站都沒有Select這個標簽,於是找了個很冷門的網站,就一個Select。Select里面的方法也是相當多的,如下:
s.first_selected_option #第一個選中的子項 s.select_by_index(index) #根據索引選擇 s.select_by_value(value) #根據值來選擇 s.select_by_visible_text(text) #根據選項可見文本 s.deselect_by_index(index) #根據索引來取消選擇 s.deselect_by_value(value) #根據值來取消選擇 s.deselect_by_visible_text(text) #根據可見文本來取消選擇 s.deselect_all() #取消所有選擇
(九)、顯示等待和隱式等待
想必大家應該聽過這個概念,顯示等待就是瀏覽器在我們設置的時間內不斷尋找,等到元素后才繼續執行,如果沒在規定時間內找到,也會拋異常;而隱式等待則是我們設置時間,然后程序去找元素,期間會不斷刷新頁面,到了時間仍然沒找到就拋異常。這里有個常用的模塊專門用來實現顯示等待和隱式等待的,它就是”wait“,我們來看看吧。如下:
from selenium.webdriver.support.ui import WebDriverWait from selenium import webdriver from selenium.webdriver.common.by import By import time c=webdriver.Chrome() c.get('https://www.baidu.com/') su=WebDriverWait(c,10).until(lambda x:x.find_element_by_id('su')) su.location_once_scrolled_into_view print(su.get_attribute('value')) time.sleep(3) c.close() c.quit()
隱式等待很簡單,就一行代碼,如下:
c.implicitly_wait(10)
它的等待時間適用於全局的環境,也就是任何地方找不到某個元素,它都將發揮作用,如果找得到,則不會產生作用。
(十)斷言
斷言assertion:
驗證應用程序的狀態是否同所期望的一致。
常見的斷言包括:驗證頁面內容,如標題是否為X或當前位置是否正確,或是驗證該復選框是否被勾選。
selenium 提供了三種模式的斷言:assert 、verify、waitfor
- Assert 失敗時,該測試將終止。
- Verify 失敗時,該測試將繼續執行,並將錯誤記入日顯示屏 。也就是說允許此單個 驗證通過。確保應用程序在正確的頁面上
- Waitfor 用於等待某些條件變為真。可用於 AJAX 應用程序的測試。
如果該條件為真,他們將立即成功執行。如果該條件不為真,則將失敗並暫停測試。直到超過當前所設定的超過時間。一般跟setTimeout時間一起使用
assertLocation(判斷當前是在正確的頁面)、
assertTitle(檢查當前頁面的 title 是否正確)、
assertValue(檢查 input 的值, checkbox 或 radio,有值為”on”無為”off”)、
assertSelected(檢查 select 的下拉菜單中選中是否正確)、
assertSelectedOptions(檢查下拉菜單中的選項的是否正確)、
assertText(檢查指定元素的文本)、
assertTextPresent(檢查在當前給用戶顯示的頁面上是否有出現指定的文本)、
assertTextNotPresent(檢查在當前給用戶顯示的頁面上是否沒有出現指定的文本)、
assertAttribute(檢查當前指定元素的屬性的值)、
assertTable(檢查 table 里的某個 cell 中的值)、
assertEditable(檢查指定的 input 是否可以編輯)、assertNotEditable(檢查指定的 input 是否不可以編輯)、
assertAlert(檢查是否有產生帶指定 message 的 alert 對話框)、
verifyTitle (檢查預期的頁面標題)
verifyTextPresent (驗證預期的文本是否在頁面上的某個位置)
verifyElementPresent(驗證預期的UI元素,它的HTML標簽的定義,是否在當前網頁上)
verifyText(核實預期的文本和相應的HTML標簽是否都存在於頁面上)
verifyTable(驗證表的預期內容)
waitForPageToLoad(暫停執行,直到預期的新的頁面加載)
waitForElementPresent (等待檢驗某元素的存在。為真時,則執行。)驗證和斷言的區別:驗證失敗后不影響腳本的繼續執行,斷言失敗后將停止腳本的執行。
異常類型
AssertionError:assert語句失敗AttributeError:試圖訪問一個對象沒有的屬性
IOError:輸入輸出異常,基本是無法打開文件
ImportError:無法引入模塊或者包,基本是路徑問題
IndentationError:語法錯誤,代碼沒有正確的對齊
IndexError:下標索引超出序列邊界
KeyError:試圖訪問字典里不存在的鍵
KeyboadrInterrupt:Ctrl+c被按下
NameError:使用一個還未賦值對象的變量
SyntaxError:python代碼邏輯語法錯誤,不能執行
TypeError:傳入的對象類型與要求不符
UnboundLocalError:試圖訪問一個還未設置的全局變量,基本上是由於另有一個同名的全局變量,導致你以為在訪問
ValueError:傳入一個不被期望的值,即使類型正確
(十一)、總結
Selenium的內容其實還是挺豐富的,它還有手機端的自動化測試框架,不過小編先把WEB端講完就可以了,畢竟也寫了這么多了,日后有時間再慢慢了解。大家如果是對觸摸活動事件感興趣的也可以看看“touch_actions"這個模塊。這個模塊里集成的都是關於觸摸屏的操作,里面也有很多的方法,小編之所以能把Selenium一天學完,還是Selenium模塊中的文檔比較給力,主要是介紹的比較好,讓人能輕松聯想到方法的使用,感激開源作者的無私奉獻。