WEB自動(dòng)化簡(jiǎn)介
測(cè)試:
- 所有的項(xiàng)目都可以做自動(dòng)化?1. 軟件需求變更不頻繁,2. 項(xiàng)目周期比較長(zhǎng),3. 自動(dòng)化腳本能夠重復(fù)利用
- 自動(dòng)化測(cè)試介入點(diǎn):系統(tǒng)測(cè)試
- 自動(dòng)化項(xiàng)目的實(shí)施過(guò)程:可行性分析,框架的選擇selenium,RF,需求分析,計(jì)劃,測(cè)試用例設(shè)計(jì),無(wú)人值守,提交報(bào)告,腳本維護(hù)
簡(jiǎn)介:
Selenium 是一套 Web網(wǎng)站 的程序自動(dòng)化操作 解決方案。
通過(guò)它,我們可以寫出自動(dòng)化程序,像人一樣在瀏覽器里操作web界面。 比如點(diǎn)擊界面按鈕,在文本框中輸入文字 等操作。
而且還能從web界面獲取信息。 比如獲取 火車、汽車票務(wù)信息,招聘網(wǎng)站職位信息,財(cái)經(jīng)網(wǎng)站股票價(jià)格信息 等等,然后用程序進(jìn)行分析處理。
Selenium 的自動(dòng)化原理是這樣的
(自動(dòng)化程序-Selenium客戶端庫(kù))->瀏覽器驅(qū)動(dòng):由瀏覽器廠商提供->瀏覽器比如:Chrom,Firefox
我們寫的自動(dòng)化程序 需要使用 客戶端庫(kù)。
我們程序的自動(dòng)化請(qǐng)求都是通過(guò)這個(gè)庫(kù)里面的編程接口發(fā)送給瀏覽器。
比如,我們要模擬用戶點(diǎn)擊界面按鈕, 自動(dòng)化程序里面就應(yīng)該 調(diào)用客戶端庫(kù)相應(yīng)的函數(shù), 就會(huì)發(fā)送 點(diǎn)擊元素 的請(qǐng)求給 下方的 瀏覽器驅(qū)動(dòng)。 然后,瀏覽器驅(qū)動(dòng)再轉(zhuǎn)發(fā)這個(gè)請(qǐng)求給瀏覽器。
這個(gè)自動(dòng)化程序發(fā)送給瀏覽器驅(qū)動(dòng)的請(qǐng)求 是HTTP請(qǐng)求。
客戶端庫(kù)從哪里來(lái)的? 是Selenium組織提供的。
Selenium組織提供了多種 編程語(yǔ)言的Selenium客戶端庫(kù), 包括 java,python,js, ruby等,方便不同編程語(yǔ)言的開(kāi)發(fā)者使用。
我們只需要安裝好客戶端庫(kù),調(diào)用這些庫(kù),就可以發(fā)出自動(dòng)化請(qǐng)求給瀏覽器咯。
瀏覽器驅(qū)動(dòng) 也是一個(gè)獨(dú)立的程序,是由瀏覽器廠商提供的, 不同的瀏覽器需要不同的瀏覽器驅(qū)動(dòng)。 比如 Chrome瀏覽器和 火狐瀏覽器有 各自不同的驅(qū)動(dòng)程序。
瀏覽器驅(qū)動(dòng)接收到我們的自動(dòng)化程序發(fā)送的界面操作請(qǐng)求后,會(huì)轉(zhuǎn)發(fā)請(qǐng)求給瀏覽器, 讓瀏覽器去執(zhí)行對(duì)應(yīng)的自動(dòng)化操作。
瀏覽器執(zhí)行完操作后,會(huì)將自動(dòng)化的結(jié)果返回給瀏覽器驅(qū)動(dòng), 瀏覽器驅(qū)動(dòng)再通過(guò)HTTP響應(yīng)的消息返回給我們的自動(dòng)化程序的客戶端庫(kù)。
自動(dòng)化程序的客戶端庫(kù) 接收到響應(yīng)后,將結(jié)果轉(zhuǎn)化為 數(shù)據(jù)對(duì)象 返回給 我們的代碼。
我們的程序就可以知道這次自動(dòng)化操作的結(jié)果如何了。
Python+Selenium環(huán)境搭建
selenium官方下載地址:http://selenium-release.storage.googleapis.com/index.html
訪問(wèn)上方下載地址下載或者使用python命令pip install selenium
Java+Selenium環(huán)境搭建
selenium官方下載地址:http://selenium-release.storage.googleapis.com/index.html
下載selenium后在項(xiàng)目中添加selenium-server-standalone-xx.xx.xx.jar\selenium-java-xxx.xxx.jar\selenium-java-xxx.xxx.srcs.jar
添加完畢后設(shè)置驅(qū)動(dòng)地址
System.setProperty("webdriver.gecko.driver","D:\Program Files\geckodriver.exe");
WebDriver firefoxDriver = new FirefoxDriver();
firefoxDriver.get("https://www.baidu.com");
下載瀏覽器對(duì)應(yīng)驅(qū)動(dòng)Chrome,如果是其他瀏覽器百度即可太簡(jiǎn)單了不說(shuō)了 驅(qū)動(dòng)地址:http://chromedriver.storage.googleapis.com/index.html
其中,下面這行代碼,就會(huì)運(yùn)行瀏覽器驅(qū)動(dòng),并且運(yùn)行Edge瀏覽器
```python
Edge(r'C:\Users\sj176\Downloads\edgedriver_win64\msedgedriver.exe')
這樣寫的話每次我們都需要指定一下才能生效,所以還可以不指定,但是要將驅(qū)動(dòng)放入到環(huán)境變量中
我們可以把瀏覽器驅(qū)動(dòng) 所在目錄 加入環(huán)境變量 Path , 寫代碼時(shí),就可以無(wú)需指定瀏覽器驅(qū)動(dòng)路徑了,像下面這樣
driver=webdriver.Edge()
置完環(huán)境變量后,重啟IDE新的環(huán)境變量才會(huì)生效。
定位
如果元素定位不到如何分析?
- 元素沒(méi)有加載完成
- Frame中
- 元素不可用,不可讀,不可見(jiàn)
- 動(dòng)態(tài)元素,動(dòng)態(tài)加載出來(lái)的DIV層
定位方式-Xpath:
- ID:
- NAME
- CLASS_NAME
- XPATH
- CSS
- TAG_NAME
- LINK_TEXT
- PARTAIL_LINK_TEXT
示例代碼
self.driver.get('https://www.baidu.com')
# ID定位id屬性定位
# driver.find_element(By.ID,'kw').send_keys('小明')
# NAME定位 name屬性定位
# driver.find_element(By.NAME,'wd').send_keys('dddd')
# LINK_TEXT 匹配完全text字符
# self.driver.find_element(By.LINK_TEXT, '新聞').click()
# elements = wd.find_elements(By.TAG_NAME, 'div')
# PARTIAL_LINK_TEXT 匹配符合任意一個(gè)字符
# self.driver.find_element(By.PARTIAL_LINK_TEXT, '聞').click()
# XPATH
# 絕對(duì)路徑開(kāi)頭是/相對(duì)路徑是//,相對(duì)路徑+索引定位//from/span[1]input這里的索引是從1開(kāi)始的,相對(duì)路徑+屬性定位://input[@*='no'] 相對(duì)路徑+部分屬性值定位以開(kāi)頭//*[starts-with(@autocomplete,'of)],以結(jié)尾//*[substring(@autocomplete,2)='tf'],包含//*[contains(@autocomplete,'of')],相對(duì)路徑+文本定位//span[text()='圖片']
self.driver.find_element(By.XPATH,'//*[@id="kw"]').send_keys('111')
定位方式-css:
- 絕對(duì)路徑-不用
- 通過(guò)ID和Class定位
- 通過(guò)屬性定位
- 通過(guò)部分屬性定位
- 查詢子元素定位
- 查詢兄弟元素定位
操控元素的基本方法
- 點(diǎn)擊元素:調(diào)用 WebElement 對(duì)象的 click 方法去點(diǎn)擊 元素的時(shí)候, 瀏覽器接收到自動(dòng)化命令,點(diǎn)擊的是該元素的 中心點(diǎn) 位置 。
- 輸入元素: 把輸入框中已經(jīng)有的內(nèi)容清除掉,可以使用WebElement對(duì)象的clear方法
element = wd.find_element(By.ID, "input1")
element.clear() # 清除輸入框已有的字符串
element.send_keys('xiaobai') # 輸入新字符串
- 獲取文本元素: WebElement 對(duì)象的 text
- 獲取屬性元素: WebElement 對(duì)象的get_attribute('class')
- 獲取整個(gè)元素對(duì)應(yīng)的HTML可以使用 要獲取整個(gè)元素對(duì)應(yīng)的HTML文本內(nèi)容,可以使用 element.get_attribute('outerHTML')如果,只是想獲取某個(gè)元素 內(nèi)部 的HTML文本內(nèi)容,可以使用 element.get_attribute('innerHTML')
- 獲取輸入框的文字:對(duì)于input輸入框的元素,要獲取里面的輸入文本,用text屬性是不行的,這時(shí)可以使用 element.get_attribute('value')
- 獲取輸入框的文本內(nèi)容2:可以嘗試使用 element.get_attribute('innerText') ,或者 element.get_attribute('textContent')使用 innerText 和 textContent 的區(qū)別是,前者只顯示元素可見(jiàn)文本內(nèi)容,后者顯示所有內(nèi)容(包括display屬性為none的部分)
睡眠
隱式等待:
Selenium提供了一個(gè)更合理的解決方案,是這樣的:
當(dāng)發(fā)現(xiàn)元素沒(méi)有找到的時(shí)候, 并不立即返回 找不到元素的錯(cuò)誤。
而是周期性(每隔半秒鐘)重新尋找該元素,直到該元素找到,
或者超出指定最大等待時(shí)長(zhǎng),這時(shí)才 拋出異常(如果是 find_elements 之類的方法, 則是返回空列表)
Selenium 的 Webdriver 對(duì)象 有個(gè)方法叫 implicitly_wait ,可以稱之為 隱式等待 ,或者 全局等待 。
該方法接受一個(gè)參數(shù), 用來(lái)指定 最大等待時(shí)長(zhǎng)。
如:
driver.implicitly_wait(10)
那么后續(xù)所有的 find_element 或者 find_elements 之類的方法調(diào)用 都會(huì)采用上面的策略:
如果找不到元素, 每隔 半秒鐘 再去界面上查看一次, 直到找到該元素, 或者 過(guò)了10秒 最大時(shí)長(zhǎng)。
那么是不是有了 implicitwait , 可以徹底不用sleep了呢?
不是的,有的時(shí)候我們等待元素出現(xiàn),仍然需要sleep。
強(qiáng)制等待:
sleep(10)python程序中的強(qiáng)制等待,不管遇到什么情況都會(huì)強(qiáng)制等待10秒接著執(zhí)行;
顯示等待:
WebDriverWait(driver,20).until(EC.visibility_of_element_located((By.XPATH,'//a[text()=" - Web Browser Automation"]')))
driver.find_element_by_xpath('//a[text()=" - Web Browser Automation"]').click()
WebDriverWait,配合該類的until()和until_not()方法,就能夠根據(jù)判斷條件而進(jìn)行靈活地等待了.它主要的意思就是:程序每隔x秒看一眼,如果條件成立了,則執(zhí)行下一步,否則繼續(xù)等待,直到超過(guò)設(shè)置的最長(zhǎng)時(shí)間,然后拋出TimeoutException
css選擇器
通過(guò) CSS Selector 選擇單個(gè)元素的方法是
find_element(By.CSS_SELECTOR, CSS Selector參數(shù))
選擇所有元素的方法是
find_elements(By.CSS_SELECTOR, CSS Selector參數(shù))
要選擇 所有的tag名為div的元素,就可以是這樣
elements = wd.find_elements(By.CSS_SELECTOR, 'div')
等價(jià)于
elements = wd.find_elements(By.TAG_NAME, 'div')
根據(jù)ID如下方:
<input type="text" id='searchtext' />
就可以使用#searchtext
element = wd.find_element(By.CSS_SELECTOR, '#searchtext')
element.send_keys('你好')
根據(jù)class如下方:
elements = wd.find_elements(By.CLASS_NAME, 'animal')
使用css這樣寫
elements = wd.find_elements(By.CSS_SELECTOR, '.animal')
選擇子元素和后代元素
<div id='container'>
<div id='layer1'>
<div id='inner11'>
<span>內(nèi)層11</span>
</div>
<div id='inner12'>
<span>內(nèi)層12</span>
</div>
</div>
<div id='layer2'>
<div id='inner21'>
<span>內(nèi)層21</span>
</div>
</div>
</div>
如果 元素2 是 元素1 的 直接子元素, CSS Selector 選擇子元素的語(yǔ)法是這樣的
元素1 > 元素2
最終選擇的元素是 元素2, 并且要求這個(gè) 元素2 是 元素1 的直接子元素
也支持更多層級(jí)的選擇, 比如
元素1 > 元素2 > 元素3 > 元素4
就是選擇 元素1 里面的子元素 元素2 里面的子元素 元素3 里面的子元素 元素4 , 最終選擇的元素是 元素4
如果 元素2 是 元素1 的 后代元素, CSS Selector 選擇后代元素的語(yǔ)法是這樣的
元素1 元素2
中間是一個(gè)或者多個(gè)空格隔開(kāi)
最終選擇的元素是 元素2 , 并且要求這個(gè) 元素2 是 元素1 的后代元素
也支持更多層級(jí)的選擇, 比如
元素1 元素2 元素3 元素4
最終選擇的元素是 元素4
根據(jù)屬性選擇
如:
<a >蘇ICP備88885574號(hào)</a>
css 選擇器支持通過(guò)任何屬性來(lái)選擇元素,語(yǔ)法是用一個(gè)方括號(hào) [] 。
# 根據(jù)屬性選擇元素
element = wd.find_element(By.CSS_SELECTOR, '[)
當(dāng)然,前面可以加上標(biāo)簽名的限制,比如 div[class='SKnet'] 表示 選擇所有 標(biāo)簽名為div,且class屬性值為SKnet的元素
屬性值用單引號(hào),雙引號(hào)都可以。
根據(jù)屬性選擇,還可以不指定屬性值,比如 [href] , 表示選擇 所有 具有 屬性名 為href 的元素,不管它們的值是什么
CSS 還可以選擇 屬性值 包含 某個(gè)字符串 的元素
比如, 要選擇a節(jié)點(diǎn),里面的href屬性包含了 miitbeian 字符串,就可以這樣寫
a[href*="miitbeian"]
還可以 選擇 屬性值 以某個(gè)字符串 開(kāi)頭 的元素
比如, 要選擇a節(jié)點(diǎn),里面的href屬性以 http 開(kāi)頭 ,就可以這樣寫
a[href^="http"]
還可以 選擇 屬性值 以某個(gè)字符串 結(jié)尾 的元素
比如, 要選擇a節(jié)點(diǎn),里面的href屬性以 gov.cn 結(jié)尾 ,就可以這樣寫
a[href$="gov.cn"]
如果一個(gè)元素具有多個(gè)屬性
<div class="misc" ctype="gun">沙漠之鷹</div>
CSS 選擇器 可以指定 選擇的元素要 同時(shí)具有多個(gè)屬性的限制,像這樣 div[class=misc][ctype=gun]
語(yǔ)法聯(lián)合使用
CSS selector的另一個(gè)強(qiáng)大之處在于: 選擇語(yǔ)法 可以 聯(lián)合使用
比如, 我們要選擇 網(wǎng)頁(yè) html 中的元素 <span class='copyright'>版權(quán)</span>
<div id='bottom'>
<div class='footer1'>
<span class='copyright'>版權(quán)</span>
<span class='date'>發(fā)布日期:2018-03-03</span>
</div>
<div class='footer2'>
<span>備案號(hào)
<a >蘇ICP備88885574號(hào)</a>
</span>
</div>
</div>
CSS selector 表達(dá)式 可以這樣寫:
div.footer1 > span.copyright
就是 選擇 一個(gè)class 屬性值為 copyright 的 span 節(jié)點(diǎn), 并且要求其 必須是 class 屬性值為 footer1 的 div節(jié)點(diǎn) 的子節(jié)點(diǎn)
也可以更簡(jiǎn)單:
.footer1 > .copyright
就是 選擇 一個(gè)class 屬性值為copyright 的節(jié)點(diǎn)(不限類型), 并且要求其 必須是 class 屬性值為 footer1 的節(jié)點(diǎn)的 子節(jié)點(diǎn)
當(dāng)然 這樣也是可以的:
.footer1 .copyright
組選擇
如果我們要 同時(shí)選擇所有class 為 plant 和 class 為 animal 的元素。怎么辦?
這種情況,css選擇器可以 使用 逗號(hào) ,稱之為 組選擇 ,像這樣
class.plant , class.animal
再比如,我們要同時(shí)選擇所有tag名為div的元素 和 id為BYHY的元素,就可以像這樣寫
div,#BYHY
#t1 > span , #t1 > p
選擇所有 id 為 t1 里面的 span 和 所有的 p 元素
另外注意:組選擇結(jié)果列表中,選中元素排序, 不是 組表達(dá)式的次序, 而是符合這些表達(dá)式的元素,在HTML文檔中的出現(xiàn)的次序
父元素的第n個(gè)子節(jié)點(diǎn),選擇的是 第2個(gè)子元素,并且是span類型
span:nth-child(2)
直接這樣寫 :nth-child(2)也可以就是選擇所有位置為第2個(gè)的所有元素,不管是什么類型
父元素的倒數(shù)第n個(gè)子節(jié)點(diǎn)
p:nth-last-child(1)
是選擇第倒數(shù)第1個(gè)子元素,并且是p元素
父元素的第幾個(gè)某類型的子節(jié)點(diǎn)
我們可以指定選擇的元素 是父元素的第幾個(gè) 某類型的 子節(jié)點(diǎn)
使用 nth-of-type
比如,
我們要選擇 唐詩(shī) 和宋詞 的第一個(gè) 作者,
可以像上面那樣思考:選擇的是 第2個(gè)子元素,并且是span類型
所以這樣可以這樣寫 span:nth-child(2) ,
還可以這樣思考,選擇的是 第1個(gè)span類型 的子元素
所以也可以這樣寫 span:nth-of-type(1)
父元素的倒數(shù)第幾個(gè)某類型的子節(jié)點(diǎn)
當(dāng)然也可以反過(guò)來(lái), 選擇父元素的 倒數(shù)第幾個(gè)某類型 的子節(jié)點(diǎn)
使用 nth-last-of-type
像這樣
p:nth-last-of-type(2)
如果要選擇的是父元素的 偶數(shù)節(jié)點(diǎn),使用 nth-child(even)
比如
p:nth-child(even)
如果要選擇的是父元素的 奇數(shù)節(jié)點(diǎn),使用 nth-child(odd)
p:nth-child(odd)
如果要選擇的是父元素的 某類型偶數(shù)節(jié)點(diǎn),使用 nth-of-type(even)
如果要選擇的是父元素的 某類型奇數(shù)節(jié)點(diǎn),使用 nth-of-type(odd)
兄弟節(jié)點(diǎn)選擇
還有一種思考方法,就是選擇 h3 后面緊跟著的兄弟節(jié)點(diǎn) span。
這就是一種 相鄰兄弟 關(guān)系,可以這樣寫 h3 + span
表示元素 緊跟關(guān)系的 是 加號(hào)
后續(xù)所有兄弟節(jié)點(diǎn)選擇
h3 ~ span
還有更多用法具體參考:https://www.w3school.com.cn/cssref/css_selectors.asp
frame切換
wd.switch_to.frame(frame_reference)
其中, frame_reference 可以是 frame 元素的屬性 name 或者 ID
也可以填寫frame 所對(duì)應(yīng)的 WebElement 對(duì)象。
wd.switch_to.frame(wd.find_element(By.TAG_NAME, "iframe"))
切換回去到主html
wd.switch_to.default_content()
切換到新的窗口
我們經(jīng)常遇到,點(diǎn)擊一個(gè)鏈接 或者 按鈕,就會(huì)打開(kāi)一個(gè) 新窗口 。
可以使用Webdriver對(duì)象的switch_to屬性的 window方法,如下所示
wd.switch_to.window(handle)
WebDriver對(duì)象有window_handles 屬性,這是一個(gè)列表對(duì)象, 里面包括了當(dāng)前瀏覽器里面所有的窗口句柄。
所謂句柄,大家可以想象成對(duì)應(yīng)網(wǎng)頁(yè)窗口的一個(gè)ID,
那么我們就可以通過(guò) 類似下面的代碼
方式一
for handle in wd.window_handles:
# 先切換到該窗口
wd.switch_to.window(handle)
# 得到該窗口的標(biāo)題欄字符串,判斷是不是我們要操作的那個(gè)窗口
if 'Bing' in wd.title:
# 如果是,那么這時(shí)候WebDriver對(duì)象就是對(duì)應(yīng)的該該窗口,正好,跳出循環(huán),
break
方式二
# mainWindow變量保存當(dāng)前窗口的句柄
mainWindow = wd.current_window_handle
切換到新窗口操作完后,就可以直接像下面這樣,將driver對(duì)應(yīng)的對(duì)象返回到原來(lái)的窗口
#通過(guò)前面保存的老窗口的句柄,自己切換到老窗口
wd.switch_to.window(mainWindow)
打開(kāi)新窗口
打開(kāi)新標(biāo)簽頁(yè)并切換進(jìn)入
driver.switch_to_window('tab')
driver.get('https://www.baidu.com')
print(driver.title)
打開(kāi)新窗口,切換并進(jìn)入
driver.switch_to_window('window')
driver.get('https://www.baidu.com')
print(driver.title)
選擇框
常見(jiàn)的選擇框包括: radio框、checkbox框、select框
radio框
radio框選擇選項(xiàng),直接用WebElement的click方法,模擬用戶點(diǎn)擊就可以了
checkbox框
對(duì)checkbox進(jìn)行選擇,也是直接用 WebElement 的 click 方法,模擬用戶點(diǎn)擊選擇。
需要注意的是,要選中checkbox的一個(gè)選項(xiàng),必須 先獲取當(dāng)前該復(fù)選框的狀態(tài) ,如果該選項(xiàng)已經(jīng)勾選了,就不能再點(diǎn)擊。否則反而會(huì)取消選擇
<div id="s_checkbox">
<input type="checkbox" name="teacher" value="小江老師">小江老師<br>
<input type="checkbox" name="teacher" value="小雷老師">小雷老師<br>
<input type="checkbox" name="teacher" value="小凱老師" checked="checked">小凱老師
</div>
先把已選中的取消選中,確保都是未選狀態(tài)
再點(diǎn)擊小雷老師
# 先把 已經(jīng)選中的選項(xiàng)全部點(diǎn)擊一下
elements = wd.find_elements(By.CSS_SELECTOR,
'#s_checkbox input[checked="checked"]')
for element in elements:
element.click()
# 再點(diǎn)擊 小雷老師
wd.find_element(By.CSS_SELECTOR,
"#s_checkbox input[value='小雷老師']").click()
select框
radio框及checkbox框都是input元素,只是里面的type不同而已
select框 則是一個(gè)新的select標(biāo)簽
對(duì)于Select 選擇框, Selenium 專門提供了一個(gè) Select類 進(jìn)行操作
from selenium.webdriver.support.ui import Select
s = Select(wd.find_element(By.ID, "ss_single"))
<option value="foo">Bar</option>
方式一:根據(jù)value值選擇
s.select_by_value('foo')
方式二:根據(jù)index值選擇
s.select_by_index(1)
方式三:根據(jù)可見(jiàn)文本選擇元素
s.select_by_visible_text('Bar')
去除選擇元素
deselect_by_value
deselect_by_index
deselect_by_visible_text
deselect_all
Select單元框
原來(lái)選的是什么,直接用Select方法選擇即可
s.select_by_value('foo')
Select多選框
可以用select類 的deselect_all方法,清除所有 已經(jīng)選中 的選項(xiàng)
然后再通過(guò) select_by_visible_text方法選中想要的值
# 導(dǎo)入Select類
from selenium.webdriver.support.ui import Select
# 創(chuàng)建Select對(duì)象
select = Select(wd.find_element(By.ID, "ss_multi"))
# 清除所有 已經(jīng)選中 的選項(xiàng)
select.deselect_all()
select.select_by_visible_text("1")
select.select_by_visible_text("2")
ActionChains 模擬鼠標(biāo)點(diǎn)擊,雙擊,移動(dòng)鼠標(biāo)到某個(gè)元素,鼠標(biāo)拖拽
ActionChains 類 里面提供了 一些特殊的動(dòng)作的模擬,我們可以通過(guò) ActionChains 類的代碼查看到
from selenium.webdriver.common.action_chains import ActionChains
鼠標(biāo)移移動(dòng)到某個(gè)元素上方
move_to_element
from selenium.webdriver.common.action_chains import ActionChains
ac = ActionChains(driver)
# 鼠標(biāo)移動(dòng)到 元素上
ac.move_to_element(
driver.find_element(By.CSS_SELECTOR, '[name="tj_briicon"]')
).perform()
直接執(zhí)行JavaScript
我們可以直接讓瀏覽器運(yùn)行一段javascript代碼,并且得到返回值,如下
# 直接執(zhí)行 javascript,里面可以直接用return返回我們需要的數(shù)據(jù)
nextPageButtonDisabled = driver.execute_script(
'''
ele = document.querySelector('.soupager > button:last-of-type');
return ele.getAttribute('disabled')
''')
# 返回的數(shù)據(jù)轉(zhuǎn)化為Python中的數(shù)據(jù)對(duì)象進(jìn)行后續(xù)處理
if nextPageButtonDisabled == 'disabled': # 是最后一頁(yè)
return True
else: # 不是最后一頁(yè)
return False
有時(shí),自動(dòng)化的網(wǎng)頁(yè)內(nèi)容很長(zhǎng),或者很寬,超過(guò)一屏顯示
如果我們要點(diǎn)擊的元素不在窗口可見(jiàn)區(qū)內(nèi),新版本的selenium協(xié)議, 瀏覽器發(fā)現(xiàn)要操作(比如點(diǎn)擊操作)的元素,不在可見(jiàn)區(qū)內(nèi),往往會(huì)操作失敗
這時(shí)就可以,可以調(diào)用 execute_script 直接執(zhí)行js代碼,讓該元素出現(xiàn)在窗口可見(jiàn)區(qū)正中
driver.execute_script("arguments[0].scrollIntoView({block:'center',inline:'center'})", job)
其中 arguments[0] 就指代了后面的第一個(gè)參數(shù) job 對(duì)應(yīng)的js對(duì)象,
js對(duì)象的 scrollIntoView 方法,就是讓元素滾動(dòng)到可見(jiàn)部分
block:'center' 指定垂直方向居中
inline:'center' 指定水平方向居中
滾動(dòng)頁(yè)面
方式一:縱向滾動(dòng)
js="var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)
方式二:橫向滾動(dòng)
js = "window.scrollTo(100,400);"
driver.execute_script(js)
凍結(jié)界面
如果遇到頁(yè)面鼠標(biāo)懸浮觸發(fā)的操作,則可以使用斷點(diǎn)然后凍結(jié)頁(yè)面來(lái)定位元素
在開(kāi)發(fā)者工具中輸入如下代碼即可
setTimeout(function(){debugger}, 5000)
含義表示5000毫秒后瀏覽器會(huì)進(jìn)入debug狀態(tài),此時(shí)頁(yè)面都是靜止的;
彈出對(duì)話框
彈出的對(duì)話框有三種類型,分別是 Alert(警告信息)、confirm(確認(rèn)信息)和prompt(提示輸入)
alert點(diǎn)擊ok按鈕操作
driver.switch_to.alert.accept()
Confirm
點(diǎn)擊ok
driver.switch_to.alert.accept()
點(diǎn)擊dismiss
driver.switch_to.alert.dismiss()
prompt
輸入:driver.switch_to.alert.send_keys()
點(diǎn)擊ok:driver.switch_to.alert.accept()
點(diǎn)擊dismiss:driver.switch_to.alert.dismiss()
窗口大小
獲取窗口大小
driver.get_window_size()
設(shè)置窗口大小
driver.set_window_size(x, y)
獲取當(dāng)前窗口的標(biāo)題
driver.title
獲取當(dāng)前窗口URL地址
driver.current_url
截屏
以使用 WebDriver 的 get_screenshot_as_file方法來(lái)截屏并保存為圖片
# 截屏保存為圖片文件
driver.get_screenshot_as_file('1.png')
ele = driver.find_element_by_id('s4612')
ele.screenshot('ele.png') #元素截圖
上傳文件
<input type="file" multiple="multiple">
# 先定位到上傳文件的 input 元素
ele = wd.find_element(By.CSS_SELECTOR, 'input[type=file]')
# 再調(diào)用 WebElement 對(duì)象的 send_keys 方法
ele.send_keys(r'h:\g02.png')
但是,有的網(wǎng)頁(yè)上傳,是沒(méi)有 file 類型 的 input 元素的。
如果是Windows上的自動(dòng)化,可以采用 Windows 平臺(tái)專用的方法:
執(zhí)行
pip install pypiwin32
確保 pywin32 已經(jīng)安裝,然后參考如下示例代碼
# 找到點(diǎn)擊上傳的元素,點(diǎn)擊
driver.find_element(By.CSS_SELECTOR, '.dropzone').click()
sleep(2) # 等待上傳選擇文件對(duì)話框打開(kāi)
# 直接發(fā)送鍵盤消息給 當(dāng)前應(yīng)用程序,
# 前提是瀏覽器必須是當(dāng)前應(yīng)用
import win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
# 輸入文件路徑,最后的'\n',表示回車確定,也可能時(shí) '\r' 或者 '\r\n'
shell.Sendkeys(r"h:\a2.png" + '\n')
sleep(1)
手機(jī)模式
我們可以通過(guò) desired_capabilities 參數(shù),指定以手機(jī)模式打開(kāi)chrome瀏覽器
參考代碼,如下
from selenium import webdriver
mobile_emulation = { "deviceName": "Nexus 5" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome( desired_capabilities = chrome_options.to_capabilities())
driver.get('http://www.baidu.com')
input()
driver.quit()
Xpath定位
借鑒:實(shí)戰(zhàn)技巧 | 白月黑羽 (byhy.net)
模擬鍵盤操作
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
ActionChains(self.driver).key_down(Keys.CONTROL).perform()
self.driver.find_element_by_class_name("chartContainer").click()
self.driver.find_element_by_class_name("dropdown").click()
ActionChains(self.driver).key_up(Keys.CONTROL).perform()