文章目錄
前言
在我的上一篇Selenium的文章中已經詳細介紹了關於安裝方面、使用方面的各種經常使用的方法,本篇內容對上篇文章做一些擴展,比如詳細的CSS+XPath定位元素的方法,遇見窗口切換等的處理,讓你在Selenium的使用上更進一步,最後,如果想了解更仔細的基礎知識請點擊傳送門:《Web自動化-Selenium》
CSS表達式
1.1 屬性選擇
注意一下,包括上篇文章在內,關於文章中寫的那麼多classname,
需要注意的是,class是一個屬性,而不是指的classname是一個屬性,
classname指的僅僅是class對應的那個值!!!
看過上一篇的同志們都知道,在元素定位的方法中有個id定位、還有classname定位,在CSS中,它們也被包含在內了,並且非常簡單。舉個例子,對id定位的CSS表達式:
#對id='XXX'的元素進行定位,下面是相應的CSS表達式方法
driver.find_element_by_css_selector('#XXX')
注意一下,這個driver還是上篇文章中的那個webdriver
對象,然後,哈哈哈看到對應表達式了吧,如果不知道CSS的小夥伴是不是很懵,其實你沒猜錯,對id定位只需要在id對應的值前加個#
井號鍵即可,實際上,包括對classname進行定位:
#對classname='XXX'的元素進行定位,下面是相應的CSS表達式
driver.find_element_by_css_seletor('.XXX')
是的,對classname定位只需要在對應值之前加個.
點即可,那大家會不會想定位什麼就在前加個對應標記就行了,不是這樣的,只有id和classname因爲出現頻率高且比較廣泛,所以CSS中專門給出了對應的簡單標記,至於其它的,包括嵌套標記等方法,後文細細講來。
在這裏提一點,對於id和classname,它們其實都是HTML中標籤裏面的屬性,當然屬性還有很多其它的屬性,比如會有style、src、href等等等等,不過有一點是不變的,它們都是屬性,那我們會不會有時候找的不是標籤內的東西,而是這些屬性的對應值,答案是會!那麼在Selenium中也提供了一種方法可以直接得到該元素對應屬性的值:
get_attribute(attribute name)
沒錯,就是這麼簡單粗暴,這是一個方法,使用對象是一個webdriver element
對象,也就是driver定位後的元素對象,舉個例子:
#先得到id='XXX'的元素對象
webdriver_element = driver.find_element_by_id('XXX')
#打印此對象中'src'屬性的值
print(webdriver_element.get_attribute('src'))
是的,就是這麼操作。
前邊說了id和classname的相應在CSS中分別用#和.
來標記,對於標籤名,在CSS中是不標記的,直接沒有標記寫出來就代表找的是這個的標籤:
#用CSS選擇器找到span標籤的第一個元素
driver.find_element_by_css_selector('span')
也就是直接把標籤名寫進去就代表找的此標籤。
1.2 子元素和後代元素
- 選擇子元素和後代元素的方法。
我們都知道,HTML是一個標籤樹一樣的形式,節點很多,子節點更多,很多節點被嵌套在一些節點中,有時候某個元素的很多東西都不是唯一的,不能直接定位,那麼這個時候就需要使用一整串表達式來定位了。
- 在CSS表達式中,只需要在兩個元素之間加上一個
空格
,則代表空格後的元素爲前一個元素的後代元素,而加上一個>
,則代表大於號後的元素爲前一個元素的直接子元素。舉個例子:
#選擇id='XXX'的元素的所有名爲'span'的所有後代元素
driver.find_elements_by_css_selector('#XXX span')
#s選擇class='XXX'的元素的所有名字'src'的直接子元素
driver.find_elements_by_css_selector('.XXX>src')
當然,後代元素就不說了,對於選擇子元素也支持多層級的原則:
#選擇id='XXX'的元素的子元素名爲'span'的子元素'src'
driver.find_elements_by_css_selector('#XXX>span>src')
1.3 根據屬性來選
- 根據屬性來選
在有些時候,我們會發現,有一些子標籤,它們的標籤名一樣,卻有些屬性不一樣,並且包含的東西也不一樣,這個時候我們需要獲取一些擁有目標屬性的標籤,如下:
#獲取div標籤的後代標籤中標籤名爲a屬性爲href的元素
driver.find_elements_by_css_selector('div a[href]')
#如果想要獲取某個固定的元素,只需要下面這樣
driver.find_element_by_css_selector('div a[href='XXX']')
#也就是說把s給去掉,其實不去掉也沒事因爲本來也就一個,指定href屬性的值即可。
1.4 按照次序選擇子節點
- 按照次序選擇子節點
我們可以單獨指定選擇父元素的第n個子節點,使用的方法是:
:nth-child()
具體使用方法如下:
#選擇id='XXX'的元素的第二個子元素
driver.find_elements_by_css_selector('#XXX:nth-child(2)')
#選擇所有標籤名爲src的子元素'中'的元素的第二個子元素
driver.find_elements_by_css_selector('src :nth-child(2)')
#選擇所有標籤元素的第二個子元素
driver.find_elements_by_css_selector(':nth-child(2)')
也就是說,在冒號前,是已經定位好的元素,然後選擇此元素子元素中的第二個。括號內的數字指第幾個。
還有一種選擇方法,是選擇父元素的第幾個某種類型的子節點。上文中,可以理解爲先指定元素,再從該元素的子元素中找第幾個,那麼下面這個意思是,先指定元素,然後在該元素的子元素中找第幾個某類型的元素。方法:
:nth-of-type()
示例:
#選擇id='XXX'的元素的第三個src類型的子元素,src爲標籤名
driver.find_elements_by_css_selector('#XXX>src:nth-of-type(3)')
1.5 奇數節點和偶數節點
- 奇數節點和偶數節點
這個代表在確定了父元素之後,選擇其奇數子元素還是偶數子元素。
:nth-child(even)
選擇奇數的話用此參數
:nth-child(odd)
選擇偶數的話用此參數
和1.4相比之下,只是參數有限制了,用法是差不多的。
1.6 兄弟節點選擇
- 兄弟節點選擇
這個方法呢需要首先確定我們的目標元素,然後再確定兄弟元素,比如:
#選擇span元素後面緊跟的兄弟節點src
driver.find_elements_by_css_selector('span+src')
#選擇span元素後面跟着的所有兄弟節點src
driver.find_elements_by_css_selector('span~src')
frame窗口切換
在有些時候,我們需要訪問的元素是在一個iframe標籤當中,
如此圖左上角的iframe
,我們發現此標籤後面也有head和body,說明這是另一份HTML文檔,其實在HTML語法中,frame或者iframe元素的全部會包含一個被嵌入的另一份html文檔,簡單理解就是我們要定位的目標元素在程序現在操作的html文檔之外,如果直接對其操作是不行的,你根本找不到它,此時必須要將操作範圍換到目標元素所在的html文檔,切換的方法很簡單:
driver.switch_to.frame(frame_reference)
其中,frame_reference可以是frame元素的屬性或者ID。如圖片中的iframe爲例,這樣切換即可:
driver.switch_to.frame(0)
瀏覽器窗口切換
這個大家就比較熟悉了,在很多時候,我們在網頁的某個地方點擊之後會出現新的網頁,也就是點了超鏈接,此時瀏覽器裏面會有兩個窗口,這個時候也是需要切換的,我們可以切換至任意一個我們想要切換到的窗口。那麼怎麼切換呢,用這個方法:
driver.switch_to.window(handle)
handle是一個句柄,是我們要切換到的窗口的句柄,在Webdirver中有一個屬性window_handles
,這是一個列表對象,當你調用它的時候,會返回含有所有當前窗口句柄的一個列表,那麼怎麼從列表中找到我們需要的窗口呢?有如下辦法:
for handle in driver.window_handles:
#從該列表對象中遍歷
dirver.switch_to.window(handle)
#上面是切換窗口,然後來判斷
if 'XXX' in driver.title:
break
#就是切換到的窗口裏面,如果我們需要的窗口的標題在現在的窗口裏面,就退出遍歷,也就是當前切換到的窗口就是目標窗口了。
凍結界面
在瀏覽器開發者工具欄的console裏面輸入:
setTimeout(function(){debugger},10000)
這句話是什麼意思呢?這其實是一段JavaScript命令,他將在10000毫秒也就是10秒後凍結瀏覽器界面,也就是所有元素靜止,此時,你就可以爲所欲爲了,可能你想不到有什麼用,不過,你可以先實驗一下,改裏面的10000成你想要的時間,看看會出現什麼,放心吧,你總會用得到的。
總結
值得一提的是,當我們定位元素的時候使用的find_element_by...
的時候,也就是element沒有加s的時候,如果獲取不到路徑下的元素,程序會報錯,而假如使用的elements的時候,如果獲取不到目標元素,不會報錯,會返回一個空列表。
另外,使用driver.title
會返回當前窗口的標題,使用i.text
會返回元素的文本,注意i是一個webdriver element對象。
最後這兩篇Selenium的文章到此結束了,本人知識不足難免文中會有錯誤,如有發現懇請提出,謝謝。如果你已經完全掌握了兩篇文章的內容,那麼你已經可以做很多一些事情了。其實還有一種定位元素的方法XPath
,不過相信很多瞭解前端的人已經非常熟悉了,本文沒有給出方法,如果感覺文章對您有用,還請點個贊支持一下謝謝~