Web自動化-Selenium擴展+定位方法

前言

在我的上一篇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,不過相信很多瞭解前端的人已經非常熟悉了,本文沒有給出方法,如果感覺文章對您有用,還請點個贊支持一下謝謝~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章