[TOC]
Install
pip install selenium
selenium 是自動測試工具,支持各種界面式瀏覽器,實際上就是在這些瀏覽器里面安裝一個 selenium 的插件,方便地實現(xiàn) Web 界面測試,即 selenium 支持這些瀏覽器驅(qū)動。PhantomJS 也是一個瀏覽器,selenium 也能夠支持。
Demo
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://www.baidu.com/')
驅(qū)動文件
放在 path 路徑下
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
print driver.page_source
測試用例:
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class PythonOrgSearch(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def test_search_in_python_org(self):
driver = self.driver
driver.get("http://www.python.org")
self.assertIn("Python", driver.title)
elem = driver.find_element_by_name("q")
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
測試用例是繼承了 unittest.TestCase 類,繼承這個類表明這是一個測試類。setUp方法是初始化的方法,這個方法會在每個測試類中自動調(diào)用。每一個測試方法命名都有規(guī)范,必須以 test 開頭,會自動執(zhí)行。最后的 tearDown 方法會在每一個測試方法結(jié)束之后調(diào)用。這相當(dāng)于最后的析構(gòu)方法。在這個方法里寫的是 close 方法,你還可以寫 quit 方法。不過 close 方法相當(dāng)于關(guān)閉了這個 TAB 選項卡,然而 quit 是退出了整個瀏覽器。當(dāng)你只開啟了一個 TAB 選項卡的時候,關(guān)閉的時候也會將整個瀏覽器關(guān)閉。
頁面交互
假如有一個表單輸入框:
<input type="text" name="passwd" id="passwd-id" />
元素選取
單個元素選取:
- 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
還可以用 By 類確定哪種選擇方式:
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, '//button[text()="Some text"]')
driver.find_elements(By.XPATH, '//button')
By 類的一些屬性如下:
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
可以獲取這個元素:
element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_elements_by_tag_name("input")
element = driver.find_element_by_xpath("http://input[@id='passwd-id']")
element = driver.find_element_by_id("q")
element.size() //大小 dict
element.get_attribute("type") //獲取元素屬性
element.is_displayed() //是否可見
element.text //獲取文本信息
driver.current_url //當(dāng)前url
用 xpath 時需要注意,如果有多個元素匹配了 xpath,只會返回第一個匹配的元素。如果沒有找到,會拋出 NoSuchElementException 的異常。
填充表單
向文本輸入內(nèi)容
element.send_keys("some text")
還可以利用 Keys 這個類模擬點擊某個按鍵
element.send_keys("and some", Keys.ARROW_DOWN)
element.clear()
//輸入的文本會被清除
Select 方法
下拉選項卡處理:
element = driver.find_element_by_xpath("http://select[@name='name']")
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
print("Value is: %s" % option.get_attribute("value"))
option.click()
WebDriver 提供更簡單的方法 Select:
from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)
可以根據(jù)索引來選擇,根據(jù)值來選擇,根據(jù)文字來選擇。
全部取消選擇:
select = Select(driver.find_element_by_id('id'))
select.deselect_all()
獲取所有已選選項:
select = Select(driver.find_element_by_xpath("xpath"))
all_selected_options = select.all_selected_options
獲取所有可選選項:
options = select.options
提交表單
driver.find_element_by_id("submit").click()
相當(dāng)于模擬點擊 submit 按鈕提交表單
也可以單獨提交某個元素
element.submit()
WebDriver 會在表單中尋找該元素所在表單,如果發(fā)現(xiàn)該元素沒有被表單包圍,程序會拋出 NoSuchElementException
元素拖拽
指定被拖動的元素和拖動目標(biāo)元素,然后利用 ActionChains 類實現(xiàn)
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()
元素從 source 拖動到 target
頁面窗口切換
一個瀏覽器肯定有很多窗口,所以肯定有方法實現(xiàn)窗口的切換:
driver.switch_to_window("windowName")
另外可以使用 window_handles
方法獲取每個窗口的操作對象:
for handle in driver.window_handles:
driver.switch_to_window(handle)
切換 frame:
driver.switch_to_frame("frameName.0.child")
之后焦點會切換到 name 為 child 的 frame 上
彈窗處理
當(dāng)觸發(fā)了某個事件之后,頁面出現(xiàn)了彈框提示,如何處理呢?
alert = driver.switch_to_alert()
可以獲取彈窗對象
.get_text()
.accept() //點擊確定
.dismiss() //點擊取消
send_keys() //輸入值
歷史紀(jì)錄
前進(jìn)和后臺:
driver.forward()
driver.back()
Cookies處理
給頁面添加 Cookies:
# Go to the correct domain
driver.get("http://www.example.com")
# Now set the cookie. This one's valid for the entire domain
cookie = {'name' : 'foo', 'value' : 'bar'}
driver.add_cookie(cookie)
獲取頁面 Cookies:
# Go to the correct domain
driver.get("http://www.example.com")
# And now output all the available cookies for the current URL
driver.get_cookies()
頁面等待
這是非常重要的一部分,現(xiàn)代網(wǎng)頁越來越多采用 Ajax 技術(shù),這樣程序就不能確定某個元素何時加載完畢,會讓元素定位困難并且報出 ElementNotVisibleException 的概率提高
隱式等待:等待特定的時間
顯式等待:指定某一條件,直到這個條件成立時繼續(xù)執(zhí)行
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
顯式等待
顯式等待指定某個條件,設(shè)置最長等待時間,如果這個時間內(nèi)還沒有找到元素,便會拋出異常
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("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
程序默認(rèn)會 500ms 調(diào)用一次來查看元素是否已經(jīng)生成,如果本來元素就是存在的,那么會立即返回
下面是一些內(nèi)置的等待條件,可以直接調(diào)用這些條件,而不用自己寫某些等待條件了:
title_is
title_contains
presence_of_element_located
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 – it is Displayed and Enabled.
staleness_of
element_to_be_selected
element_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID,'someid')))
隱式等待
隱式等待比較簡單,就是簡單地設(shè)置一個等待時間,單位為秒。
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")
Demo
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = wendriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
Http 協(xié)議分析
GET / HTTP/1.1\r\n
Host: rk-zyk.zx.ga\r\n
Connection: Keep-Alive\r\n
例子
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox()
driver.get('http://www.baidu.com')
driver.maximize_window()
setting = driver.find_element_by_link_text(u'設(shè)置')
ActionChains(driver).move_to_element(setting).perform()
driver.find_element_by_link_text(u'高級搜索'),click()