Web自動化 - 選擇操作元素 1


文章轉自 白月黑羽教Python

 

所有的 UI (用戶界面)操作 的自動化,都需要選擇界面元素。

選擇界面元素就是:先讓程序能找到你要操作的界面元素。

先找到元素,才能操作元素。

 

 

選擇元素的方法

程序 怎么才能找到 要操作的 web 界面元素?

方法就是要根據這個 web 元素的 特征 去選擇。

元素的特征怎么查看?

可以使用瀏覽器的開發者工具欄幫我們查看、選擇web 元素。

請大家安裝最新版的Chrome瀏覽器(可以百度搜索下載)。

用chrome瀏覽器訪問百度,按F12后,點擊下圖箭頭處的Elements標簽,即可查看頁面對應的HTML 元素

 

 

然后,再點擊 最左邊的圖標,如下所示

 

 

之后,鼠標在界面上點擊哪個元素,就可以查看該元素對應的html標簽內容了。

比如,前面的圖的高亮處,就是百度搜索輸入框對應的input元素。

 

 

根據 元素的id 屬性選擇元素

大家仔細看上面的 input元素 內容,會發現它有一個屬性叫id。

 

 

我們可以把 id 想象成元素的編號, 是用來在html中標記該元素的。 根據規范, 如果元素有id ,這個id 必須是當前html中唯一的。

所以如果元素有id, 根據id選擇元素是最簡單高效的方式。

下面的代碼,就是用selenium 訪問百度,並且在輸入框中搜索 黑羽魔巫宗

大家可以運行一下看看。

from selenium import webdriver # 創建 WebDriver 實例對象,指明使用chrome瀏覽器驅動 driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') # WebDriver 實例對象的get方法 可以讓瀏覽器打開指定網址 driver.get('https://www.baidu.com') # 根據id選擇元素,返回的就是該元素對應的WebElement對象 element = driver.find_element_by_id('kw') # 通過該 WebElement對象,就可以對頁面元素進行操作了 # 比如輸入字符串到 這個 輸入框里 element.send_keys('黑羽魔巫宗\n') 

其中

driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') 

返回的是 WebDriver 實例對象,我們可以通過這個實例對象來操控瀏覽器,比如 打開網址、選擇界面元素等。

下面的代碼

driver.find_element_by_id('kw')

就是使用 WebDriver 實例對象 的方法find_element_by_id, 這個方法就是 根據輸入框元素的 id 值 ‘kw’ 來選擇到元素。

選擇到元素之后, find_element_by_id 方法會返回一個 WebElement, 我們通過這個對象就可以操控對應的界面元素。

比如 send_keys 方法就是在對應的元素中輸入字符串,

而 click 方法就可以點擊該元素。

 

根據 class屬性、tag名 選擇元素

除了根據元素的id ,我們還可以根據元素的class 屬性選擇元素。

大家請訪問這個網址

這個網址對應的html內容 有如下的部分

 

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>白月黑羽測試網頁1</title> <style> .animal {color: red;} </style> </head> <body> <div class="plant"><span>土豆</span></div> <div class="plant"><span>洋蔥</span></div> <div class="plant"><span>白菜</span></div> <div class="animal"><span>獅子</span></div> <div class="animal"><span>老虎</span></div> <div class="animal"><span>山羊</span></div> </body> </html> 

所有的植物元素都有個class屬性 值為 plant。

所有的動物元素都有個class屬性 值為 animal。

如果我們要選擇所有的 動物, 就可以使用方法 find_elements_by_class_name

driver.find_elements_by_class_name('animal')

注意

find_elements_by_class_name 方法返回的是找到的符合條件的所有元素 (這里有3個元素), 放在一個列表中返回。

而如果我們使用 find_element_by_class_name (注意少了一個s) 方法, 就只會返回第一個元素。

大家可以運行如下代碼看看。

 

from selenium import webdriver # 創建 WebDriver 實例對象,指明使用chrome瀏覽器驅動 driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') # WebDriver 實例對象的get方法 可以讓瀏覽器打開指定網址 driver.get('http://www.python3.vip/doc/tutorial/python/code/sample1.html') # 根據 class name 選擇元素,返回的是 一個列表 # 里面 都是class 屬性值為 animal的元素對應的 WebElement對象 elements = driver.find_elements_by_class_name('animal') # 取出列表中的每個 WebElement對象,打印出其text屬性的值 # text屬性就是該 WebElement對象對應的元素在網頁中的文本內容 for element in elements: print(element.text) 

 

如果我們把

elements = driver.find_elements_by_class_name('animal') 

去掉一個s ,改為

element = driver.find_element_by_class_name('animal') print(element.text) 

那么返回的就是第一個class 屬性為 animal的元素, 也就是這個元素

<div class="animal"><span>獅子</span></div>



類似的,我們可以通過方法 find_elements_by_tag_name ,選擇所有的tag名為 div的元素,如下所示

from selenium import webdriver # 創建 WebDriver 實例對象,指明使用chrome瀏覽器驅動 driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') # WebDriver 實例對象的get方法 可以讓瀏覽器打開指定網址 driver.get('http://www.python3.vip/doc/tutorial/python/code/sample1.html') # 根據 tag name 選擇元素,返回的是 一個列表 # 里面 都是 tag 名為 div 的元素對應的 WebElement對象 elements = driver.find_elements_by_tag_name('div') # 取出列表中的每個 WebElement對象,打印出其text屬性的值 # text屬性就是該 WebElement對象對應的元素在網頁中的文本內容 for element in elements: print(element.text) 

 

等待界面元素出現

在我們進行網頁操作的時候, 有的元素內容不是可以立即出現的, 可能會等待一段時間。

比如 百度搜索一個詞語, 我們點擊搜索后, 瀏覽器需要把這個搜索請求發送給百度服務器, 百度服務器進行處理后,把搜索結果返回給我們。

只是通常百度服務器的處理比較快,我們感覺好像是立即出現了搜索結果。

百度搜索的每個結果 對應的界面元素 其ID 分別是數字 1, 2 ,3, 4 。。。

如下

 

那么我們可以試試用如下代碼 來將 第一個搜索結果里面的文本內容 打印出來

from selenium import webdriver driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') driver.get('https://www.baidu.com') element = driver.find_element_by_id('kw') element.send_keys('黑羽魔巫宗\n') # id 為 1 的元素 就是第一個搜索結果 element = driver.find_element_by_id('1') # 打印出 第一個搜索結果的文本字符串 print (element.text) 

 

如果大家去運行一下,就會發現有如下異常拋出

selenium.common.exceptions.NoSuchElementException: 
Message: no such element: 
Unable to locate element: {"method":"id","selector":"1"}

NoSuchElementException 的意思就是在當前的網頁上 找不到該元素, 就是找不到 id 為 1 的元素。

為什么呢?

因為我們的代碼執行的速度比 百度服務器響應的速度 快。

百度還沒有來得及 返回搜索結果,我們就執行了如下代碼

element = driver.find_element_by_id('1')

在那短暫的瞬間, 網頁上是沒有用 id為1的元素的 (因為還沒有搜索結果呢)。自然就會報告錯誤 id為1 的元素不存在了。

那么怎么解決這個問題呢?

很多聰明的讀者可以想到, 點擊搜索后, 用sleep 來 等待幾秒鍾, 等百度服務器返回結果后,再去選擇 id 為1 的元素, 就像下面這樣

 

from selenium import webdriver driver = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe') driver.get('https://www.baidu.com') element = driver.find_element_by_id('kw') element.send_keys('黑羽魔巫宗\n') # 等待 2 秒 from time import sleep sleep(2) # 2 秒 過后,再去搜索 element = driver.find_element_by_id('1') # 打印出 第一個搜索結果的文本字符串 print (element.text) 

 

大家可以運行一下,基本是可以的,不會再報錯了。

但是這樣的方法 有個很大的問題,就是設置等待多長時間合適呢?

這次百度網站反應可能比較快,我們等了一秒鍾就可以了。

但是誰知道下次他的反應是不是還這么快呢?百度也曾經出現過服務器癱瘓的事情。

可能有的讀者說,我干脆sleep比較長的時間, 等待 20 秒, 總歸可以了吧?

這樣也有很大問題,假如一個自動化程序里面需要10次等待, 就要花費 200秒。 而可能大部分時間, 服務器反映都是很快的,根本不需要等20秒, 這樣就造成了大量的時間浪費了。

 

Selenium提供了一個更合理的解決方案,是這樣的:

當發現元素沒有找到的時候, 並不 立即拋出 找不到元素的異常。

而是周期性(每隔半秒鍾)重新尋找該元素,直到該元素找到,

或者超出指定最大等待時長,這時才 拋出異常(如果是 find_elements 則是返回空列表)。

Selenium 的 Webdriver 對象 有個方法叫 implicitly_wait

該方法接受一個參數 就是指定的 最大等待時長。

如果我們 加入如下代碼

driver.implicitly_wait(10) 

那么后續所有的 find_element 或者 find_elements 之類的方法調用 都會采用上面的策略。

就是找不到元素 每隔 半秒鍾 再去界面上查看一次, 直到找到該元素, 或者 過了10秒鍾 最大時長。

這樣,我們的百度搜索的例子的最終代碼如下

 

from selenium import webdriver driver = webdriver.Chrome() # 設置最大等待時長為 10秒 driver.implicitly_wait(10) driver.get('https://www.baidu.com') element = driver.find_element_by_id('kw') element.send_keys('黑羽魔巫宗\n') element = driver.find_element_by_id('1') print (element.text) 

 

大家再運行一下,可以發現不會有錯誤了。

 

 

訪問原文網站,看 下一篇 操作web界面 2

文章轉自 白月黑羽教Python


免責聲明!

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



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