Selenium 簡介
Selenium是一個自動化測試工具,利用它可以驅動瀏覽器執行特定的操作例如點擊、下拉等操作。同事它還能夠獲取瀏覽器當前呈現的頁面的源代碼,即可以做到可見可爬。這對於一些JavaScript渲染的頁面我就就可以使用它進行爬取,而不用去分析后台接口參數。#應用:(以google瀏覽器為例))安裝selenium並且將google驅動chromedirver.exe程序與python代碼文件的放置在同一個目錄中,即可使用selenium驅動google瀏覽器.以下為一個簡單示例:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait #聲明瀏覽器對象(也可以是其他瀏覽器:火狐、IE等) browser = webdriver.Chrome() try: #訪問頁面 browser.get('https://www.baidu.com') input = browser.find_element_by_id('kw') input.send_keys('python') input.send_keys(Keys.ENTER) wait = WebDriverWait(browser,10) wait.until(EC.presence_of_element_located((By.ID,'content_left'))) print(browser.current_url) print(browser.get_cookies()) print(browser.page_source) finally: browser.close() 結果(輸出當前url,源代碼,cookies) .............................................................................................省略 <script> if(bds.comm.supportis){ window.__restart_confirm_timeout=true; window.__confirm_timeout=8000; window.__disable_is_guide=true; window.__disable_swap_to_empty=true; } initPreload({ 'isui':true, 'index_form':"#form", 'index_kw':"#kw", 'result_form':"#form", 'result_kw':"#kw" }); </script> <script> if(navigator.cookieEnabled){ document.cookie="NOJS=;expires=Sat, 01 Jan 2000 00:00:00 GMT"; } </script> </body></html>
Selenium聲明瀏覽器對象
from selenium import webdriver #聲明谷歌瀏覽器對象 browser = webdriver.Chrome() #聲明火狐瀏覽器對象 browser = webdriver.Firefox() browser = webdriver.Edge() browser = webdriver.PhantomJS() browser =webdriver.Safari()
Selenium訪問頁面
from selenium import webdriver browser = webdriver.Chrome() #訪問淘寶網頁面獲取網頁原代碼 browser.get('https://www.taobao.com') #獲取網頁原代碼 print(browser.page_source) #關閉瀏覽器 browser.close()
Selenium查找節點
1.單節點查找
單個節點查找find_element()方法
常見方法有:
- find_element_by_id()
- 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_css_selector()
或
find_element()傳入兩個參數查找方式By和值,例如:
find_element(By.ID,id)
*取以淘寶搜索框網頁為例 <input id="q" name="q" aria-label="請輸入搜索文字" accesskey="s" autofocus="autofocus" autocomplete="off" class="search-combobox-input" aria-haspopup="true" aria-combobox="list" role="combobox" x-webkit-grammar="builtin:translate" tabindex="0"> from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') #根據id獲取淘寶搜索框 input_first = browser.find_element_by_id('q') #根據css選擇器獲取 input_second = browser.find_element_by_css_selector('#q') #根據xpath獲取 input_third = browser.find_element_by_xpath('//*[@id="q"]') print(input_first,input_second,input_third) browser.close() 結果(三個結果一致) <selenium.webdriver.remote.webelement.WebElement (session="2c84a22fc9d5113f9b53256945f72454", element="0.9638255071470887-1")> <selenium.webdriver.remote.webelement.WebElement (session="2c84a22fc9d5113f9b53256945f72454", element="0.9638255071470887-1")> <selenium.webdriver.remote.webelement.WebElement (session="2c84a22fc9d5113f9b53256945f72454", element="0.9638255071470887-1")>
2.多節點查找
多個節點查找find_elements()方法
- find_elements_by_id()
- 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_css_selector()
或
find_elements()傳入兩個參數查找方式By和值,例如:
find_element(By.ID,id)
*以淘寶導航欄為例 from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.taobao.com') lis = browser.find_elements_by_css_selector('.service-bd li') 或者以下方法 Liss = browser.find_elements(By.CSS_SELECTOR,’.server-bd li’)#結果一致 print(lis) browser.close() 結果 [<selenium.webdriver.remote.webelement.WebElement (session="89a7ea4bb337fc1f8976d6593615d13d", element="0.7879413394489616-1")>...<selenium.webdriver.remote.webelement.WebElement (session="89a7ea4bb337fc1f8976d6593615d13d", element="0.7879413394489616-16")>]
節點交互,常用的有以下幾個:
- 輸入文字用send_keys()方法
- 清空文字用clear()方法
- 點擊按鈕用click()方法
from selenium import webdriver import time browser = webdriver.Chrome() browser.get('https://www.taobao.com') #獲取輸入框 input = browser.find_element_by_id('q') #搜索框輸入iphone,但是未點擊搜索按鈕所以不進行搜索 input.send_keys('iphone') time.sleep(1) #清空輸入框 input.clear() input.send_keys('ipad') #獲取搜索按鈕 button = browser.find_element_by_class_name('btn-search') #點擊按鈕完成搜索任務 button.click() #關閉瀏覽器 browser.close()
動作鏈:例如鼠拖曳和鍵盤按鍵等操作就稱之為動作鏈,它們沒有特定的執行對象
*舉例:實現一個節點的拖曳操作 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') #拖曳的節點 source = browser.find_element_by_css_selector('#draggable') #拖曳的目標點 target = browser.find_element_by_css_selector('#droppable') #聲明ActionChains對象 actions = ActionChains(browser) #action調用以下兩個方法完成拖曳操作 actions.drag_and_drop(source,target) actions.perform() browser.close()
執行JavaScript:例如下拉進度條可以直接模擬運行JavaScript,執行execute_script()方法即可實現
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://www.zhihu.com/explore') #將下拉條拉倒最底部 browser.execute_script('window.scrollTo(0,document.body.scrollHeight)') #彈出alert提示框 browser.execute_script('alert("To Bottom")') browser.close()
獲取節點信息(包括屬性,文本以及id位置標簽名和大小)
*獲取屬性 from selenium import webdriver browser = webdriver.Chrome() url = 'https://www.zhihu.com/explore' browser.get(url) #獲取提問按鈕 logo = browser.find_element_by_id('zh-top-link-logo') print(logo) #打印屬性 print(logo.get_attribute('class')) browser.close() 結果 <selenium.webdriver.remote.webelement.WebElement (session="52975bfa983727a2a7f26b9972c414a2", element="0.9714708708818114-1")> zu-top-link-logo *獲取文本值 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.text) browser.close() 結果 提問
獲取id、位置、標簽名、和大小
*通過id,location、tag_name、size屬性獲取對應的值 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') #獲取id值 print(input.id) #獲取位置 print(input.location) #獲取標簽名 print(input.tag_name) #獲取大小 print(input.size) browser.close() 結果 0.8772617338808859-1 {'x': 760, 'y': 7} button {'height': 32, 'width': 66}
切換Frame:網頁中有一種節點叫做iframe,也就是子Frame,相當於頁面的子頁面,結構和外部網頁完全一致。Selenium默認打開后是在父級Frame里面操作,而此時如果頁面中還有子Frame,則是不能夠獲取子Frame里面的節點的。則需要使用switch_to_.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) #通過switch_to.frame()切換到子頁面Frame里面 browser.switch_to.frame('iframeResult') try: #獲取子Frame里面的logo節點 logo = browser.find_element_by_class_name('logo') #若不存在打印No Logo except NoSuchElementException: print('No Logo') #通過switch_to_.parent_frame切回父級Frame browser.switch_to.parent_frame() #重新獲取logo節點 logo = browser.find_element_by_class_name('logo') print(logo) print(logo.text) 結果 No Logo <selenium.webdriver.remote.webelement.WebElement (session="342ed5d025ac85c06d872fdf337edc82", element="0.12105089091907728-2")> RUNOOB.COM
延時等待:
selenium中get()方法會在網頁加載結束后結束執行,此時如果要獲取page_source,可能並不是瀏覽器完全加載完成的頁面,如果某些頁面有額外的Ajax請求,我們在網頁源代碼中不一定能成功獲取,所以需要等待一定的時間從而確保頁面加載出來,而等待又分為隱式等待和和顯式等待。
- 隱式等待::當時用隱式等待執行測試的時候,若Selenium沒有在DOM中找到節點,將繼續等待,超出設定時間后,則會拋出找不到的節點的異常,即當查找節點而節點並沒有立即出現的時候,隱式等待將等待一段時間在查找DOM,默認時間為0
- 顯式等待:指定要查找的節點,然后指定一個最長的等待時間。若在規定的時間內加載出來這個節點,就返回查找的節點,若到了規定時間沒有加載出來這個節點則會拋出超時異常。
隱式等待
from selenium import webdriver browser = webdriver.Chrome() #調用implicitly_wait()方法實現隱式等待 browser.implicitly_wait(10) browser.get('https://www.zhihu.com/explore') input = browser.find_element_by_class_name('zu-top-add-question') print(input) 結果 <selenium.webdriver.remote.webelement.WebElement (session="9bc5b8f1ae5203fd98654d854b8b70e6", element="0.6674161481100129-1")>
顯式等待條件
等待條件 含義
title_is 標題是某內容
title_contains 標題包含某內容
presence_of_element_located 節點加載出來,傳入定位元組,如(By.ID,’p’)
visibility_of_element_located 節點可見,傳入定位元組
visibility_of 可見,傳入節點對象
presence_of_all_elements_located 所有節點加載出來
text_to_be_present_in_element 某個節點文本包含某個文字
text_to_be_present_in_element_value 某個節點值包含某文字
frame_to_be_available_and_switch_to_it 加載並切換
invisibility_of_element_located 節點不可見
element_to_be_clickable 節點可點擊
staleness_of 判斷一個節點是否仍然在DOM,可判斷頁面是否已經刷新
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') #創建WebDriverWait對象,指定最長等待時間 10秒 wait = WebDriverWait(browser,10) #調用until()方法傳入等待條件(條件為id為q的節點出現10秒內是否出現) input = wait.until(EC.presence_of_element_located((By.ID, 'q'))) #查找CSS選擇器為.btn-serch的按鈕,若在10秒內是可點擊的,則成功加載出來 button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search'))) print(input,button) browser.close() 結果 <selenium.webdriver.remote.webelement.WebElement (session="c8d488bc04ef5ad442cab51e8547dc34", element="0.8244517500943758-1")> <selenium.webdriver.remote.webelement.WebElement (session="c8d488bc04ef5ad442cab51e8547dc34", element="0.8244517500943758-2")>
前進和后退selenium
*back()方法后退,forward方法前進
import time
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(1)
browser.forward()
browser.close()
Cookies
*使用selenium可以方便的對cookies進行獲取、添加、刪除等操作
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
#獲取所有cookies
print(browser.get_cookies())
#添加cookies
browser.add_cookie({'name':'name','domain':'www.zhihu.com','value':'germey'})
print(browser.get_cookies())
#刪除所有cookies
browser.delete_all_cookies()
#重新獲取結果為空
print(browser.get_cookies())
browser.close()
選項卡管理
*當我們在訪問網頁的時候會開啟一個選項卡,可以使用selenuim對選項卡進行操作
import time
from selenium import webdriver
browser = webdriver.Chrome()
#訪問百度網頁
browser.get('https://www.baidu.com')
#開啟一個新的選項卡
browser.execute_script('window.open()')
#調用window_handles屬性獲取當前開啟的所有選項卡
print(browser.window_handles)
#調用switch_to_window()方法切換到第二個選項卡
browser.switch_to_window(browser.window_handles[1])
browser.get('https://www.taobao.com')
time.sleep(1)
#調用switch_to_window()方法切換到第一個選項卡
browser.switch_to_window(browser.window_handles[0])
browser.get('https://python.org')
結果
['CDwindow-E4ECA535D3501ED974B9B9E0AD36995B', 'CDwindow-C362F44E7078475E2676DD6C5DF455DF']
異常處理
*在使用selenium的過程中難免會遇到一些錯誤,一旦出現錯誤程序便不會在運行了,而我們可以使用try excep語句來捕獲各種異常
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()
結果
No Element
