Selenium
Selenium是一個(gè)Web的自動(dòng)化測(cè)試工具,最初是為網(wǎng)站自動(dòng)化測(cè)試而開(kāi)發(fā)的豹爹,類(lèi)型像我們玩游戲用的按鍵精靈,可以按指定的命令自動(dòng)操作,不同是Selenium 可以直接運(yùn)行在瀏覽器上辆脸,它支持所有主流的瀏覽器(包括PhantomJS這些無(wú)界面的瀏覽器)。
Selenium 可以根據(jù)我們的指令螃诅,讓瀏覽器自動(dòng)加載頁(yè)面啡氢,獲取需要的數(shù)據(jù),甚至頁(yè)面截屏术裸,或者判斷網(wǎng)站上某些動(dòng)作是否發(fā)生倘是。
可以從 PyPI 網(wǎng)站下載 Selenium庫(kù)https://pypi.python.org/simple/selenium ,也可以用 第三方管理器 pip用命令安裝:
pip install selenium
Selenium 官方參考文檔:http://selenium-python.readthedocs.io/index.html
快速入門(mén)
Selenium 庫(kù)里有個(gè)叫 WebDriver 的 API袭艺。WebDriver 有點(diǎn)兒像可以加載網(wǎng)站的瀏覽器搀崭,但是它也可以像 BeautifulSoup 或者其他 Selector 對(duì)象一樣用來(lái)查找頁(yè)面元素,與頁(yè)面上的元素進(jìn)行交互 (發(fā)送文本猾编、點(diǎn)擊等)瘤睹,以及執(zhí)行其他動(dòng)作來(lái)運(yùn)行網(wǎng)絡(luò)爬蟲(chóng)升敲。
# 導(dǎo)入 webdriver
from selenium import webdriver
# 要想調(diào)用鍵盤(pán)按鍵操作需要引入keys包
from selenium.webdriver.common.keys import Keys
# 調(diào)用環(huán)境變量指定的PhantomJS瀏覽器創(chuàng)建瀏覽器對(duì)象
driver = webdriver.PhantomJS()
# 如果沒(méi)有在環(huán)境變量指定PhantomJS位置
# driver = webdriver.PhantomJS(executable_path="./phantomjs"))
# get方法會(huì)一直等到頁(yè)面被完全加載,然后才會(huì)繼續(xù)程序轰传,通常測(cè)試會(huì)在這里選擇 time.sleep(2)
driver.get("http://www.baidu.com/")
# 獲取頁(yè)面名為 wrapper的id標(biāo)簽的文本內(nèi)容
data = driver.find_element_by_id("wrapper").text
# 打印數(shù)據(jù)內(nèi)容
print data
# 打印頁(yè)面標(biāo)題 "百度一下驴党,你就知道"
print driver.title
# 生成當(dāng)前頁(yè)面快照并保存
driver.save_screenshot("baidu.png")
# id="kw"是百度搜索輸入框,輸入字符串"長(zhǎng)城"
driver.find_element_by_id("kw").send_keys(u"馬云")
# id="su"是百度搜索按鈕绸吸,click() 是模擬點(diǎn)擊
driver.find_element_by_id("su").click()
# 獲取新的頁(yè)面快照
driver.save_screenshot("馬云.png")
# 打印網(wǎng)頁(yè)渲染后的源代碼
print driver.page_source
# 獲取當(dāng)前頁(yè)面Cookie
print driver.get_cookies()
# ctrl+a 全選輸入框內(nèi)容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a')
# ctrl+x 剪切輸入框內(nèi)容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x')
# 輸入框重新輸入內(nèi)容
driver.find_element_by_id("kw").send_keys(u"王健林")
# 模擬Enter回車(chē)鍵
driver.find_element_by_id("su").send_keys(Keys.RETURN)
# 清除輸入框內(nèi)容
driver.find_element_by_id("kw").clear()
# 生成新的頁(yè)面快照
driver.save_screenshot("王健林.png")
# 獲取當(dāng)前url
print driver.current_url
# 關(guān)閉當(dāng)前頁(yè)面鼻弧,如果只有一個(gè)頁(yè)面,會(huì)關(guān)閉瀏覽器
# driver.close()
# 關(guān)閉瀏覽器
driver.quit()
頁(yè)面操作
Selenium 的 WebDriver提供了各種方法來(lái)尋找元素锦茁,假設(shè)下面有一個(gè)表單輸入框:
<input type="text" name="user-name" id="passwd-id" />
那么:
# 獲取id標(biāo)簽值
element = driver.find_element_by_id("passwd-id")
# 獲取name標(biāo)簽值
element = driver.find_element_by_name("user-name")
# 獲取標(biāo)簽名值
element = driver.find_elements_by_tag_name("input")
# 也可以通過(guò)XPath來(lái)匹配
element = driver.find_element_by_xpath("http://input[@id='passwd-id']")
定位UI元素 (WebElements)
關(guān)于元素的選取攘轩,有如下的API 單個(gè)元素選取
find_element_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_class_name
find_elements_by_css_selector
頁(yè)面等待
注意:這是非常重要的一部分!码俩!
現(xiàn)在的網(wǎng)頁(yè)越來(lái)越多采用了 Ajax 技術(shù)度帮,這樣程序便不能確定何時(shí)某個(gè)元素完全加載出來(lái)了。如果實(shí)際頁(yè)面等待時(shí)間過(guò)長(zhǎng)導(dǎo)致某個(gè)dom元素還沒(méi)出來(lái)稿存,但是你的代碼直接使用了這個(gè)WebElement笨篷,那么就會(huì)拋出NullPointer的異常。
為了避免這種元素定位困難而且會(huì)提高產(chǎn)生 ElementNotVisibleException 的概率瓣履。所以 Selenium 提供了兩種等待方式率翅,一種是隱式等待,一種是顯式等待袖迎。
隱式等待是等待特定的時(shí)間冕臭,顯式等待是指定某一條件直到這個(gè)條件成立時(shí)繼續(xù)執(zhí)行。
顯式等待
顯式等待指定某個(gè)條件燕锥,然后設(shè)置最長(zhǎng)等待時(shí)間辜贵。如果在這個(gè)時(shí)間還沒(méi)有找到元素,那么便會(huì)拋出異常了归形。
from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 庫(kù)托慨,負(fù)責(zé)循環(huán)等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 類(lèi),負(fù)責(zé)條件出發(fā)
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
# 頁(yè)面一直循環(huán)暇榴,直到 id="myDynamicElement" 出現(xiàn)
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
如果不寫(xiě)參數(shù)厚棵,程序默認(rèn)會(huì) 0.5s 調(diào)用一次來(lái)查看元素是否已經(jīng)生成,如果本來(lái)元素就是存在的蔼紧,那么會(huì)立即返回窟感。
下面是一些內(nèi)置的等待條件,你可以直接調(diào)用這些條件歉井,而不用自己寫(xiě)某些等待條件了柿祈。
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
隱式等待
隱式等待比較簡(jiǎn)單,就是簡(jiǎn)單地設(shè)置一個(gè)等待時(shí)間,單位為秒躏嚎。
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")