作者:東東
來源:https://blog.yasking.org
(一)判斷元素是否存在
self.driver.find_element(By.ID, 'name').size != 0
(二)智能延時/等待指定節(jié)點加載
當(dāng)需要獲取的元素節(jié)點是由 JavaScript
動態(tài)生成時,需要讓獲取節(jié)點的代碼'等一等'再運行 通過 time.sleep(5)這種方式,當(dāng)需要等待網(wǎng)絡(luò)請求比較多時,會導(dǎo)致完成一次運行需要等待很久,如下是一些代碼及使用場景
每次點擊事件后都應(yīng)該添加智能延時代碼,它會等待時間為0~5秒
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Firefox()
driver.get('http://www.example.com/')
driver.find_element(By.ID, 'submit').click()
driver.implicitly_wait(5)
一般來講,稍稍設(shè)置大一些的等待時間即可加載出相應(yīng)節(jié)點的數(shù)據(jù),有一種更為確定的方法,可以在指定的時間內(nèi)等待,直到我們需要的節(jié)點加載出來,相比于 implicitly_wait
它更加的精確,節(jié)省時間,因為它不必等待我們不關(guān)心的節(jié)點加載
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get('http://www.example.com/')
wait = WebDriverWait(self.driver, 10)
wait.until(
EC.presence_of_element_located((By.ID, 'submit'))
).click()
如上的寫法是針對于獲取到節(jié)點就點擊的,如果一個登陸表單時動態(tài)加載的,并且里面的元素也是動態(tài)加載的,那么首先需要先獲取登陸表單,然后在表單的基礎(chǔ)上再選擇節(jié)點,示例代碼段如下
# 等待登錄頁加載完成
wait = WebDriverWait(driver, WAIT_TIME)
formElement = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, '.sign-in-form'))
)
# 填寫郵箱與密碼登陸
emailElement = formElement.find_element(By.ID, 'email')
emailElement.send_keys(username)
passwordEmement = formElement.find_element(By.ID, 'password')
passwordEmement.send_keys(password)
# 點擊登陸
formElement.find_element(By.CSS_SELECTOR, '[type='button']').click()
driver.implicitly_wait(WAIT_TIME)
(三)元素個數(shù)(Elements Counts)
一些情況下,獲取元素下子節(jié)點的數(shù)量有助于幫助程序判斷節(jié)點的狀態(tài),簡化代碼,而且有時數(shù)量信息也是很重要的數(shù)據(jù)
counts = self.driver.find_elements(By.CLASS_NAME, 'img')
print len(counts)
為了這個問題,我Google了有一會,有說需要使用xpath才能返回列表的,有的是java的代碼,嘗試好久,最后我才在一個問題下邊猛然的發(fā)現(xiàn)我的方法少了一個 s
,是 find_elements_by_xxx()
而不是 find_element_by_xxx()
(四)處理iframe的情況
driver.switchtoframe(self, frame_reference) 這個方法已經(jīng)廢棄
新的函數(shù)如下:
def frame_switch(css_selector):
driver.switch_to.frame(driver.find_element_by_css_selector(css_selector))
def frame_switch(name):
driver.switch_to.frame(driver.find_element_by_name(name))
處理完iframe,回到之前的界面
driver.switch_to.default_content()
(五)Firefox與Chrome的driver差異
當(dāng)寫完Login()函數(shù)后,加載其它函數(shù),比如或許用戶詳情頁的時候,F(xiàn)irefox Driver或自動帶上Cookies,Chrome Driver 不會自動加載Cookies,所以使用Chrome比Firefox需要多兩行代碼,手動加載Cookies
# 登陸后獲取cookies
cookies = driver.get_cookies()
# 在加載新的頁面后倒入Cookies
for cookie in cookies:
driver.add_cookie(cookie)
如果有些網(wǎng)站的Cookies有效期很長,那么可以將Cookies保存到文件
# 保存Cookies到文件
import pickle
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get('http://www.google.com')
pickle.dump( driver.get_cookies() , open('cookies.pkl','wb'))
# 從文件加載Cookies
import pickle
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get('http://www.google.com')
cookies = pickle.load(open('cookies.pkl', 'rb'))
for cookie in cookies:
driver.add_cookie(cookie)
(六)滾動加載
有些數(shù)據(jù)一頁展示不完,當(dāng)側(cè)邊欄向下拉或者鼠標(biāo)滾動的時候才會繼續(xù)加載數(shù)據(jù),這種模式在瀑布流的圖片展示站點非常常見,不過也很好解決
# 回到頂部
js='var q=document.body.scrollTop=0'
driver.execute_script(js)
# 拉到底部
js='var q=document.body.scrollTop=10000'
driver.execute_script(js)
在網(wǎng)上搜索的時候有這樣的寫法 document.documentElement.scrollTop=10000
,我在測試的時候發(fā)現(xiàn)body的寫法是工作的,這可能跟網(wǎng)站/瀏覽器 有一定關(guān)系,在測試的時候哪種能工作就用哪種吧
題圖:pexels,CC0 授權(quán)。