1. 程式人生 > >Web自動化 - 選擇操作元素 1

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

click 列表 文章 ebe ssa href 數字 錯誤 nor

文章轉自 白月黑羽教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

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