Selenium Web自動化的一些注意點

瀏覽器copy selector

我們選擇元素有一個方法可以快速生成,右鍵點擊元素點擊檢查定位到元素后糠亩,右鍵點擊元素有個Copy秆撮,選擇Copy selector

image.png
也會把選擇的表達式選擇下來Copy selectorCss的寫法收壕,我們看到也有XPath大家也可以試一下歼捐,這種方法其實是非常有限的,這種方式是以一個有id的元素為瞄點往下找你画,如果有id的元素不是本身而是上層節(jié)點他就要依賴上層節(jié)點和他的相對關(guān)系來找抵碟,如果上層節(jié)點跟他隔得很遠,他也會一層層的找打他有id的上層節(jié)點坏匪,路徑會很長如果他中間的任何一個環(huán)節(jié)發(fā)生變化就容易出問題健壯性不好拟逮,他不會根據(jù)別的方法比如class,這種方法我們了解一下就好很雞肋。


異常捕獲适滓,確保chrom進程退出

我們做練習(xí)的時候不可能一次就把作業(yè)做出來罚屋,總歸要做一些調(diào)試出錯調(diào)試出錯尖滚,肯定遇到過出錯瀏覽器就沒法關(guān)閉的狀況造锅,有的同學(xué)會想不關(guān)就不關(guān)唄我們手動關(guān)上就好了糙箍,調(diào)試的時候是可以的咕晋,假如我們做系統(tǒng)自動化的時候有很多的用例上百個web自動化用例在執(zhí)行质蕉,如果遇到報錯瀏覽器沒有關(guān)閉绷蹲,第二天我們?nèi)タ吹脑挋C器就像卡死了一樣测秸,因為很多用例遇到報錯比如找不到元素的錯誤導(dǎo)致瀏覽器開了二三十個在那甚至更多铃拇,我們可以把自動化邏輯放在異常捕獲try里面`钞瀑,看下面例子

from selenium import webdriver
import time

driver = webdriver.Chrome('E:\ChromDriver\chromdriver2.43\chromedriver.exe')
driver.implicitly_wait(10)

driver.get('https://www.baidu.com/')
print(driver.title)

driver.find_element_by_id('kk').send_keys('杭州')

driver.quit()

百度的輸入框idkw我這里改為kk這時候,由于不能執(zhí)行到driver.quit,瀏覽器就不能自動關(guān)閉慷荔,解決方法

import traceback

from selenium import webdriver
import time

driver = webdriver.Chrome('E:\ChromDriver\chromdriver2.43\chromedriver.exe')
driver.implicitly_wait(10)
try:
    driver.get('https://www.baidu.com/')
    print(driver.title)

    driver.find_element_by_id('kk').send_keys('杭州')

except:
    print(traceback.format_exc())
finally:
    driver.quit()0

寫在try里面雕什,finally 后面需要driver.quit()


我們操作界面的時候不需要點擊他,把鼠標移動到上面就會導(dǎo)致頁面的變化显晶,比如我們打開華為官網(wǎng)https://www.vmall.com/

image.png
鼠標放在上面元素就會彈出出來贷岸,大家可能發(fā)現(xiàn)我們這里把鼠標放在上面直接右鍵查看元素也是可以定位到元素的,其實他本身也在HTML當中即使光標不放在上面磷雇,我們能不能不模擬光標放在上面偿警,可以找到直接去選擇元素(筆記本電腦之類的)嗎?像這些界面元素如果沒有把光標停在上面讓界面顯示出來唯笙,通常是不能操作他的會出錯螟蒸,因為當前這個元素如果處于沒有顯示出來的狀態(tài)你就想試著去操作他,其實這個元素有個屬性
image.png
class等于none的這種屬性他的displaynone
image.png
display元素是none的意思是他當前在界面放在HTML里面但是他不顯示出來不顯示在界面上睁本,Selenium是高度模擬用戶點擊操作的尿庐,因為他沒有顯示出來這個時候你點擊他會出錯的,我們可以把它凍結(jié)
image.png
這個時候就不會消失了呢堰,這個時候可以去查看內(nèi)容了


Selenium怎么模擬這個移動鼠標到某個元素的動作呢抄瑟?通過ActionChains 類,ActionChains類 里面提供了 一些特殊的動作, 比如移動鼠標到某個元素枉疼,就是其中之一,ActionChains本身有個ActionChains模塊文件本身實現(xiàn)了一個ActionChains類皮假,我們查看這個類的放方法

image.png
可以看到他的方法有
image.png
click點擊,click_and_hold點擊按住不動不要松骂维,context_click右鍵點擊惹资,double_click雙擊等這里不一一介紹大家自己去研究,我們這里用到的就是move_to_element懸停就使用他

from selenium import webdriver
import time

executable_path = r"d:\tools\webdrivers\chromedriver.exe"
driver = webdriver.Chrome(executable_path)

driver.get('https://www.vmall.com/')

# ---------------------------------------
# 導(dǎo)入ActionChains這個類
from selenium.webdriver.common.action_chains import ActionChains
# 創(chuàng)建實例對象
ac = ActionChains(driver)
#移動不點擊  .perform()執(zhí)行
ac.move_to_element(driver.find_element_by_id('zxnav_1')).perform()

ele= driver.find_element_by_css_selector(
    '#zxnav_1 > div.category-panels.relative > ul > li:nth-child(1) > a')

ele.click()
# ---------------------------------------
input('...')
driver.quit()


下面我們看一段HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>定位網(wǎng)頁元素</title>
</head>

<body style="width:1600px">

<div>
<span>輸入框</span> <input type="text" style="margin-top:2200px">
</div>


</body>
</html>

可以看到這段HTML很簡單航闺,body里面有個div褪测,div里面有個span里面有個input輸入框,里面有個很奇怪的屬性margin-top
他的意思是

image.png
這個元素和他的上面元素的間隔有多高2200px像素潦刃,這個間隔是很高的侮措,大家復(fù)制這段html看一下,比如做自動化的時候web頁面很長乖杠,他的內(nèi)容在很下面分扎,我們需不要把這個頁面滾動到下方讓他出來再去操作這個元素呢?大家注意華為官網(wǎng)的看不到是因為元素所在的區(qū)域已經(jīng)有了胧洒,只是你沒有操作他畏吓,它屬于不可見屬性的看不到墨状,但是我們現(xiàn)在講的這種其實可見狀態(tài)只是你滾動條沒有拉下來,通長這種情況不需要你滾動下來的菲饼,它本身在視圖上是有的只是沒呈現(xiàn)滾動區(qū)域里面

from selenium import webdriver
executable_path = r"d:\tools\webdrivers\chromedriver.exe"

driver = webdriver.Chrome(executable_path)
driver.implicitly_wait(10)


driver.get('file:///D:/gsync/workspace/sq/selenium/samples_selenium/wd/lesson07/winsize.html')

searchbox = driver.find_element_by_tag_name('input')

searchbox.send_keys('你好啊\n')


input('...')
driver.quit()

大家自己拿代碼試一下肾砂。


如果確實需要改變窗口大小,

  • 有時確實讓元素可見巴粪,才能點擊(有時候確實是這樣通今,不知道什么原因)
  • 或者覺得這樣看起來更清楚一些
size = driver.get_window_size()#返回是字典格式
driver.set_window_size(1100,size['height'])

下面是對網(wǎng)易云音樂寫的代碼,可拿去試一下

from selenium import webdriver

driver = webdriver.Chrome(r"E:\ChromDriver\chromedriver.exe")
driver.implicitly_wait(10)

driver.get('http://music.163.com')

# 結(jié)果像這樣 {'width': 855, 'height': 922}
size = driver.get_window_size()
print(size)
# 只改變寬度
driver.set_window_size(1300, size['height'])

#最大化
driver.maximize_window()

searchbox = driver.find_element_by_css_selector('#srch')

searchbox.send_keys('張學(xué)友\n')

driver.quit()

假如還一種情況要找的元素他在特別的右邊或特別的下邊窗口最大化都顯現(xiàn)不出來肛根,那就需要滾動元素的方案,selenium沒有直接的方法漏策,可以使用最后一招派哲, 直接讓瀏覽器執(zhí)行javascript腳本瀏覽器執(zhí)行的語言是js, 如果我們能直接傳入js代碼讓瀏覽器執(zhí)行掺喻,就得到了最大的靈活性去控制瀏覽器芭届。可以算是終極武器感耙。 比如滾動屏幕褂乍,就可以使用js語言

driver.execute_script('window.scrollBy(250,0)')

第一個參數(shù)250是橫向滾動就是x坐標滾動,往右滾250個像素即硼,如果有們想往左滾

driver.execute_script('window.scrollBy(-250,0)')就滾回去了

第二個參數(shù)是下滾

driver.execute_script('window.scrollBy(0,300)')

上滾加個負號就好了


界面重新繪制

接下來說一下界面里面元素出現(xiàn)動態(tài)改變的這個情況逃片,我們看一個例子,下面截圖是一個教管系統(tǒng)!

image.png

假如我們要實現(xiàn)一個自動化只酥,要把所有的課程信息刪除掉褥实,如果按照之前的方法我們點擊“刪除”然后點擊“確定”,把所有的刪除按鈕都找到裂允,看似很簡單我們按照這個思路去寫代碼损离,根據(jù)我們的思路要把所有的刪除按鈕找出來
image.png
大家看一下根據(jù)什么屬性去找呢,沒有id根據(jù)class绝编,但是這個class有好多屬性僻澎,btn-green看名字就可以看出來按鈕是綠色的btn-outlined是外面有一個方框,根據(jù)這個class是不好去找的因為編輯也有同樣的屬性十饥,這里根據(jù)ng-click這個屬性去找比較好窟勃,他這個屬性對應(yīng)刪除的動作,點了這個刪除之后會執(zhí)行一段JavaScript代碼或函數(shù)绷跑,刪除是跟這個緊密相關(guān)的拳恋,點擊刪除之后這里還有個確定,
image.png
這個元素在這里很好找砸捏,我們就不講解了

from selenium import  webdriver
import time


driver = webdriver.Chrome()
driver.implicitly_wait(5)

driver.get('http://localhost/mgr/login/login.html')
#登錄
driver.find_element_by_id('username').send_keys('auto')
driver.find_element_by_id('password').send_keys('sdfsdfsdf')
driver.find_element_by_tag_name('button').click()

time.sleep(1)

#根據(jù)ng-click去找刪除按鈕谬运,這里是個list
delButtons = driver.find_elements_by_css_selector(
'*[ng-click^=delOne]')


for button in delButtons:
    button.click()
    time.sleep(1)
    driver.find_element_by_css_selector(
        '.modal-footer  .btn-primary').click()

運行會發(fā)現(xiàn)刪除第一個之后就不動了隙赁,報錯了報錯信息如下

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=74.0.3729.157)
  (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Windows NT 10.0.17134 x86_64)

我們分析一下報錯WebDriver報的Exception,unknown error不知道什么類型,我們看下error的報錯Element <button >對應(yīng)的是這個webelement對象梆暖,看后面的就是我們刪除按鈕web的寫法<button type="button" class="btn btn-green btn-outlined btn-xs ng-scope" ng-click="delOne(one)"伞访,報is not clickable at point是不可點擊的,Other element would receive the click另外一個元素接收到點擊的動作轰驳,這個元素為什么不可點擊呢厚掷。大家想一下剛才的運行結(jié)果,確實已經(jīng)刪除了一個元素了到第二個刪除操作的時候就報錯了级解,大家以后做自動化的時候會經(jīng)常遇到這種事情冒黑,因為現(xiàn)在web前端的開發(fā)很多開發(fā)人員使用的方法都會動態(tài)的更新的前端界面,之前最早的web界面的呈現(xiàn)勤哗,比如導(dǎo)致web界面出現(xiàn)了變化抡爹,都是發(fā)起http請求,后端返回一個完整的http頁面給你芒划,以前都是這樣冬竟,隨著前端開發(fā)衍進覺得這種效率太低,因為有的時候并不需要后端重新產(chǎn)生一個完整的界面民逼,比如這個刪除操作泵殴,刪除一個課程只需要告訴后端我把這個課程刪了,服務(wù)器處理一下在數(shù)據(jù)庫把這個課程清除掉拼苍,沒有必要讓服務(wù)端再返回一個完整html的界面給前端笑诅,對于我們來說只需要在代碼里動態(tài)的把課程清除掉就可以,所以這個時候前端的開發(fā)可以動態(tài)改變前端的內(nèi)容映屋,可以通過JavaScript代碼更新界面苟鸯,或者一些框架,這樣就產(chǎn)生了一個問題就像之前這樣看似點擊刪除按鈕棚点,點擊確定好像界面只少了一個課程早处,但實際上有的框架就不是簡單的把這一個元素刪了,他有可能把整個表格獲取一次重新產(chǎn)生了瘫析,重新產(chǎn)生意思是原來是4條記錄現(xiàn)在重新產(chǎn)生了眼睛看起來就少了一條ji記錄砌梆,實際上頁面上所有的元素都重新創(chuàng)建了一遍,這就帶來我們刪除一門課程之后導(dǎo)致現(xiàn)在界面剩下來3個刪除按鈕已經(jīng)不是剛才4個中的3個了贬循,就是這個原因?qū)е碌南贪覀兛梢赃@樣既然你之后界面刷新了那我們每次刪除之后就重新獲取當前界面的元素就可以了

from selenium import  webdriver
import time


driver = webdriver.Chrome()
driver.implicitly_wait(5)

driver.get('http://localhost/mgr/login/login.html')

driver.find_element_by_id('username').send_keys('auto')
driver.find_element_by_id('password').send_keys('sdfsdfsdf')

driver.find_element_by_tag_name('button').click()


time.sleep(1)

driver.implicitly_wait(1)


while True:
#找刪除按鈕
    delButtons = driver.find_elements_by_css_selector(
    '*[ng-click^=delOne]')
#判斷有沒有刪除按鈕
    if delButtons == []:
        break
#如果有就找到第一個元素,點擊他
    delButtons[0].click()
#點確定
    driver.find_element_by_css_selector('.modal-footer  .btn-primary').click()

    time.sleep(1)


driver.implicitly_wait(5)

這樣就沒有問題杖虾,因為我們每次刪除按鈕都會重新獲取當前頁面烂瘫,大家會不會有個疑惑循環(huán)前有個implicitly_wait(1)循環(huán)后又把implicitly_wait(1)改成implicitly_wait(5)呢,主要是因為循環(huán)刪除總有一次刪光了,刪光了最后一次循環(huán)執(zhí)行delButtons = driver.find_elements_by_css_selector('*[ng-click^=delOne]')的時候坟比,因為刪光了就沒有元素芦鳍,就會等待全局的等待時間比如5秒,就會等待5秒葛账,臨時的把時間改短了點這樣比較好柠衅。這里的time.sleep(1)很重要,因為你點擊確定刪除的時候就會執(zhí)行刪除操作籍琳,服務(wù)端就會刪除數(shù)據(jù)菲宴,界面刷新會花一段時間,如果沒有sleep(1)就會立即獲取頁面趋急,就會獲取到?jīng)]有更新的頁面元素


看一個練習(xí):
Selenium 作業(yè) 6
作業(yè)1

登錄華為官網(wǎng) https://www.vmall.com/喝峦,
點擊 "華為官網(wǎng)" 鏈接

查 "華為官網(wǎng)" 頁面上是否 有如下主菜單

智能手機
筆記本
平板
穿戴設(shè)備
智能家居
更多產(chǎn)品
軟件應(yīng)用
服務(wù)與支持

最后再回到主窗口, 檢查鼠標停留在 "筆記本&平板" 處的時候宣谈, 是否顯示的菜單有
"平板電腦 筆記本電腦 筆記本配件"

怎么模擬鼠標停留事件愈犹,請大家自行網(wǎng)上搜索,看看能不能自己解決問題闻丑。

from selenium import  webdriver
import time

from selenium.webdriver import ActionChains

driver = webdriver.Chrome('E:\ChromDriver\chromdriver2.43\chromedriver.exe')
driver.get('https://www.vmall.com/')
driver.implicitly_wait(10)
# print(driver.title)
#主窗口handle
main_window=driver.current_window_handle
#點擊進入華為官網(wǎng)
driver.find_element_by_css_selector('a[).click()

for handle in driver.window_handles:
    driver.switch_to.window(handle)
    if '華為消費者業(yè)務(wù)官網(wǎng)' in driver.title:
        # print(handle)
        break

#找到主菜單
orders_eles = driver.find_elements_by_css_selector('ul.clearfix.nav-cnt a.a-common.products-name')

orders_txt = [ele.text for ele in orders_eles]
expect_orders='''智能手機
    筆記本
    平板
    穿戴設(shè)備
    智能家居
    更多產(chǎn)品
    軟件應(yīng)用
    服務(wù)與支持
'''
expect_text = [order.strip() for order in expect_orders.split('\n')]
if orders_txt == expect_text:
    print('匹配菜單成功')
else:
    print('匹配失敗')
    # print(orders_txt)
    # print(expect_text)
#回到主頁面
driver.switch_to.window(main_window)
# print(driver.title)

#鼠標停留在筆記本菜單
ele = driver.find_element_by_id('zxnav_1')
ActionChains(driver).move_to_element(ele).perform()

#檢查菜單項
css='li#zxnav_1 div.category-panels.category-panels-1 span'
orders = driver.find_elements_by_css_selector(css)
order_text = [order.text for order in orders]
# print(order_txt)
expect_txt = u'''平板電腦|筆記本電腦|筆記本配件'''
order_txt='|'.join(order_text)

if expect_txt == order_txt:
    print('匹配菜單成功')
else:
    print('匹配失敗')
    print(expect_txt)
    print(order_txt)


driver.quit()

作業(yè)2
寫一個程序?qū)崿F(xiàn)如下的自動化過程

  • 登錄 https://tinypng.com/
  • 點擊 上傳文件的虛線框
  • 選擇 插圖,在本地目錄中選擇一張準備好的圖片 , 查看是否能夠上傳圖片成功
from selenium import webdriver

import time

driver = webdriver.Chrome('E:\ChromDriver\chromdriver2.43\chromedriver.exe')
driver.implicitly_wait(10)


driver.get('https://tinypng.com/')
print(driver.title)
#點擊上傳圖標
driver.find_element_by_css_selector("figure.icon").click()

# 直接發(fā)送鍵盤消息給 當前應(yīng)用程序勋颖,
# 前提是瀏覽器必須是當前應(yīng)用
#   pip install pypiwin32
import win32com.client

shell = win32com.client.Dispatch("WScript.Shell")

# 有的系統(tǒng)要加 '\r'
# 有的系統(tǒng)要加 '\r\n'
img_name='1.jpg'
shell.Sendkeys('e:\\' + img_name + '\n'+ '\n')#在當前的焦點應(yīng)用程序發(fā)送一個字符串
time.sleep(3)

file_ele = driver.find_element_by_css_selector('div.before:nth-of-type(1)')

print(file_ele.text)
file_name = file_ele.text.split('\n')[1]

if img_name.upper() == file_name.upper():
    print('上傳成功')
else:
    print('上傳失敗')
input('...')
driver.quit()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗦嗡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饭玲,更是在濱河造成了極大的恐慌侥祭,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茄厘,死亡現(xiàn)場離奇詭異矮冬,居然都是意外死亡,警方通過查閱死者的電腦和手機次哈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門胎署,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窑滞,你說我怎么就攤上這事琼牧。” “怎么了哀卫?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵巨坊,是天一觀的道長。 經(jīng)常有香客問我此改,道長趾撵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任共啃,我火速辦了婚禮占调,結(jié)果婚禮上暂题,老公的妹妹穿的比我還像新娘。我一直安慰自己妈候,他們只是感情好敢靡,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苦银,像睡著了一般啸胧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幔虏,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天纺念,我揣著相機與錄音,去河邊找鬼想括。 笑死陷谱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的瑟蜈。 我是一名探鬼主播烟逊,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铺根!你這毒婦竟也來了宪躯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤位迂,失蹤者是張志新(化名)和其女友劉穎访雪,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掂林,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡臣缀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了泻帮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片精置。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖刑顺,靈堂內(nèi)的尸體忽然破棺而出氯窍,到底是詐尸還是另有隱情,我是刑警寧澤蹲堂,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布狼讨,位于F島的核電站,受9級特大地震影響柒竞,放射性物質(zhì)發(fā)生泄漏政供。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望布隔。 院中可真熱鬧离陶,春花似錦、人聲如沸衅檀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哀军。三九已至沉眶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間杉适,已是汗流浹背谎倔。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猿推,地道東北人片习。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹬叭,于是被迫代替她去往敵國和親藕咏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容