1. 程式人生 > >selenium使用總結

selenium使用總結

selenium

selenium是一個支援各大瀏覽器的自動化測試工具,包括 Chrome,Safari,Firefox ,ie等。再構造爬蟲時,如果我們加入了User-Agent,那麼變偽裝成了瀏覽器,可以騙過一些技術水平不太高的網站。但如果使用selenium,則就不是偽裝瀏覽器,而是真正的用瀏覽器去訪問。有時我們可能會遇到這種情況,前端頁面展示出來的東西,並不在後端原始碼中,自然無法通過使用requests請求獲得原始碼進行爬取。這時候就可以使用selenium進行爬取資料,因為他就是用真實的瀏覽器去訪問頁面的,所以出現的內容和我們在前端看到的是一模一樣的。

0x01:selenium安裝

python下使用pip安裝

pip install selenium

此外,因為selenium是配合瀏覽器一起使用,所以需要下載瀏覽器的驅動(webdriver),以chrome為例
chrome的webdriver: http://chromedriver.storage.googleapis.com/index.html
不同的Chrome的版本對應的chromedriver.exe 版本也不一樣,下載時不要搞錯了。如果是最新的Chrome, 下載最新的chromedriver.exe 就可以了。把chromedriver的路徑也加到環境變數裡。

檢測:執行這段程式碼,會自動開啟百度

from selenium import webdriver      # 引入webdriver api
browser = webdriver.Chrome()        # 使用chrome瀏覽器宣告一個webdriver物件
browser.get('http://www.baidu.com/')    # 表示使用chrome以get的方式請求百度的url
driver.find_element_by_id("kw").send_keys("selenium")   # 檢索到百度的輸入框,輸入selenium
driver.find_element_by_id("su").click() # 檢索到百度的搜尋按鈕並點選

0x02:元素選取
在上面的例項中,最重要的就是找到搜尋框和搜尋按鈕對應的元素,然後再進行相應的操作(輸入關鍵字、點選),強大的selenium提供了多種提取元素的方法。

單個元素提取

find_element_by_id      # 通過元素id
find_element_by_name    # 通過name屬性
find_element_by_xpath   # 通過xpath
find_element_by_link_text   # 通過連結文字
find_element_by_partial_link_text
find_element_by_tag_name    # 通過標籤名
find_element_by_class_name      # 通過class名稱定位
find_element_by_css_selector    # 通過css選擇器定位

多個元素提取,返回一個列表

find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector

0x03:操作元素方法

  • clear 清除元素的內容:clear(self)
  • send_keys 模擬按鍵輸入:send_keys(self, *value)
  • click 點選元素:click(self)
  • submit 提交表單:submit(self)
  • 獲取元素屬性:get_attribute(self, name)
  • 獲取元素文字:text

0x04:頁面操作方法
from selenium import webdriver

  • 開啟瀏覽器:driver = webdriver.Chrome()
  • 請求一個url:driver.get("www.baidu.com")
  • 返回當前頁面的title:title = driver.title
  • 返回當前頁面的url:url = driver.current_url
  • 返回當前頁面的原始碼:source = driver.page_source
  • 關閉當前頁面:driver.close()
  • 登出並關閉瀏覽器:driver.quit()
  • 瀏覽器前進:driver.forward()
  • 瀏覽器後退:driver.back()
  • 重新整理當前頁面:driver.refresh()
  • 獲取當前session中的全部cookie:get_cookies(self)
  • 獲取當前會中中的指定cookie:get_cookie(self, name)
  • 在當前會話中新增cookie:add_cookie(self, cookie_dict)
  • 新增瀏覽器User-Agent:
    options.add_argument('User-Agent=Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30')
  • 新增設定項Chrome Options:
    options = webdriver.ChromeOptions()
    options.add_argument('xxxx')
    driver = webdriver.Chrome(chrome_options=options)

0x05:頁面等待
既然selenium是使用瀏覽器傳送請求,那麼勢必會載入一些東西,而且現在的網頁越來越多采用了ajax技術。如果程式碼執行到了提取元素的地方,而這個元素尚未被載入,那麼就會報錯。為了解決這個問題,selenium提供了兩種等待方式,隱式等待顯示等待。隱式等待是等待特定的時間,顯式等待是指定某一條件直到這個條件成立時繼續執行。

  • 隱式等待
    隱式等待比較簡單,就是簡單地設定一個等待時間,單位為秒。

      from selenium import webdriver
    
      driver = webdriver.Chrome()
      driver.implicitly_wait(10) # seconds
      driver.get("http://somedomain/url_that_delays_loading")
      myDynamicElement = driver.find_element_by_id("myDynamicElement")
  • 顯式等待
    顯式等待指定某個條件,然後設定最長等待時間。如果在這個時間還沒有找到元素,那麼便會丟擲異常了。

      from selenium import webdriver
      from selenium.webdriver.support.ui import WebDriverWait
      driver = webdriver.Chrome()
      driver.get("http://somedomain/url_that_delays_loading")
      try:
          element = WebDriverWait(driver, 10).until(
              EC.presence_of_element_located((By.ID, "myDynamicElement"))
          )
      finally:
          driver.quit()

wait模組的WebDriverWait類是顯性等待類,引數如下:

WebDriverWait(driver, 超時時長, 呼叫頻率, 忽略異常).until(可執行方法, 超時時返回的資訊)

這裡需要特別注意的是until或until_not中的可執行方法method引數,很多人傳入了WebElement物件,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))  # 錯誤

這是錯誤的用法,這裡的引數一定要是可以呼叫的,即這個物件一定有 call() 方法,否則會丟擲異常:

TypeError: 'xxx' object is not callable

在這裡,你可以用selenium提供的 expected_conditions 模組中的各種條件,也可以用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法,或者用自己封裝的方法都可以。那麼接下來我們看一下selenium提供的條件有哪些:

expected_conditions:

xpected_conditions是selenium的一個模組,其中包含一系列可用於判斷的條件:

selenium.webdriver.support.expected_conditions(模組)

這兩個條件類驗證title,驗證傳入的引數title是否等於或包含於driver.title
title_is
title_contains

這兩個人條件驗證元素是否出現,傳入的引數都是元組型別的locator,如(By.ID, 'kw')
顧名思義,一個只要一個符合條件的元素加載出來就通過;另一個必須所有符合條件的元素都加載出來才行
presence_of_element_located
presence_of_all_elements_located

這三個條件驗證元素是否可見,前兩個傳入引數是元組型別的locator,第三個傳入WebElement
第一個和第三個其實質是一樣的
visibility_of_element_located
invisibility_of_element_located
visibility_of

這兩個人條件判斷某段文字是否出現在某元素中,一個判斷元素的text,一個判斷元素的value
text_to_be_present_in_element
text_to_be_present_in_element_value

這個條件判斷frame是否可切入,可傳入locator元組或者直接傳入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it

這個條件判斷是否有alert出現
alert_is_present

這個條件判斷元素是否可點選,傳入locator
element_to_be_clickable

這四個條件判斷元素是否被選中,第一個條件傳入WebElement物件,第二個傳入locator元組
第三個傳入WebElement物件以及狀態,相等返回True,否則返回False
第四個傳入locator以及狀態,相等返回True,否則返回False
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be

最後一個條件判斷一個元素是否仍在DOM中,傳入WebElement物件,可以判斷頁面是否重新整理了
staleness_of

上面是所有17個condition,與until、until_not組合能夠實現很多判斷,如果能自己靈活封裝,將會大大提高指令碼的穩定性。

0x06:滑鼠操作
在現實的自動化測試中關於滑鼠的操作不僅僅是click()單擊操作,還有很多包含在ActionChains類中的操作。如下:

  • context_click(elem) 右擊滑鼠點選元素elem,另存為等行為
  • double_click(elem) 雙擊滑鼠點選元素elem,地圖web可實現放大功能
  • drag_and_drop(source,target) 拖動滑鼠,源元素按下左鍵移動至目標元素釋放
  • move_to_element(elem) 滑鼠移動到一個元素上
  • click_and_hold(elem) 按下滑鼠左鍵在一個元素上
  • perform() 在通過呼叫該函式執行ActionChains中儲存行為

舉例如下圖所示,獲取通過滑鼠右鍵另存為百度圖片logo。程式碼:

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
 
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
 
#滑鼠移動至圖片上 右鍵儲存圖片
elem_pic = driver.find_element_by_xpath("//div[@id='lg']/img")
print elem_pic.get_attribute("src")
action = ActionChains(driver).move_to_element(elem_pic)
action.context_click(elem_pic)
 
#重點:當右鍵滑鼠點選鍵盤游標向下則移動至右鍵選單第一個選項
action.send_keys(Keys.ARROW_DOWN)
time.sleep(3)
action.send_keys('v') #另存為
action.perform()
 
#獲取另存為對話方塊(失敗)
alert.switch_to_alert()
alert.accept()

0x07:鍵盤操作
在webdriver的Keys類中提供了鍵盤所有的按鍵操作,當然也包括一些常見的組合鍵操作如Ctrl+A(全選)、Ctrl+C(複製)、Ctrl+V(貼上)。

  • send_keys(Keys.ENTER) 按下回車鍵
  • send_keys(Keys.TAB) 按下Tab製表鍵
  • send_keys(Keys.SPACE) 按下空格鍵space
  • send_keys(Kyes.ESCAPE) 按下回退鍵Esc
  • send_keys(Keys.BACK_SPACE) 按下刪除鍵BackSpace
  • send_keys(Keys.SHIFT) 按下shift鍵
  • send_keys(Keys.CONTROL) 按下Ctrl鍵
  • send_keys(Keys.ARROW_DOWN) 按下滑鼠游標向下按鍵
  • send_keys(Keys.CONTROL,'a') 組合鍵全選Ctrl+A
  • send_keys(Keys.CONTROL,'c') 組合鍵複製Ctrl+C
  • send_keys(Keys.CONTROL,'x') 組合鍵剪下Ctrl+X
  • send_keys(Keys.CONTROL,'v') 組合鍵貼上Ctrl+V

這裡使用的例子參考蟲師的書籍《selenium2 python自動化測試》

import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
 
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
 
#輸入框輸入內容
elem = driver.find_element_by_id("kw")
elem.send_keys("Eastmount CSDN")
time.sleep(3)
 
#刪除一個字元CSDN 回退鍵
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
elem.send_keys(Keys.BACK_SPACE)
time.sleep(3)
 
#輸入空格+"部落格"
elem.send_keys(Keys.SPACE)
elem.send_keys(u"部落格")
time.sleep(3)
 
#ctrl+a 全選輸入框內容
elem.send_keys(Keys.CONTROL,'a')
time.sleep(3)
 
#ctrl+x 剪下輸入框內容
elem.send_keys(Keys.CONTROL,'x')
time.sleep(3)
 
#輸入框重新輸入搜尋
elem.send_keys(Keys.CONTROL,'v')
time.sleep(3)
 
#通過回車鍵替代點選操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)
time.sleep(3)
 
driver.quit()
  • 參考文章:
    https://cuiqingcai.com/2599.html

    https://huilansame.github.io/huilansame.github.io/archivers/sleep-implicitlywait-wait

    https://blog.csdn.net/Eastmount/article/details/48108259

    https://www.kancloud.cn/guanfuchang/python_selenium/710816