selenium安裝配置
Python安裝
-
selenium客戶端庫(kù)
# win pip install selenium # mac sudo pip3 install selenium
-
驗(yàn)證是否安裝成功
控制臺(tái)輸入命令pip list
查看列表中是否存在selenium,如果有,則說(shuō)明安裝成功。image
-
-
谷歌瀏覽器驅(qū)動(dòng)chromedriver
notes.txt文件可以查看對(duì)應(yīng)的chrome版本
- 下載地址1-官網(wǎng)
- 下載地址2-第三方
-
確保瀏覽器版本和驅(qū)動(dòng)版本相對(duì)應(yīng)相關(guān)版本查看方法
引自WeiFong
-
將瀏覽器驅(qū)動(dòng)文件(chromedriver.exe)放到環(huán)境變量中配置的路徑內(nèi)
- 如果不放入環(huán)境變量,則每次使用時(shí)需填寫(xiě)瀏覽器驅(qū)動(dòng)文件所在的路徑
- 必須為系統(tǒng)的環(huán)境變量,臨時(shí)設(shè)置的環(huán)境變量無(wú)效
- 快速設(shè)置:mac 可以把瀏覽器驅(qū)動(dòng)文件放到
/usr/local/bin
下 - 快速設(shè)置:win 可以把瀏覽器驅(qū)動(dòng)文件放到
C:\Windows
下
# 在系統(tǒng)環(huán)境變量中 from selenium import webdriver # driver = webdriver.Chrome(chromedriver) driver = webdriver.Chrome() driver.get('https://www.baidu.com/') # 不在系統(tǒng)環(huán)境變量中 from selenium import webdriver test = r'E:/python/chromedriver' driver = webdriver.Chrome(test) driver.get('https://www.baidu.com/')
-
補(bǔ)充:安裝三大瀏覽器驅(qū)動(dòng)(driver)
- chromedriver 下載地址:參考第三點(diǎn)
# 啟動(dòng)谷歌瀏覽器 from selenium import webdriver browser = webdriver.Chrome() browser.get('http://www.baidu.com/')
- Firefox的驅(qū)動(dòng)geckodriver 下載地址:https://github.com/mozilla/geckodriver/releases/
# 啟動(dòng)火狐瀏覽器 from selenium import webdriver browser = webdriver.Firefox() browser.get('http://www.baidu.com/')
- IE的驅(qū)動(dòng)IEdriver 下載地址:http://www.nuget.org/packages/Selenium.WebDriver.IEDriver/
# 啟動(dòng)IE瀏覽器 from selenium import webdriver browser = webdriver.Ie() browser.get('http://www.baidu.com/')
-
簡(jiǎn)單操作方法
- 導(dǎo)入
from selenium import webdriver
- 打開(kāi)瀏覽器
driver = webdriver.Chrome()
- get方法打開(kāi)指定網(wǎng)址
driver.get('https://www.baidu.com/')
- 通過(guò)id獲取元素
element_keyword = find_element_by_id('kw')
- 對(duì)輸入框輸入文字內(nèi)容
element_keyword.send_keys('松勤')
- 對(duì)按鈕進(jìn)行點(diǎn)擊
element_search_button.click()
- 獲取某個(gè)元素的內(nèi)容
one_yuansu.text
- 關(guān)閉瀏覽器
driver.quit()
- 設(shè)置瀏覽器固定寬、高
driver.set_window_size(480,800)
- 控制瀏覽器前進(jìn)、后退:前進(jìn)
driver.forward()
后退driver.back()
- 示例如下:
from selenium import webdriver driver = webdriver.Chrome() #get方法打開(kāi)指定網(wǎng)址 driver.get('https://www.baidu.com/') # 查找到那個(gè)搜索輸入欄網(wǎng)頁(yè)元素,返回一個(gè)表示該元素到WebElement對(duì)象 element_keyword = driver.find_element_by_id('kw') # 輸入字符 element_keyword.send_keys('測(cè)試') # 找到搜素按鈕 element_search_button = driver.find_element_by_id('su') # 點(diǎn)擊該按鈕 element_search_button.click() import time time.sleep(2)# 設(shè)置等待時(shí)間 ret = driver.find_element_by_id('1') # 獲取第一條信息 print(ret.text) # if ret.text.startswith('松勤'): # print('測(cè)試通過(guò)') # else: # print('測(cè)試不通過(guò)') # 退出(關(guān)閉瀏覽器) driver.quit() # 控制臺(tái)輸出效果 測(cè)試_百度百科 測(cè)試英文名Test、Measure;中文拼音cè shì;由中文“測(cè)”與中文“試”兩個(gè)字組成的詞語(yǔ)。是動(dòng)詞、名詞。測(cè)試行為,一般發(fā)生于為檢測(cè)特定的目標(biāo)是否符合標(biāo)準(zhǔn)而采用專用的工具或... 詞語(yǔ) 綜合式測(cè)試 心理測(cè)試 baike.baidu.com/
- 導(dǎo)入
元素選擇之常規(guī)方法
Selenium 選擇、操作web元素01
Selenium 自動(dòng)化主要就是:
- 選擇界面元素
依靠selenium庫(kù)
難點(diǎn)
- 操作界面元素
依靠selenium庫(kù)
- 輸入操作:點(diǎn)擊、輸入文字、拖拽等
- 輸出操作:獲取元素的各種屬性
- 根據(jù)界面上獲取的數(shù)據(jù)進(jìn)行分析和處理
依靠編程語(yǔ)言,例如Python等
難點(diǎn)
選擇元素
- WebDriver:操作整個(gè)瀏覽器和當(dāng)前整個(gè)頁(yè)面
- 當(dāng)前頁(yè)面上的選擇符合查找條件的對(duì)象
- 打開(kāi)網(wǎng)址,回退,前進(jìn),刷新網(wǎng)頁(yè)
- 獲取、改變?yōu)g覽器窗口大小,關(guān)閉瀏覽器,截屏
- 獲取、設(shè)置cookies
- WebElement:操作和對(duì)應(yīng)web元素
- 當(dāng)前web元素的所有子元素里面符合查找條件的對(duì)象
- 操作該web元素,比如
- 點(diǎn)擊元素
- 輸入字符
- 獲取元素坐標(biāo)、尺寸、文本內(nèi)容、其他的屬性信息
通過(guò)id選擇元素
-
id是DOM中唯一標(biāo)志這個(gè)元素的屬性
- 查找效率高
- 寫(xiě)法一:
element = driver.find_element_by_id("kw")
- 寫(xiě)法二:
from selenium.webdriver.common.by import By element = driver.find_element(by=By.ID,value="kw")
沒(méi)有找到id時(shí)將報(bào)錯(cuò)
selenium.common.exceptions.NoSuchElementException
-
沒(méi)有id時(shí),可以通過(guò)根據(jù)上層的id,然后獲取內(nèi)部的源代碼,然后找到相關(guān)信息(str)
當(dāng)開(kāi)發(fā)做一定的變動(dòng)時(shí),此方法就失效了
沒(méi)有id時(shí),使用BeautifulSoup4
詳見(jiàn)后續(xù)內(nèi)容
獲取元素信息
text屬性
顯示該元素在web頁(yè)面顯示出來(lái)的文本內(nèi)容
-
get_attribute方法
非界面值
- 某個(gè)屬性的值
ele.get_attribute('href')
- 該元素對(duì)應(yīng)的html源代碼
ele.get_attribute('outerHTML')
出現(xiàn)問(wèn)題時(shí),將相關(guān)源代碼打印到日志里,以便快速定位問(wèn)題
- 該元素的內(nèi)部部分的html源代碼
ele.get_attribute('innerHTML')
- 某個(gè)屬性的值
Selenium 選擇、操作web元素02
選擇元素的方法
通過(guò)name選擇元素 id是唯一的,name不一定是唯一的
<input name='cheese' type='text'/>
- 返回第一個(gè)找到的元素
如果找不到,拋出異常
# 方法一:
cheese = driver.find_element_by_name('cheese')
# 方法二:
from selenium.webdriver.common.by import By
cheeses = driver.find_emement(By.NAME,'cheese')
# 示例
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
button = driver.find_element_by_name('button')
print(button.text)
# 執(zhí)行結(jié)果
按鈕01
#找不到時(shí)
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
try:
button = driver.find_element_by_name('button4')
print(button.text)
except:
print('未找到')
# 執(zhí)行結(jié)果
未找到
- 返回所有的元素(list)
如果找不到,返回空列表,不拋出異常
# 方法一:
cheese = driver.find_elements_by_name('cheese')
# 方法二:
from selenium.webdriver.common.by import By
cheeses = driver.find_emements(By.NAME,'cheese')
# 示例
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(r'file:///E:/Python/tmp/own/test.html')
button = driver.find_elements_by_name('button')
for a in button:
print(a.text)
# 執(zhí)行結(jié)果
按鈕01
按鈕02
按鈕03
通過(guò)class選擇元素非唯一值,通常用來(lái)選擇多個(gè)元素
- 返回所有的元素(list)
cheeses = driver.find_elements_by_class_name('cheese')
通過(guò)tag名選擇元素
- 如果tag名是唯一的,可以根據(jù)tag名定位
- 如果tag名不是唯一的,返回到是第一個(gè)
frame = driver.find_element_by_tag_name('iframe')
通過(guò)鏈接文本選擇元素
- 對(duì)于鏈接,可以通過(guò)其鏈接文本的內(nèi)容
<a >轉(zhuǎn)到百度</a>
ele = driver.find.element_by_link_text("轉(zhuǎn)到百度")
- 只通過(guò)部分文本去找到該鏈接元素
適用于文本內(nèi)容過(guò)長(zhǎng)時(shí)
ele = driver.find.element_by_partial_link_text(u"百度") # 此處可以不寫(xiě)u,python2中此處的“u”必寫(xiě)
頁(yè)面操作(補(bǔ)充)
查找時(shí)間
- 每半秒查找一次,直到10秒后
driver.implicitly_wait((10))
- 強(qiáng)制睡眠10秒
import time
time.sleep(10)
模擬回車鍵enter的操作
- 使用
\n
方法
from selenium.webdriver.common.keys import Keys
driver.find_element_by_id('toStationText').send_keys('杭州東\n')
- 使用enter方法
from selenium.webdriver.common.keys import Keys
driver.find_element_by_id('toStationText').send_keys('杭州東')
driver.find_element_by_id('toStationText').send_keys(Keys.ENTER) # 模擬鍵盤enter
頁(yè)面交互
WebDriver提供了各種方法來(lái)尋找元素。例如下面有一個(gè)表單輸入框。
<input type="text" name="passwd" id="passwd-id" />
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']")
獲取了元素之后,下一步當(dāng)然就是向文本輸入內(nèi)容了,可以利用下面的方法
element.send_keys("some text")
同樣你還可以利用 Keys 這個(gè)類來(lái)模擬點(diǎn)擊某個(gè)按鍵
element.send_keys("and some", Keys.ARROW_DOWN)
可以用下面的方法來(lái)清除輸入文本的內(nèi)容。
element.clear()
填充表單
元素選擇之BeautifulSoup4
BeautifulSoup4
BS是可以從HTML或XML文件中提取數(shù)據(jù)的庫(kù)
Selenium可以用來(lái)遠(yuǎn)程獲取數(shù)據(jù)
有的時(shí)候,感覺(jué)用Selenium獲取某些元素?cái)?shù)據(jù)不太方便
可以將其父節(jié)點(diǎn)的html獲取回來(lái),利用BS在本地做分析
我們可以將它和selenium兩種技術(shù)融合使用,達(dá)到我們的目的
-
安裝BeautifulSoup4
pip install beautifulsoup4 # pip install beautifulsoup4 -i https://pypi.douban.com/simple/ pip install html5lib
-
常見(jiàn)用法(詳見(jiàn)示例內(nèi)的代碼及注釋)
- 示例及具體方法
# 本例采用的是本地的html with open ('test.html',encoding = 'utf8') as f : html_doc = f.read() # 導(dǎo)入beautifulsoup from bs4 import BeautifulSoup # 指定html5lib來(lái)解析html文檔 soup = BeautifulSoup(html_doc,'html5lib') print(soup.title) # 獲取標(biāo)簽整體內(nèi)容 print(soup.p)# 有多個(gè)時(shí),獲取的是第一個(gè) print(soup.title.name) # 獲取標(biāo)簽名稱 print(soup.title.string) # 獲取點(diǎn)前節(jié)點(diǎn)標(biāo)簽的內(nèi)容 print(soup.title.get_text()) # 獲取當(dāng)前節(jié)點(diǎn)及子節(jié)點(diǎn)的所有內(nèi)容 print(soup.body.get_text("|")) # 獲取當(dāng)前節(jié)點(diǎn)及子節(jié)點(diǎn)的所有內(nèi)容,以|分隔每個(gè)節(jié)點(diǎn)的內(nèi)容 print(soup.title.parent)# 獲取當(dāng)前節(jié)點(diǎn)及父節(jié)點(diǎn)的內(nèi)容 print(soup.body['style']) # 獲取屬性值 print(soup.body.get('style')) # 獲取屬性值 # 有多個(gè)標(biāo)簽想獲取非第一個(gè) # 方法一;先返回所有的,在根據(jù)下標(biāo)查找 print(soup.find_all('p')) #返回的是一個(gè)列表所以可以使用列表獲取元素的方法 print(soup.find_all('p')[1]) # 根據(jù)下標(biāo)獲取第二個(gè) # 方法二:根據(jù)屬性找 print(soup.find_all('p',id='b')) # 根據(jù)id獲取第二個(gè) # 執(zhí)行結(jié)果 <title>測(cè)試</title> <p id="a">第一個(gè)p</p> title 測(cè)試 測(cè)試 | 標(biāo)題1 | | 標(biāo)題2 | |第一個(gè)p| |第二個(gè)p| |第三個(gè)p| <head> <title>測(cè)試</title> </head> background-color: yellow background-color: yellow [<p id="a">第一個(gè)p</p>, <p id="b">第二個(gè)p</p>, <p id="c">第三個(gè)p</p>] <p id="b">第二個(gè)p</p> [<p id="b">第二個(gè)p</p>]
- 演示文件
# html文件(本地) <html> <head> <title>測(cè)試</title> </head> <body style='background-color: yellow'> <h1 > 標(biāo)題1 </h1> <h2 style = 'background-color:green;text-align:center'> 標(biāo)題2 </h2> <p id ='a'>第一個(gè)p</p> <p id = 'b'>第二個(gè)p</p> <p id = 'c'>第三個(gè)p</p> </body> </html>
元素選擇之css
語(yǔ)法
# 選擇單個(gè)元素 driver.find_element_by_css_selector('...') # 選擇多個(gè)元素 driver.find_elements_by_css_selector('...')
子元素(child)選擇器
-
選擇元素的子元素(直接子節(jié)點(diǎn))
- 對(duì)比:后代選擇器(非直接子節(jié)點(diǎn))
#choose_car option
- 語(yǔ)法舉例
#choose_car > option footer > p
- 可以是很多級(jí)
ul > ol > li > em
-
組選擇:同時(shí)選擇多個(gè)元素,逗號(hào)隔開(kāi)
,
- 語(yǔ)法:<s1>,<s2>
- 舉例:
p,button #food,.cheese
-
組合使用
- 選擇id為food的所有span子元素和所有的p(包括非food的子元素)
#food >span, p
- 選擇id為food的:所有span子元素和所有的p子元素
#food > span,#food > p
- 選擇id為food的所有子元素
#food > *
兄弟節(jié)點(diǎn)選擇
-
選擇緊跟在另一個(gè)元素后的元素,二者有相同的父元素
+
- 舉例
#food + div #many > div > p.special + p
-
選擇在另一個(gè)元素后的元素,二者有相同的父元素
~
- 舉例
#food ~ div
屬性選擇器
-
可以根據(jù)元素的屬性及屬性值來(lái)選擇元素
- 舉例
*[style] # 選擇所有的元素中屬性中含style的元素 p[spec = len2] # 選擇元素p的屬性spec=len2的元素(spec ='len2 len3'時(shí),不會(huì)選中) p[spec = 'len2 len3'] p[spec* = 'len2'] # 選擇元素p的屬性spec包含len2的元素(spec ='len2 len3'時(shí),也會(huì)選中) p[spec^ = 'len2'] # 選擇元素p的屬性spec以len2開(kāi)頭的元素(spec ='len2 len3'時(shí),也會(huì)選中) p[spec$ = 'len2'] # 選擇元素p的屬性spec以len2結(jié)尾的元素(spec ='len2 len3'時(shí),不會(huì)選中) p[class = special][name = p1] # 選擇元素p的屬性class = special,同時(shí)name = p1的元素
編輯框的一些操作
-
- 用clear方法清楚該元素里面的字符串
input1.clear()
- 輸入內(nèi)容
input1.sed_keys('xxxx')
- 獲取input元素里面輸入的文本內(nèi)容
input1.get_attribute('value')
單選框-選擇單個(gè)
-
- 對(duì)應(yīng)的html
<input type='radio' name='gender' value='male'>男<br> <input type='radio' name='gender' value='female'>女<br>
- click方法選擇
- 不管原來(lái)該元素是否選中,直接去點(diǎn)擊該元素沒(méi)有問(wèn)題,都可以確保該單選框選中
- 示例
input1 = driver.find_element_by_css_selector('input[value=male]') input1.click()
勾選框-可選擇多個(gè)
-
- 對(duì)應(yīng)的html
<input type='checkbox' name='vehicle' value='bike'>自行車<br> <input type='checkbox' name='vehicle' value='car'>汽車<br>
- click方法選擇
- is_selected方法來(lái)獲取選擇的狀態(tài)
- 示例
input1 = driver.find_element_by_css_selector('input[value=car]') # 判斷是否已經(jīng)被選中 selected = input1.isselected() if selected: print('car already selected') else: print('car not selected,click on it') input1.click()
復(fù)選框
-
- 對(duì)應(yīng)的html
# 按住ctrl可多選 <select id='multi' multiple> <option value='benz'>奔馳S300</option> <option value='accord'>雅閣</option> <option value='aa'>測(cè)試aa</option> <option value='bb'>測(cè)試bb</option> </select> # 單選 <select id='single'> <option value='male'>男</option> <option value='female' selected='selected'>女</option> </select>
- Select類
- 方法deselect_all
- 方法select_by_visible_text
- 示例
# 導(dǎo)入Select from selenium.webdriver.support.ui import Select # 獲得相應(yīng)的WebElement select = Select(driver.find_element_by_id('multi')) # 先去選擇所有的選項(xiàng) select.deselect_all() select.select_by_visible_text('雅閣') select.select_by_visible_text('奔馳S300') # 獲得相應(yīng)的WebElement select = Select(driver.find_element_by_id('single')) select.select_by_visible_text('男')
補(bǔ)充01:點(diǎn)擊查看selenium之下拉選擇框Select 相關(guān)補(bǔ)充內(nèi)容
-
Select提供了三種選擇方法:
- select_by_index(index) ——通過(guò)選項(xiàng)的順序,第一個(gè)為 0
- select_by_value(value) ——通過(guò)value屬性
- select_by_visible_text(text) ——通過(guò)選項(xiàng)可見(jiàn)文本
-
Select提供了四種方法取消選擇:
- deselect_by_index(index)
- deselect_by_value(value)
- deselect_by_visible_text(text)
- deselect_all()
-
Select提供了三個(gè)屬性方法給我們必要的信息:
- options ——提供所有的選項(xiàng)的列表,其中都是選項(xiàng)的WebElement元素
- all_selected_options ——提供所有被選中的選項(xiàng)的列表,其中也均為選項(xiàng)的WebElement元素
- first_selected_option ——提供第一個(gè)被選中的選項(xiàng),也是下拉框的默認(rèn)值
補(bǔ)充02:點(diǎn)擊CSS3 選擇器進(jìn)入原內(nèi)容界面查看
- 在 CSS 中,選擇器是一種模式,用于選擇需要添加樣式的元素。
- "CSS" 列指示該屬性是在哪個(gè) CSS 版本中定義的。(CSS1、CSS2 還是 CSS3。)
- 選擇屬于其父元素的第二個(gè)子元素的每個(gè) <p> 元素。
p:nth-child(2)
數(shù)字跟元素類型無(wú)關(guān),僅表示父元素下的第幾個(gè)元素
選擇器 | 例子 | 例子描述 | CSS |
---|---|---|---|
.class |
.intro |
選擇 class="intro" 的所有元素。 | 1 |
#id |
#firstname |
選擇 id="firstname" 的所有元素。 | 1 |
* |
* |
選擇所有元素。 | 2 |
element |
p |
選擇所有 <p> 元素。 | 1 |
element,element |
div,p |
選擇所有 <div> 元素和所有 <p> 元素。 | 1 |
element element |
div p |
選擇 <div> 元素內(nèi)部的所有 <p> 元素。 | 1 |
element>element |
div>p |
選擇父元素為 <div> 元素的所有 <p> 元素。 | 2 |
element+element |
div+p |
選擇緊接在 <div> 元素之后的所有 <p> 元素。 | 2 |
[attribute] |
[target] |
選擇帶有 target 屬性所有元素。 | 2 |
[attribute=value] |
[target=_blank] |
選擇 target="_blank" 的所有元素。 | 2 |
[attribute~=value] |
[title~=flower] |
選擇 title 屬性包含單詞 "flower" 的所有元素。 | 2 |
:link |
a:link |
選擇所有未被訪問(wèn)的鏈接。 | 1 |
:visited |
a:visited |
選擇所有已被訪問(wèn)的鏈接。 | 1 |
:active |
a:active |
選擇活動(dòng)鏈接。 | 1 |
:hover |
a:hover |
選擇鼠標(biāo)指針位于其上的鏈接。 | 1 |
:focus |
input:focus |
選擇獲得焦點(diǎn)的 input 元素。 | 2 |
:first-letter |
p:first-letter |
選擇每個(gè) <p> 元素的首字母。 | 1 |
:first-line |
p:first-line |
選擇每個(gè) <p> 元素的首行。 | 1 |
:first-child |
p:first-child |
選擇屬于父元素的第一個(gè)子元素的每個(gè) <p> 元素。 | 2 |
:before |
p:before |
在每個(gè) <p> 元素的內(nèi)容之前插入內(nèi)容。 | 2 |
:after |
p:after |
在每個(gè) <p> 元素的內(nèi)容之后插入內(nèi)容。 | 2 |
:lang(language) |
p:lang(it) |
選擇帶有以 "it" 開(kāi)頭的 lang 屬性值的每個(gè) <p> 元素。 | 2 |
element1~element2 |
p~ul |
選擇前面有 <p> 元素的每個(gè) <ul> 元素。 | 3 |
[attribute^=value] |
a[src^="https"] |
選擇其 src 屬性值以 "https" 開(kāi)頭的每個(gè) <a> 元素。 | 3 |
[attribute$=value] |
a[src$=".pdf"] |
選擇其 src 屬性以 ".pdf" 結(jié)尾的所有 <a> 元素。 | 3 |
[attribute*=value] |
a[src*="abc"] |
選擇其 src 屬性中包含 "abc" 子串的每個(gè) <a> 元素。 | 3 |
:first-of-type |
p:first-of-type |
選擇屬于其父元素的首個(gè) <p> 元素的每個(gè) <p> 元素。 | 3 |
:last-of-type |
p:last-of-type |
選擇屬于其父元素的最后 <p> 元素的每個(gè) <p> 元素。 | 3 |
:only-of-type |
p:only-of-type |
選擇屬于其父元素唯一的 <p> 元素的每個(gè) <p> 元素。 | 3 |
:only-child |
p:only-child |
選擇屬于其父元素的唯一子元素的每個(gè) <p> 元素。 | 3 |
:nth-child(n) |
p:nth-child(2) |
選擇屬于其父元素的第二個(gè)子元素的每個(gè) <p> 元素。 | 3 |
:nth-last-child(n) |
p:nth-last-child(2) |
同上,從最后一個(gè)子元素開(kāi)始計(jì)數(shù)。 | 3 |
:nth-of-type(n) |
p:nth-of-type(2) |
選擇屬于其父元素第二個(gè) <p> 元素的每個(gè) <p> 元素。 | 3 |
:nth-last-of-type(n) |
p:nth-last-of-type(2) |
同上,但是從最后一個(gè)子元素開(kāi)始計(jì)數(shù)。 | 3 |
:last-child |
p:last-child |
選擇屬于其父元素最后一個(gè)子元素每個(gè) <p> 元素。 | 3 |
:root |
:root |
選擇文檔的根元素。 | 3 |
:empty |
p:empty |
選擇沒(méi)有子元素的每個(gè) <p> 元素(包括文本節(jié)點(diǎn))。 | 3 |
:target |
#news:target |
選擇當(dāng)前活動(dòng)的 #news 元素。 | 3 |
:enabled |
input:enabled |
選擇每個(gè)啟用的 <input> 元素。 | 3 |
:disabled |
input:disabled |
選擇每個(gè)禁用的 <input> 元素 | 3 |
:checked |
input:checked |
選擇每個(gè)被選中的 <input> 元素。 | 3 |
:not(selector) |
:not(p) |
選擇非 <p> 元素的每個(gè)元素。 | 3 |
::selection |
::selection |
選擇被用戶選取的元素部分。 | 3 |
[attribute|=value]
[lang|=en]
選擇 lang 屬性值以 "en" 開(kāi)頭的所有元素.
元素選擇之xpath
xpath:樹(shù)型結(jié)構(gòu)
1. 基本概念
使用方法:
find_element_by_xpath("...")
根節(jié)點(diǎn):
/
-
子節(jié)點(diǎn):
/html/body/...
- 直接子節(jié)點(diǎn)
/body
- 所有子節(jié)點(diǎn)(包括直接子節(jié)點(diǎn)和非直接子節(jié)點(diǎn))
//body
- 直接子節(jié)點(diǎn)
當(dāng)前節(jié)點(diǎn)用“.”表示
./body/...
當(dāng)前節(jié)點(diǎn)的上一層節(jié)點(diǎn)用“..”表示
../body/...
從根節(jié)點(diǎn)開(kāi)始查找
/a/b/c/d
不從根節(jié)點(diǎn)開(kāi)始查找(查找所有節(jié)點(diǎn))
//c
//b/d
-
通配符用
*
表示,*
可以是任何一種類型//b//* 查找節(jié)點(diǎn)b下的所有元素
-
xpath與css方法對(duì)比
xpath css //div/*
div > *
-
-
根據(jù)屬性查找
- 所有屬性,包括id和class
- 示例01:查找屬性含style的所有元素
//*[@style]
- 示例02:查找p節(jié)點(diǎn)下屬性spec=len2的元素
//p[@spec='len2']
-
xpath與css方法對(duì)比
xpth屬性的值必須加引號(hào),css如果沒(méi)有空格可以不加引號(hào)
xpath css //*[@style] *[style] //p[@spec='len2'] p[spec=len2]
2. 舉例應(yīng)用
根據(jù)id選擇
//*[@id='food']
-
選擇屬于其父元素的第二個(gè)p
-
xpath與css方法對(duì)比
xpath css //p[2] nth-of-type(2)
-
-
選擇屬于其父元素的倒數(shù)第幾個(gè)元素
- 最后一個(gè)p類型的子元素
//p[last()]
- 倒數(shù)第二個(gè)p類型的子元素
//p[last(-1)]
- 所有元素的倒數(shù)第二個(gè)
//*[last()]
- 最后一個(gè)p類型的子元素
-
根據(jù)位置選擇
position表示位置
所有元素中的前兩個(gè)元素
//*[position()<=2]
除了第一個(gè)元素外的其他所有元素
//*[position()>1]
所有元素中的最后三個(gè)元素
//*[position()>last()-3]
-
xpath與css方法對(duì)比
- xpath:選擇所有的p和所有的button(先選擇所有的p再選擇button)
//p | //button
- css:選擇所有的p和所有的button(按結(jié)構(gòu)順序選擇)
p,button
- xpath:選擇所有的p和所有的button(先選擇所有的p再選擇button)
-
當(dāng)前節(jié)點(diǎn)下的所有直接子節(jié)點(diǎn)
- css:food下面所有的直接子節(jié)點(diǎn)中的div
#food ~ div
- xpath:
//*[@id='food']/following-sibling::div
- id為food的節(jié)點(diǎn)的子節(jié)點(diǎn)的第一個(gè)節(jié)點(diǎn)
//*[@id='food']/following-sibling::*[1]
- id是food的上一個(gè)節(jié)點(diǎn)的div節(jié)點(diǎn)
//*[@id='food']/preceding-sibling::div
- id為food的父節(jié)點(diǎn)(上層節(jié)點(diǎn))
//*[@id='food']/..
- css:food下面所有的直接子節(jié)點(diǎn)中的div
-
當(dāng)前目錄與子目錄
- 從根目錄下開(kāi)始查找所有的p:
'//p'
- 從當(dāng)前目錄下開(kāi)始查找所有的p:
'.//p'
- 從當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)開(kāi)始查找所有的p:
'..//p'
- 從當(dāng)前目錄下開(kāi)始查找直接子節(jié)點(diǎn)的p:
'./p'
- 從根目錄下開(kāi)始查找所有的p:
3. 在瀏覽器中確認(rèn)查找的元素是否正確
-
瀏覽器按F2進(jìn)入開(kāi)發(fā)者模式,點(diǎn)擊console
-
xpath與css方法對(duì)比
方法 路徑前的符號(hào) 示例 xpath $x $x("http://span")
css $$ $$('span')
-
瀏覽器按F2進(jìn)入開(kāi)發(fā)者模式,點(diǎn)擊elements,按
ctrl+F
進(jìn)入搜索模式,輸入xpath或css參數(shù)路徑
4. 瀏覽器端根據(jù)html查看xpath
- 選中某個(gè)路徑,點(diǎn)擊鼠標(biāo)右鍵,依次選擇
copy-->copy xpath
即可復(fù)制該元素的xpath
查詢12306列車
查詢有票的列車,并輸出列車車次
-
- 要求
- 南京南-杭州東
- 當(dāng)前時(shí)間的第二天
- 0600-1200
- 二等座
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
try:
driver = webdriver.Chrome()
driver.get('https://kyfw.12306.cn/otn/leftTicket/init')
driver.implicitly_wait((10))
# 出發(fā)地
driver.find_element_by_id('fromStationText').click() # 點(diǎn)擊操作用于清空默認(rèn)置灰的文字
driver.find_element_by_id('fromStationText').send_keys('南京南')
driver.find_element_by_id('fromStationText').send_keys(Keys.ENTER) # 模擬鍵盤enter
# 目的地
driver.find_element_by_id('toStationText').click()
driver.find_element_by_id('toStationText').send_keys('杭州東')
driver.find_element_by_id('toStationText').send_keys(Keys.ENTER) # 模擬鍵盤enter
# 選擇時(shí)間段
driver.find_element_by_id('cc_start_time').click()
driver.find_element_by_xpath("http://*[@id='cc_start_time']/option[@value='06001200']").click()
# 選擇日期-->自動(dòng)查詢出結(jié)果
driver.find_element_by_xpath(("http://*[@id='date_range']/ul/li[2]")).click()
# # 收集數(shù)據(jù)--方法一(本人首次做出來(lái)時(shí)使用的方法)
# with_ticket_trains = [] # 有票的車次
# without_ticket_trains =[] # 無(wú)票的車次
# all_trains_info = driver.find_elements_by_xpath("http://*[@id='queryLeftTable']/tr/td[4]")
# for one_train_info in all_trains_info:
# train_number = one_train_info.find_element_by_xpath("../td[1]//*[@class='number']").text.strip() # 查找車次
# if one_train_info.text in ('--', '無(wú)'): # 判斷是否有票
# without_ticket_trains.append(train_number)
# else:
# with_ticket_trains.append(train_number)
# # 打印出有票的列車車次
# if len(with_ticket_trains) == 0:
# print('您所選的區(qū)間及時(shí)間范圍內(nèi)所有列車均已無(wú)票')
# else:
# print('以下列車還有票:')
# for i in with_ticket_trains:
# print(f'{i:>6}')
# 收集數(shù)據(jù)--方法二(后期發(fā)現(xiàn)只有有票的才含有class屬性,代碼如下)
all_trains_info = driver.find_elements_by_xpath("http://*[@id='queryLeftTable']/tr/td[4][@class]/../td[1]//a")
for one in all_trains_info:
print(one.text)
finally:
driver.quit()
- 結(jié)果
- 點(diǎn)擊查看補(bǔ)充知識(shí)
本文采用其他方法實(shí)現(xiàn)功能,暫未涉及鏈接中介紹的方法,但此方法很實(shí)用
- 點(diǎn)擊查看補(bǔ)充知識(shí)
使用技巧
<meta charset="utf-8">
webdriver對(duì)象的一些方法
- 獲取某個(gè)元素的屬性值
# 獲取選定元素對(duì)應(yīng)的鏈接
ele.get_attribute("href")
- 獲取當(dāng)前窗口的title
driver.get('https://www.baidu.com/')
print(driver.title)
driver.find_element_by_id('kw')
print(driver.title)
獲取當(dāng)前窗口的地址欄url地址
driver.current_url
隨著用戶的操作,title和current_url會(huì)變化
截屏-全部屏幕
driver.get_screenshot_as_file('ssl.png')
- 截屏-某個(gè)元素
ele = driver.find_element_by_id('search')
ele.screenshot_as_png('serch.png')
切換窗口
-
切換到新的窗口里面操作
- 循環(huán)遍歷所有的窗口 driver.window_handles
- driver.switch_to.window(handle)方法切入新窗口
- 檢查該窗口特點(diǎn),是否為要切入的那個(gè)
-
切換到最初的窗口
- 保存主窗口的handle
-
關(guān)閉窗口
- close方法
- quit()關(guān)閉整個(gè)瀏覽器
-
示例
# 點(diǎn)擊某個(gè)元素,打開(kāi)了一個(gè)新的窗口 # 保存主窗口handle mainWindow = driver.current_window_handle print(driver.window_handles) for handle in driver.window_handle: # 切換到新窗口 driver.switch_to.window(handle) # 檢查是否是我們要進(jìn)入到window if '百度' in driver.title: break # 進(jìn)行操作 pass # 切換到主窗口 driver.switch_to.window(mainWindow) # 進(jìn)行操作 pass
彈出對(duì)話框
- 對(duì)話框一般來(lái)說(shuō)有三種:
- alert 簡(jiǎn)單通知(一個(gè)按鈕)
- confirm (確定,取消)
- prompt (輸入內(nèi)容,確定,取消)
- 操作方法
driver.switch_to.alert.accept() # 點(diǎn)擊ok
driver.switch_to.alert.text # 得到對(duì)話框內(nèi)容
driver.switch_to.alert.getText() # 得到對(duì)話框的內(nèi)容
driver.switch_to.alert.dismiss() # 點(diǎn)擊Cancel
driver.switch_to.alert.send_keys() # 輸入內(nèi)容
# alert = driver.switch_to.alert() # 獲取彈框
-
alert彈窗和html元素彈框
- alert彈窗,用上述方法
- html彈框,查找定位相關(guān)元素進(jìn)行操作
-
如何判斷alert彈窗和html彈框
- 點(diǎn)擊F12,查看是否可以獲得該元素
頁(yè)面含有input元素,通過(guò)插入文件到方式input元素
win32com.client
- 直接發(fā)送鍵盤消息給 當(dāng)前應(yīng)用程序。
- 前提是瀏覽器必須是當(dāng)前應(yīng)用(放在最上層,瀏覽器運(yùn)行后不要操作
import win32com.client
shell = win32com.client.Dispath('WScript.Shell')
shell.Senkey(r'd:\p1.jpg' + '\n')
刷新頁(yè)面,前進(jìn),后退
- 頁(yè)面刷新
refresh
- 前進(jìn)
forward
- 后退
back
driver.refresh()
driver.forward()
driver.back()
使用技巧
- 易消失元素的查看技巧
鼠標(biāo)移到該元素上面才會(huì)出現(xiàn)
鼠標(biāo)移開(kāi)就會(huì)消失
-
5秒后凍結(jié)頁(yè)面
setTimeout(function(){debugger;},5000)
image
瀏覽器定位元素 copy selector
獲取元素的方法
css
xpath
-
取巧:選中元素,右鍵點(diǎn)擊copy,選擇
copy selector
,或者選擇copy xpath
上層節(jié)點(diǎn)有id時(shí),此方法比較方便,否則可能會(huì)生成比較長(zhǎng)的路徑;
路徑太長(zhǎng)時(shí),后期html中被修改的可能性比較大,不好維護(hù)
此方法并不適用于所有情況,慎用 動(dòng)態(tài)的id不可使用
異常捕獲,確保chrome進(jìn)程退出
切換到新的窗口里面操作
-
使用try...finally...
try: # 可執(zhí)行代碼 except: print() finally: driver.quit()
特殊動(dòng)作
-
ActionChains 類
按下,移動(dòng),拖動(dòng)等
- acInstance.action1().action2().actionN().perform()
-
移動(dòng)到某個(gè)元素上面
- ActionChains(driver).move_to_element(ele).perform()
from selenium.webdriver.common.action_chains import ActionChains ac = ActionChains(driver) ac.move_to_element(driver.find_element_by_id('zxnav_1')).perform()
-
一次性輸入多個(gè)input內(nèi)容
t1 = driver.find_element_by_id('t1') t2 = driver.find_element_by_id('t2') t3 = driver.find_element_by_id('t3') from selenium.webdriver.common.action_chains import ActionChains ac = ActionChains(driver) ac.click(t1).send_key('1').click(t2).send_key('2').click(t3).send_key('3').perform()
頁(yè)面元素不可見(jiàn)
通常不可見(jiàn)元素都是可以操作的
-
如果確實(shí)需要改變窗口大小
# 獲取窗口大小,返回的size是字典(寬度和高度) size = driver.get_window_size() # 改變大小,()里對(duì)應(yīng)的分別是寬度和高度,數(shù)字對(duì)應(yīng)的是像素,size['height']表示保持原高度不變 driver.set_window_size(1100,size['height'])
driver.max... 窗口最大化
-
滾動(dòng)頁(yè)面
# X坐標(biāo)的值,Y坐標(biāo)的值 # 正數(shù)往下往右移動(dòng),負(fù)數(shù)往上往左移動(dòng) driver.execute_script('window.scrollBy(250,0)') # 可在瀏覽器的console中輸入window.scrollBy(250,0),以查看是否能滾動(dòng)到自己想要的位置
渲染
- 后端渲染
- 前端渲染
- 前端渲染問(wèn)題引起的報(bào)錯(cuò):statle element reference
- 解決方法:獲取內(nèi)容前,sleep一下
合理使用半自動(dòng)化
-
圖形界面自動(dòng)化的難度是比較大的
- 模擬難(12306輸入驗(yàn)證碼...)
- 檢查難(檢查logo、布局等...)
-
用半自動(dòng)化的方法
-難自動(dòng)化的操作,都提示(beep)讓人去做import winsound winsound.Beep(1500,3000) # 發(fā)出提示音
- 其余部分:自動(dòng)化 去做
自動(dòng)化的目的:提高測(cè)試效率
自動(dòng)化面對(duì)的問(wèn)題
- 如何組織我們的自動(dòng)化腳本?都放在一個(gè)大目錄里面?
- 一次測(cè)試開(kāi)始了,如何選擇測(cè)試腳本去執(zhí)行?難道是手動(dòng)的一個(gè)個(gè)運(yùn)行這些腳本?
- 每個(gè)測(cè)試腳本中,各個(gè)檢查點(diǎn)是否通過(guò),如何在測(cè)試結(jié)果里面清晰的反饋
- 一些通用功能的實(shí)現(xiàn)如何以庫(kù)的形式組織起來(lái),供各個(gè)腳本使用
- 執(zhí)行結(jié)果如何以容易查看的報(bào)告的形式提交給別人查閱
- 以上這些都可以由自動(dòng)化測(cè)試框架解決