selenium是一個用於web應用程序測試工具,selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣,支持的瀏覽器包括IE(7,8,9,10,11),mozilla firefox,safari,google chrom,opera等,可使用java,python等多種語言編寫用例腳本。
Selenium Python綁定提供了一個簡單的API,可以使用Selenium WebDriver編寫功能/驗收測試。通過Selenium Python API,您可以直觀地訪問Selenium WebDriver的所有功能。
Selenium Python綁定提供了一個方便的API來訪問Selenium WebDrivers,如Firefox,Ie,Chrome,Remote等。目前支持的Python版本是2.7,3.5及更高版本
1、selenium安裝配置
pip安裝:
pip install selenium
wheel安裝:
#下載wheel安裝文件:https://pypi.python.org/pypi/selenium/#downloads pip install selenium-3.13.0-py2.py3-none-any.whl
chrome瀏覽器支持的chromeDriver驅動配置:
注意:此前必須安裝好chrome瀏覽器
chromedriver下載地址:https://sites.google.com/a/chromium.org/chromedriver/downloads
首先查看chrome瀏覽器版本,然后選定支持瀏覽器版本的chromDriver選擇適合的平台包進行下載,下載完后需要配置環境:
在windows系統中可以將chromedriver.exe文件直接拖到python的scripts目錄中即可,也可以將路徑加入到環境變量中。
在linux下需要將可執行文件配置到環境變量或將文件移動到屬於環境變量的目錄中
驗證安裝是否成功,可執行命令chromedriver,如果可以看到chromeDriver的版本號說明安裝成功
使用python腳本測試:
from selenium import webdriver browser=webdriver.Chrome() #如果能彈出一個空白的chrome瀏覽器頁面,說明配置成功
其他瀏覽器的驅動安裝配置一樣,附上其他瀏覽器的驅動下載鏈接地址:
Firefox:https://github.com/mozilla/geckodriver/releases
safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/
edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
我們還可以使用phantomJS一個無界面的webkit瀏覽器引擎,它原生支持多種web標准:DOM操作,CSS選擇器,JSON,Canvas以及SVG
下載地址:http://phantomjs.org/download.html
下載完成后,將PhantomJS可執行文件所在的路徑配置到環境變量中,如在windows下降下載的文件解壓之后打開會看到一個bin文件夾,里面包含一個可執行文件phantomjs.exe,我們需要將它直接放在配置好的環境變量路徑下或者將它所在的路徑配置到環境變量里,或直接將它復制到python的scripts文件夾下
測試安裝:
(virtualenv-36) C:\Users\Administrator\PycharmProjects\untitled\pachong>phantomjs -v 2.1.1 #在python的terminal環境下執行命令phantomjs -v,如果能打印版本信息說明安裝成功
Selenium支持PhantomJS,不過phantomJS官方說明已不再更新了,在selenium中使用phantomJS將彈出警告信息,建議使用chrome或firefox無頭版,下面將重點介紹chrome和firefox
2、Selenium的基本使用
(1)聲明瀏覽器對象
Selenium支持很多瀏覽器包括chrome、Firefox、Edge、Safari等,各瀏覽器初始化對象方法:
from selenium import webdriver #browser=webdriver.Firefox() browser=webdriver.Chrome() #browser=webdriver.Edge() #browser=webdriver.Safari() print(type(browser)) #返回的是一個WebDriver對象 <class 'selenium.webdriver.chrome.webdriver.WebDriver'>
WebDriver對象的方法和屬性:(獲取節點方法在后續介紹)
- add_cookie(cookie_dict): 為當前會話添加一個cookie,為字典類型
- back(): 在瀏覽器歷史記錄中后退一步
- forward(): 在瀏覽器歷史上前進一步
- close(): 關閉當前窗口
- create_web_element(element_id): 使用指定的id創建Web元素
- delete_all_cookies(): 刪除會話范圍內的所有cookie
- delete_cookie(name): 刪除具有給定名稱的單個cookie
- execute(driver_command,params=None): 發送command執行的命令
- execute_async_script(script,*args): 異步執行當前窗口或框架中的JavaScript
- execute_script(script,*args): 同步執行當前窗口或框架中的JavaScript
from selenium import webdriver driver=webdriver.Chrome() driver.get('https://www.baidu.com') driver.execute_script("alert('are you sure');") #它基本可以實現JavaScript的所有功能
- fullscreen_window():調用窗口管理器特定的全屏操作
- get(url):在當前瀏覽器會話中加載網頁
- get_cookie(name):按名稱獲取單個cookie
- get_cookies():返回一組字典的cookies
- get_log(log_type):獲取給定日志類型的日志
- get_screenshot_as_base64():獲取當前窗口的屏幕截圖,作為base64編碼的字符串
- get_screenshot_as_file(filename):將當前窗口中的截屏保存為png圖形
- get_screenshot_as_png():獲取當前窗口的屏幕截圖作為二進制數據
- get_window_position(windowhandle='current'):獲取當前窗口的x,y位置
- get_window_rect():獲取窗口的x,y坐標以及當前窗口的高度和寬度
- get_window_size():獲取當前窗口的高度和寬度
- maximize_window():最大化webdriver正在使用的當前窗口
- minimize_window():最小化當前webdricer使用窗口
- quit():退出驅動程序並關閉每個關聯的窗口
- refresh():刷新當前頁面
- save_screenshot(filename):將當前窗口的屏幕截圖保存為PNG圖形文件
- set_page_load_timeout(time_to_wait):設置等待頁面加載完成的時間
- set_script_timeout(time_to_wait):設置腳本在執行期間等待的時間
- set_window_position(x,y,windowHandle='current'):設置當前窗口的x,y位置
- set_window_rect(x=None,y=None,width=None,height=None):設置窗口的x,y坐標以及當前窗口的高度和寬度
- set_window_size(width,height,windowHandle='current'):設置當前窗口的高度和寬度
- current_url:獲取當前頁面的URL
- current_window_handle:返回當前窗口的句柄
- desired_capabilities:返回驅動程序當前使用的所需功能
- log_types:獲取可用日志類型的列表
- name:返回此實例的基礎瀏覽器的名稱
- page_source:獲取當前頁面的源碼
- switch_to:將焦點切換到所有選項的對象上driver.switch_to.alert
- title:返回當前頁面的標題
- window_handles:返回當前會話中所有窗口的句柄
from selenium import webdriver browser=webdriver.Chrome() browser.get('http://selenium-python.readthedocs.io') browser.execute_script('window.open("https://www.baidu.com");') #在標簽頁打開URL browser.execute_script('window.open("https://www.taobao.com");') browser.back() #后退到前一個頁面 browser.set_page_load_timeout(5) browser.forward() #前進到下一個頁面 print(browser.name) print(browser.title) print(browser.current_url) print(browser.current_window_handle) print(browser.get_cookies()) print(type(browser)) # chrome Selenium with Python — Selenium Python Bindings 2 documentation http://selenium-python.readthedocs.io/ CDwindow-243FD31239F20FCC0195DD522A60A0DA [{'domain': '.readthedocs.io', 'expiry': 1530766561, 'httpOnly': False, 'name': '_gid', 'path': '/', 'secure': False, 'value': 'GA1.2.1126774326.1530680157'}, {'domain': '.readthedocs.io', 'expiry': 1593752161, 'httpOnly': False, 'name': '_ga', 'path': '/', 'secure': False, 'value': 'GA1.2.2096958532.1530680157'}, {'domain': '.readthedocs.io', 'expiry': 1530680217, 'httpOnly': False, 'name': '_gat_rtfd', 'path': '/', 'secure': False, 'value': '1'}] <class 'selenium.webdriver.chrome.webdriver.WebDriver'>
獲取頁面截圖:
from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.python.org') driver.save_screenshot('screenshot.png') #保持頁面截圖到當前路徑 driver.quit()
將頁面滾動到底部:
from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.python.org') #通過DOM中的window對象的scrollTo方法,將窗口位置滾動到指定位置,document.body.scrollHeight返回整個body的高度,所以頁面將滾動到頁面底部 driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")
cookies操作:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 16:19 # @Author : Py.qi # @File : test7.py # @Software: PyCharm from selenium import webdriver driver=webdriver.Chrome() driver.get('https://www.baidu.com') print(driver.get_cookies()) #獲取所有cookies driver.add_cookie({'name':'name','domain':'www.baidu.com','value':'germey'}) #添加cookie print(driver.get_cookies()) driver.delete_all_cookies() print(driver.get_cookies())
(2)定位元素
class selenium.webdriver.common.by.By
有各種策略來定位頁面中的元素。你可以使用最適合你的情況。Selenium提供了以下方法來定位頁面中的元素:
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_class_name
find_element_by_css_selector
要查找多個元素(這些方法將返回一個列表):
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
除了上面給出的公共方法之外,還有兩個私有方法可能對頁面對象中的定位器有用。這些是兩個私有方法:find_element和find_elements
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:03 # @Author : Py.qi # @File : test2.py # @Software: PyCharm from selenium import webdriver from selenium.webdriver.common.by import By driver=webdriver.Chrome() driver.get('http://selenium-python.readthedocs.io/locating-elements.html#locating-elements') data=driver.find_element(By.CLASS_NAME,'simple') #driver.find_element(By.ID,'IDname') #獲取ID標簽定位元素 #driver.find_element(By.CSS_SELECTOR,'cssname')#CSS選擇器定位元素 #driver.find_element(By.LINK_TEXT,'linktext') #鏈接文本定位元素 #driver.find_element(By.PARTIAL_LINK_TEXT,'linktext') #部分鏈接文件定位元素 #driver.find_element(By.NAME,'name') #屬性名定位元素 #driver.find_element(By.TAG_NAME,'tagname') #標簽名定位元素 print(data.text) #打印元素文本內容 # 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_class_name find_element_by_css_selector
#如獲取多個,可是使用: data=driver.find_elements(By.CLASS_NAME,'simple')
除了使用上面的方法外,還可以使用更細致的方法定位元素:
通過Id定位:
當您知道元素的id屬性時使用此選項。使用此策略,將返回id屬性值與該位置匹配的第一個元素,如使用find_elements_by_id將返回多個匹配的元素。如果沒有元素具有匹配的id 屬性,NoSuchElementException則會引發
driver.find_element_by_id('idname') driver.find_elements_by_id('idname')
按名稱定位:
當您知道元素的name屬性時,請使用此選項。使用此策略,將返回名稱屬性值與位置匹配的第一個元素,如使用find_elements_by_name將返回多個匹配的元素。如果沒有元素具有匹配的name 屬性,NoSuchElementException則將引發
driver.find_element_by_name('name') driver.find_elements_by_name('name')
通過XPath定位:
XPath是用於在XML文檔中定位節點的語言。由於HTML可以是XML(XHTML)的實現,因此Selenium用戶可以利用這種強大的語言來定位其Web應用程序中的元素。XPath擴展了通過id或name屬性定位的簡單方法,並打開了各種新的可能性,例如在頁面上查找第三個復選框。
使用XPath的主要原因之一是當您沒有適合您要查找的元素的id或name屬性時。您可以使用XPath以絕對術語或相對於具有id或name屬性的元素來定位元素。XPath定位器也可以用來通過id和name之外的屬性指定元素。
XPaths包含根(html)中所有元素的位置,因此可能會失敗,只需對應用程序進行最輕微的調整。通過查找具有id或name屬性的附近元素(理想情況下是父元素),可以根據關系找到目標元素。這不太可能改變,可以使您的測試更加健壯
driver.find_element_by_xpath("//from[1]") #查看第一個表單元素 friver.dind_element_by_xpath("//from[@id='loginform']") #查找id為loinform的表單元素
通過鏈接文本查找超鏈接:
當您知道錨標記中使用的鏈接文本時,請使用此選項。使用此策略,將返回鏈接文本值與位置匹配的第一個元素。如果沒有元素具有匹配的鏈接文本屬性,NoSuchElementException則將引發
<HTML> <BODY> <p>你確定要這么做嗎?</ p> <a href="continue.html">繼續</a> <a href="cancel.html">取消</a> </ BODY> <HTML> driver.find_element_by_link_text('繼續) #通過鏈接文本定位到元素
按標簽名稱定位元素:
如果要按標簽名稱查找元素,請使用此選項。使用此策略,將返回具有給定標記名稱的第一個元素。如果沒有元素具有匹配的標記名稱,NoSuchElementException 則將引發
driver.find_element_by_tag_name('h1')
按類名定位元素:
如果要按類屬性名稱定位元素,請使用此選項。使用此策略,將返回具有匹配類屬性名稱的第一個元素。如果沒有元素具有匹配的類屬性名稱,NoSuchElementException則將引發
driver.find_element_by_class_name('content')
通過CSS選擇器定位元素:
當你想通過CSS選擇器語法找到一個元素時使用它。使用此策略,將返回具有匹配的CSS選擇器的第一個元素。如果沒有元素具有匹配的CSS選擇器,NoSuchElementException則會引發
driver.find_element_by_css_selector('p.content')
(3)元素對象(element)
當我們通過上面 的方法定位到元素后返回的對象稱為web元素對象,我們可以對元素對象再進行交互或繼續查找等操作
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:55 # @Author : Py.qi # @File : test3.py # @Software: PyCharm from selenium import webdriver from selenium.webdriver.chrome.options import Options opt=Options() opt.add_argument('headless') driver=webdriver.Chrome(chrome_options=opt) driver.get('http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement') element=driver.find_element_by_id('module-selenium.webdriver.remote.webelement') print(element) print(type(element)) #返回一個webelement對象 <selenium.webdriver.remote.webelement.WebElement (session="dfaee65201abdf5a931306df6e7fe421", element="0.95256057244967-1")> <class 'selenium.webdriver.remote.webelement.WebElement'>
- selenium.webdriver.remote.webelement.WebElement為一個DOM元素,它的方法和屬性包括:
- clear() :清除文本元素
- click() :單擊元素按鈕
- get_attribute(name) :獲取元素的給定屬性的屬性值
- get_property(name) :獲取元素的給定屬性
- is_displayed() :判斷元素是否存在
- is_enable() :判斷元素是否被啟用
- is_selected() :返回元素是否被選中
- screenshot(filename) :將當前元素的屏幕截圖保存到文件
- send_keys() #發送元素值
- submit() :提交表單
- value_of_css_property() :CSS屬性的值
- id :selenium使用的內部ID
- location :元素在可渲染畫布中的位置
- location_once_scrolled_into_view :發現元素在屏幕視圖中的位置
- rect :返回包含元素大小和位置的字典
- screenshot_as_base64 :獲取當前元素的截屏,作為base64編碼的字符串
- size :獲取元素的大小
- tag_name :獲取元素的tagName屬性
- text :獲取元素的文本
與頁面交互,實現輸出文本搜索功能,並打印搜索結果源碼:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/4 13:55 # @Author : Py.qi # @File : test3.py # @Software: PyCharm from selenium import webdriver driver=webdriver.Chrome() driver.get('http://www.cnblogs.com/zhangxinqi/') element=driver.find_element_by_id('q') #獲取輸入框元素 element.send_keys('python3之requests') #發送元素 button=driver.find_element_by_id('btnZzk') #獲取搜索按鈕 button.click() #發送搜索動作 data=driver.page_source print(driver.current_url) #打印URL print(data) print(type(element)) driver.close() # http://zzk-s.cnblogs.com/s?w=blog%3Azhangxinqi%20python3%E4%B9%8Brequests <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <meta charset="utf-8" /> <title> blog:zhangxinqi python3之requests - 博客園找找看</title>......
(4)動作鏈
class selenium.webdriver.common.action_chains.ActionChains(driver)
在上面的實例中我們針對的是某個節點元素的操作,如果要對沒有特定元素的對象操作如鼠標拖拽、鍵盤按鍵等,這些動作就稱為動作鏈,selenium使用ActionChains()類來實現鼠標移動,鼠標按鈕操作,按鍵操作和上下文菜單交互,懸停和拖放等
- click(on_element=None) ——單擊鼠標左鍵
- click_and_hold(on_element=None) ——點擊鼠標左鍵,不松開
- context_click(on_element=None) ——點擊鼠標右鍵
- double_click(on_element=None) ——雙擊鼠標左鍵
- drag_and_drop(source, target) ——拖拽到某個元素然后松開
- drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某個坐標然后松開
- key_down(value, element=None) ——按下某個鍵盤上的鍵
- key_up(value, element=None) ——松開某個鍵
- move_by_offset(xoffset, yoffset) ——鼠標從當前位置移動到某個坐標
- move_to_element(to_element) ——鼠標移動到某個元素
- move_to_element_with_offset(to_element, xoffset, yoffset) ——移動到距某個元素(左上角坐標)多少距離的位置
- perform() ——執行鏈中的所有動作
- release(on_element=None) ——在某個元素位置松開鼠標左鍵
- send_keys(*keys_to_send) ——發送某個鍵到當前焦點的元素
- send_keys_to_element(element, *keys_to_send) ——發送某個鍵到指定元素
將元素拖拽到目標位置:
element = driver.find_element_by_name("source") target = driver.find_element_by_name("target") from selenium.webdriver import ActionChains action_chains = ActionChains(driver) action_chains.drag_and_drop(element, target).perform()
執行鼠標操作的流程:
menu = driver.find_element_by_css_selector(".nav") #獲取element對象 hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") #獲取點擊對象 #創建鼠標對象 actions = ActionChains(driver) #移動鼠標到對象 actions.move_to_element(menu) #點擊對象 actions.click(hidden_submenu) #執行操作 actions.perform()
(5)彈出對話框
class selenium.webdriver.common.alert.Alert(driver)
Alert內置支持處理彈窗對話框,方法:
- accept() :確認彈窗,用法:Alert(driver).appept()
- authenticate(username,password) :將用戶名和密碼發送到authenticated對話框,隱含點擊確定,用法:driver.switch_to.alert.authenticate('username','password')
- dismiss() :取消確認
- send_keys(keysToSend) :將密鑰發送到警報,keysToSend為要發送的文本
- text :獲取Alert的文本
import time from selenium import webdriver from selenium.webdriver.common.alert import Alert driver=webdriver.Chrome() driver.get('https://www.baidu.com') driver.execute_script("alert('確定');") #彈出窗口 time.sleep(2) print(driver.switch_to.alert.text) #獲取alert文本 alert=Alert(driver).accept() #自動點擊確定窗口
(6)鍵盤操作
class selenium.webdriver.common.keys.Keys
selenium提供一個keys包來模擬所有的按鍵操作,下面我們介紹下一些常用的按鍵操作:
- 回車鍵:Keys.ENTER
- 刪除鍵:Keys.BACK_SPACE
- 空格鍵:Keys.SPACE
- 制表鍵:Keys.TAB
- 回退鍵:Keys.ESCAPE
- 刷新鍵:Keys.F5
- 全選(ctrl+A):send_keys(Keys.CONTROL,'a') #組合鍵需要用send_keys方法操作
- 復制(ctrl+C):send_keys(Keys.CONTROL,'c')
- 剪切(ctrl+X):send_keys(Keys.CONTROL,'x')
- 粘貼(ctrl+V):send_keys(Keys.CONTROL,'v')
實現點擊頁面從python的pypi頁面下載selenium源碼包:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 13:05 # @Author : Py.qi # @File : test5.py # @Software: PyCharm import requests from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.action_chains import ActionChains driver=webdriver.Chrome() driver.get('https://pypi.org/') element=driver.find_element_by_id('search') #獲取輸入框 element.send_keys('selenium') #搜索selenium包 element.send_keys(Keys.ENTER) #按回車鍵 element_a=driver.find_element_by_link_text('selenium') #定位selenium包鏈接 ActionChains(driver).move_to_element(element_a).click(element_a).perform() #按左鍵點擊鏈接執行 element_down=driver.find_element_by_link_text('Download files') #定位下載鏈接 ActionChains(driver).move_to_element(element_down).click(element_down).perform() #按左鍵點擊鏈接 element_selenium=driver.find_element_by_link_text('selenium-3.13.0.tar.gz') #定位元素selenium下載包鏈接 data=element_selenium.get_attribute('href') #獲取鏈接地址 with open('selenium-3.13.0.tar.gz','wb') as f: source=requests.get(data).content #請求下載鏈接地址獲取二進制包數據 f.write(source) #寫入數據 f.close() driver.quit()
(7)延時等待
目前,大多數Web應用程序都在使用AJAX技術。當瀏覽器加載頁面時,該頁面中的元素可能以不同的時間間隔加載。這使定位元素變得困難:如果DOM中尚未存在元素,則locate函數將引發ElementNotVisibleException異常。使用等待,我們可以解決這個問題。等待在執行的操作之間提供了一些松弛 - 主要是使用元素定位元素或任何其他操作。
Selenium Webdriver提供兩種類型的等待 - 隱式和顯式。顯式等待使WebDriver等待某個條件發生,然后再繼續執行。在嘗試查找元素時,隱式等待會使WebDriver輪詢DOM一段時間。
顯示等待:
顯示等待是根據定義的代碼,用於在進一步執行代碼之前等待某個條件發送,它提供了一些便捷方法,可以編寫在僅需要等待的代碼上,實現方法需要WebDriverWait與ExpectedCondition結合使用:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 14:41 # @Author : Py.qi # @File : test6.py # @Software: PyCharm 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.Chrome() driver.get('https://www.taobao.com/') wait=WebDriverWait(driver,3) #設置監聽driver等待時間3秒 input=wait.until(EC.presence_of_element_located((By.ID,'q'))) #設置等待條件為id為q的元素加載完成 button=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search'))) #設置等待條件為class名為btn-search的元素加載完成 print(input,button)
其他等待條件:
- 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,可判斷頁面是否已經刷新
- 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 :是否出現警告
隱式等待:
當使用隱式等待執行測試的時候,如果Selenium沒有在DOM中找到節點,將繼續等待,超出設定時間后,則拋出找不到節點的異常。換句話說,當查找節點而節點並沒有立即出現的時候,隱式等待將等待一段時間再查找DOM,默認的時間是0,調用driver的implicitly_wait()方法實現隱式等待:
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) #隱式等待設置為10等待時間 driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement")
(8)異常處理
所有webdriver代碼中發生的異常:
- selenium.common.exceptions.WebDriverException :webdriver基本異常
- selenium.common.exceptions.UnknownMethodException :請求的命名與URL匹配但該URL方法不匹配
- selenium.common.exceptions.UnexpectedTagNameException :當支持類沒有獲得預期的Web元素時拋出
- selenium.common.exceptions.UnexpectedAlertPresentException :出現意外警報時拋出,通常在預期模式阻止webdriver表單執行任何更多命令時引發
- selenium.common.exceptions.UnableToSetCookieException :當驅動程序無法設置cookie時拋出
- selenium.common.exceptions.TimeoutException :當命令沒有在足夠的時間內完成時拋出
- selenium.common.exceptions.StaleElementReferenceException :當對元素的引用現在“陳舊”時拋出,陳舊意味着該元素不再出現在頁面的DOM上
- selenium.common.exceptions.SessionNotCreatedException :無法創建新會話
- selenium.common.exceptions.ScreenshotException :屏幕截圖錯誤異常
- selenium.common.exceptions.NoSuchWindowException :當不存在要切換的窗口目標時拋出
- selenium.common.exceptions.NoSuchElementException :無法找到元素時拋出
- selenium.common.exceptions.NoSuchCookieException :在當前瀏覽上下文的活動文檔的關聯cookie中找不到與給定路徑名匹配的cookie
- selenium.common.exceptions.NoSuchAttributeException :無法找到元素的屬性時拋出
- selenium.common.exceptions.JavascriptException :執行用戶提供的JavaScript時發生錯誤
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/5 16:19 # @Author : Py.qi # @File : test7.py # @Software: PyCharm from selenium import webdriver from selenium.common.exceptions import NoSuchElementException driver=webdriver.Chrome() driver.get('https://www.baidu.com') try: element=driver.find_element_by_id('test') print(element) except NoSuchElementException as e: print('元素不存在:',e) # 元素不存在: Message: no such element: Unable to locate element: {"method":"id","selector":"test"} (Session info: chrome=67.0.3396.99) (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.10240 x86_64)
(9)實例:抓取淘寶頁面商品信息
#!/usr/bin/env python #coding:utf-8 import re import pymongo from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from urllib.parse import quote from selenium.common.exceptions import WebDriverException from pyquery import PyQuery as pq #鏈接mongodb數據庫 client=pymongo.MongoClient(host='localhost',port=27017) db=client['taobao'] #定義無頭chrome opt=webdriver.ChromeOptions() opt.add_argument('--headless') driver=webdriver.Chrome(chrome_options=opt) #定義頁面等待時間 wait=WebDriverWait(driver,10) #定義搜索商品名 uname='iPad' #搜索商品 def search(): try: url = 'https://s.taobao.com/search?q=' + quote(uname) driver.get(url) total=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.total'))) except TimeoutException: return search() return total.text #實現翻頁商品 def next_page(page): print('正在抓取第{}'.format(page)) try: if page >= 1: input=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > input'))) submit=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit'))) input.clear() input.send_keys(page) submit.click() wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > ul > li.item.active > span'),str(page))) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-itemlist .items .item'))) get_products() except TimeoutException: next_page(page) except WebDriverException as e: print('index_page:',e) #解析商品信息 def get_products(): #print('開始解析頁面...') html = driver.page_source doc = pq(html, parser='html') items = doc('#mainsrp-itemlist .items .item').items() for i in items: product = { 'image': 'https:' + i.find('.pic .img').attr('data-src'), 'price': i.find('.price').text(), 'deal': i.find('.deal-cnt').text(), 'title': i.find('.title').text(), 'shop': i.find('.shop').text(), 'location': i.find('.location').text() } #print(product) save_to_mongo(product) #保存到mongodb def save_to_mongo(result): try: if db['collection_taobao'].insert(result): print('保存到mongodb成功!',result) except Exception: print('保存到mongodb失敗',result) #主函數調用 def main(): try: total=search() total=int(re.compile('(\d+)').search(total).group(1)) for i in range(1,total+1): next_page(i) finally: driver.quit() #執行函數入口 if __name__ == '__main__': main()
抓取頭條圖片:

#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/7/6 11:16 # @Author : Py.qi # @File : toutiao.py # @Software: PyCharm import requests from selenium import webdriver from selenium.webdriver.common.by import By from selenium.common.exceptions import WebDriverException,TimeoutException from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from pyquery import PyQuery as pq import time from PIL import Image from io import BytesIO from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES = True opt=webdriver.ChromeOptions() opt.add_argument('--headless') driver=webdriver.Chrome(chrome_options=opt) wait=WebDriverWait(driver,10) def index_page(url,text): try: driver.get(url) insid=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#rightModule > div.search-wrapper > div > div > div.tt-input.tt-input-group.tt-input-group--append > input'))) insid.clear() insid.send_keys(text) insid.send_keys(Keys.ENTER) driver.switch_to.window(driver.window_handles[1]) images=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'body > div > div.y-box.container > div.y-left.index-middle > div.tabBar > ul > li:nth-child(3)'))) ActionChains(driver).move_to_element(images).click(images).perform() element=driver.find_element_by_id('footer') sum=0 while sum < 8: ActionChains(driver).move_to_element(element).send_keys(Keys.DOWN).perform() time.sleep(1) sum+=1 html=driver.page_source doc=pq(html,parser='html') items=doc('.index-middle .feedBox .sections .articleCard').items() for i in items: #print(i('.title-box a').attr('href')) img_url='https://www.toutiao.com/a' + str(i('.title-box a').attr('href')).split('/')[-2] driver.get(img_url) if driver.title == '404錯誤頁': continue else: wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.bui-box'))) img_source=driver.page_source doc1=pq(img_source,parser='html') excent=doc1('.imageList .image-list .image-item').items() for item in excent: image_url=item('.image-item-inner a').attr('href') image_name='D:\images\\' + image_url.split('/')[-1] + '.jpg' content=requests.get(image_url).content im=Image.open(BytesIO(content)) im.save(image_name) im.close() print('保存圖片成功',image_name) except TimeoutException: print('超時') except WebDriverException: print('driverError') except Exception as e: print(e) def main(): url='https://www.toutiao.com' context='街拍' index_page(url,context) if __name__ == '__main__': main()
其他異常請查看官網文檔:http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions
其他詳細使用方法參考官方文檔:http://selenium-python.readthedocs.io