Selenium使用詳解
Selenium是一個自動化測試工具,支援多種瀏覽器。它採用Javascript單元測試工具JSUnit為核心,模擬真實使用者操作,包括瀏覽頁面、點選連結、輸入文字、提交表單、觸發滑鼠事件等等,並且能夠對頁面結果進行種種驗證。也就是說,只要在測試用例中把預期的使用者行為與結果都描述出來,我們就得到了一個可以自動化執行的功能測試套件。(Selenium的核心是Javascript寫的,他和瀏覽器進行通訊,把測試用例的資訊傳送給瀏覽器執行,從而達到自動化測試的目的。)
爬蟲時主要用它來解決JavaScript渲染的問題。
安裝:pip3 install selenium
具體安裝過程(包括瀏覽器驅動)可以看這裡
一、 基本用法
from selenium import webdriver #瀏覽器驅動物件
from selenium.webdriver.common.keys import Keys #下方的Keys需要定義
from selenium.webdriver.support.wait import WebDriverWait #下方的WebDriverWait需要定義
from selenium.webdriver.support import expected_conditions as EC #下方的EC需要定義
from selenium.webdriver.common. by import By #下方的By也需要定義
browser = webdriver.Chrome() #聲明瞭一個瀏覽器物件,可以用.後面加上一個瀏覽器的名稱,也可以不新增環境變數在括號內新增路徑亦可
try:
browser.get("https://www.baidu.com/") #傳入一個url,效果為跳出一個瀏覽器訪問百度這個網址
input = browser.find_element_by_id('kw') #找出id為kw的元素
input.send_keys('Python') #向這些元素髮送一些鍵,比如說敲入Python。這就是模擬了在百度的輸入框中輸入Python的動作。
input.send_keys(Keys.ENTER) #敲入回車,確定輸入內容進入網頁
wait = WebDriverWait(browser,10) #呼叫等待
wait.until(EC.presence_of_element_located((By.ID,'content_left'))) #等待id為content_left的元素被加載出來
print(browser.current_url) #打印出當前的URL
print(browser.get_cookies())#再把cookies打印出來
print(browser.page_source)#再把原始碼打印出來
finally:
browser.close() #關掉瀏覽器
結果打印出三個內容,略密集,這裡就不展示了。
二、宣告瀏覽器物件
from selenium import webdriver #需要宣告瀏覽器物件必須引入這個包
browser = webdriver.Chrome() #生成一個Chrome瀏覽器物件,需要一個驅動檔案
browser = webdriver.Firefox() #本行及下面三行同上,對應不同的瀏覽器,需要什麼驅動檔案可自查
browser = webdriver.Edge()
browser = webdriver.PhantomJS()
browser = webdriver.Safari()
本文主要用的是Chrome瀏覽器。
三、訪問頁面
from selenium import webdriver #瀏覽器驅動物件
browser = webdriver.Chrome() #生成一個Chrome瀏覽器
browser.get("https://www.taobao.com") #傳入一個url
print(browser.page_source) #把原始碼打印出來
browser.close() #關掉瀏覽器
四、查詢元素
1.查詢單個元素
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("https://www.taobao.com")
input_first = browser.find_element_by_id('q')
#用find_element_by_id來尋找,這個id的名稱為q;用id來選擇元素; 以下的兩個方法與此方法查詢的結果應該一致,都是查詢q
input_second = browser.find_element_by_css_selector('#q')
#用css選擇器來選擇一個查詢元素
input_third = browser.find_element_by_xpath('//*[@id="q"]')
#用xpath選擇器來選擇一個查詢的元素
print(input_first)
print(input_second)
print(input_third)
browser.close()
以上三種查詢元素的方法雖然方法不同但是結果都是相同的,下面會列出查詢元素的其他方法。
- find_element_by_name
- find_element_by_xpath
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector
查詢單個元素(通用版):
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get("https://www.taobao.com")
input_first = browser.find_element(By.ID,'q')
#By後面傳型別,第二個引數就是要查的內容。這就是上面各種方法的一個通用的實現
print(input_first)
browser.close()
2.查詢多個元素
from selenium import webdriver
from selenium.webdriver.common.by import By#這裡匯入By,不能漏掉
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
lis1 = browser.find_elements_by_css_selector('.service-bd li') #多個元素查詢的方法只是比單個元素查詢多了一個s:elements
lis2 = browser.find_elements(By.CSS_SELECTOR,'.service-bd li') #這是另一種寫法
print(lis1)
print(lis2)
browser.close()
可以通過索引從查找出來的多個元素中取出某個元素。
print(lis1[1])
其他查詢多個元素的方法,同樣,比起單個的,都多了一個s:
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector
五、元素互動操作
對獲取的元素呼叫互動方法(輸入、點選等等)
from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q') #搜尋id為q的元素(淘寶的q元素為輸入框)
input.send_keys('iphone') #在q元素中輸入一個iPhone
time.sleep(1) #等待一秒鐘
input.clear() #將這個文字框清空
input.send_keys('iPad') #又再次輸入iPad
button = browser.find_element_by_class_name('btn-search') #查詢btn-search元素
button.click() #調整搜尋結果
六、互動動作
將動作附加到動作鏈中序列執行。
from selenium import webdriver
from selenium.webdriver import ActionChains
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame("iframeResult") #切換到iframeResult,也就是進行拖拽的介面
source = browser.find_element_by_css_selector('#draggable') #獲取拖拽的方塊元素
target = browser.find_element_by_css_selector('#droppable') #獲取目標放開的元素
actions = ActionChains(browser) #宣告一個動作鏈物件
actions.drag_and_drop(source, target) #將source拖拽到target上面
actions.perform() #執行上面的動作
執行以上程式後,瀏覽器會完成一個拖拽的動作。
我們看一下該網頁的原始碼:
由圖可見,兩個物件都有各自的id。我們的程式通過id獲取這兩個物件,並用一個拖拽方法實現了瀏覽器的互動動作。
更多動作查閱文件
七、執行JavaScript
有的動作是沒有API的(比如進度條拖拽),我們可以通過執行JS來實現進度條的拖拽。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
#傳一些Javasctipt語句:
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') #下拉到網頁的最下端
browser.execute_script('alert("To Bottom")') #彈出一個alert提示框雙引號裡面的是內容
執行結果:
八、獲取元素資訊
獲取屬性
from selenium import webdriver
from selenium.webdriver import ActionChains
browser = webdriver.Chrome()
url = "https://www.zhihu.com/explore"
browser.get(url)
logo = browser.find_element_by_id('zh-top-link-logo') #搜尋id為zh-top-link-logo的元素賦值給logo
print(logo) #列印資訊
print(logo.get_attribute('class')) #列印logo裡面的class屬性
獲取文字值
from selenium import webdriver
browser = webdriver.Chrome()
url = "https://www.zhihu.com/explore"
browser.get(url)
input = browser.find_element_by_class_name('zu-top-nav-link') #查詢目標的元素
print(input.text) #打印出元素裡的值
獲取ID、位置、標籤名、大小
from selenium import webdriver
browser = webdriver.Chrome()
url = "https://www.zhihu.com/explore"
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question') #查詢目標的元素
print(input.id) #列印ID
print(input.location) #列印在瀏覽器裡面的位置
print(input.tag_name) #列印標籤名
print(input.size) #在瀏覽器裡面佔多少的畫素大小
九、Frame
有的網頁需要切換frame,如何在父子frame之間切換呢?
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult') #frame()方法用來切換:進入到子Frame的iframeResult裡面
source = browser.find_element_by_css_selector('#draggable') #在子Frame裡面找到這個物件
print(source) #打印出來
try:
logo = browser.find_element_by_class_name('logo') #在子Frame裡面查詢logo元素,如果沒有執行except
except NoSuchElementException:
print('NO LOGO')
browser.switch_to.parent_frame() #parent_frame():切換到外面的Frame
logo = browser.find_element_by_class_name('logo') #查詢logo元素
print(logo) #列印logo元素資訊
print(logo.text) #列印logo元素的文字
十、等待
確保元素完全載入之後再進行操作。
隱式等待
當使用了隱式等待執行測試的時候,如果web沒有在BOM中找到元素,將繼續等待,超出設定時間後則丟擲找不到元素的異常。換句話說,當查詢元素或元素並沒有立即出現的時候,隱式等待將等待一段時間再查詢DOM,預設的時間是0。
from selenium import webdriver
browser = webdriver.Chrome()
browser.implicitly_wait(10) #傳入等待的時間
browser.get("https://www.zhihu.com/explore")
input = browser.find_element_by_class_name('zu-top-add-question') #查詢目標元素
print(input)
顯式等待
指定一個等待條件和一個最長等待時間。程式會在最長等待時間內判斷這個條件是否成立,若不成立則一直等待,成立則立即返回。
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
browser = webdriver.Chrome()
browser.get("https://www.taobao.com/")
wait = WebDriverWait(browser,10) #宣告一個WebDriverWait物件在裡面傳入一個browser等待條件引數,一個最長等待時間引數
input = wait.until(EC.presence_of_element_located((By.ID,'q'))) #利用wait.until方法傳入一些等待的條件,條件的引數是目標元素,獲取輸入框
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search'))) #利用wait.until方法傳入一些等待的條件,獲取按鈕
print(input,button)
各種等待判斷條件
- title_is 標題是某內容
- title_contains 標題包含某內容
- presence_of_element_located 元素加載出,傳入定位元組,如(By.ID,“p”)
- visibility_of_element_presence_of_element_located 元素可見,傳入定位元組
- visibility_of 可見,傳入元素物件
- presence_of_all_elements_located 所有元素加載出
- text_to_be_present_in_element 某個元素文字包含某文字
- text_to_be_oresent_in_element_value 某個元素值包含某文字
- frame_to_be_available_and_switch_to_it feame載入並切換
- invisibility_of_element_located 元素不可見
- element_to_be_clickable 元素可點選
- staleness_of 判斷一個元素是否仍在DOM,可判斷頁面是否已經重新整理
- element_to_be_selected 元素可選擇,傳元素物件
- element_located_to_be_selected 元素可選擇,傳入定位元組
- element_selection_state_to_be 傳入元素物件以及狀態,相等返回True,否則返回False
- element_located_selection_state_to_be 傳入定位元組以及狀態,相等返回True,否則返回False
- alert_is_present 是否出現Alert
十一、前進後退
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("https://www.baidu.com/")
browser.get("https://www.taobao.com/")
time.sleep(10) #睡眠一秒
browser.back() #後退一步
time.sleep(10) #睡眠一秒
browser.forward() #前進一步
browser.close()
十二、Cookies
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies()) #列印知乎的cookies
browser.add_cookie({'name':'name','domain':'www.zhihu.com','value':'germey'}) #呼叫一個add_cookie方法把設定好的cookie加進入
print(browser.get_cookies()) #列印一下cookies
browser.delete_all_cookies() #把所有的cookies清空
print(browser.get_cookies()) #再次列印一下cookies
十三、選項卡管理
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()') #執行execute_script(JS)方法開啟一個新的選項卡
print(browser.window_handles) #列印返回一個所有視窗的引用
browser.switch_to_window(browser.window_handles[1]) #呼叫switch_to_window方法切換到第二個選項卡
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to_window(browser.window_handles[0]) #再切換到第一個選項卡
browser.get('https://python.org')
十四、異常處理
#下面是錯誤異常程式碼的例項
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.find_element_by_id('hello')#找一個不存在的元素
這段程式會出現異常。
#異常的正確處理機制
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException
browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com')
except TimeoutException: #超時異常
print('Time Out')
try:
browser.find_element_by_id('hello')
except NoSuchElementException: #找不存在的元素異常
print('No Element')
finally:
browser.close()
報錯:找不到元素。