Selenium學(xué)習(xí)

selenium安裝配置

  1. Python安裝

  2. selenium客戶端庫(kù)

    # win
    pip install selenium
    # mac
    sudo pip3 install selenium
    
    
    • 驗(yàn)證是否安裝成功
      控制臺(tái)輸入命令pip list 查看列表中是否存在selenium,如果有,則說(shuō)明安裝成功。

      image
  3. 谷歌瀏覽器驅(qū)動(dòng)chromedriver notes.txt文件可以查看對(duì)應(yīng)的chrome版本

  4. 將瀏覽器驅(qū)動(dòng)文件(chromedriver.exe)放到環(huán)境變量中配置的路徑內(nèi)

    1. 如果不放入環(huán)境變量,則每次使用時(shí)需填寫(xiě)瀏覽器驅(qū)動(dòng)文件所在的路徑
    2. 必須為系統(tǒng)的環(huán)境變量,臨時(shí)設(shè)置的環(huán)境變量無(wú)效
    3. 快速設(shè)置:mac 可以把瀏覽器驅(qū)動(dòng)文件放到/usr/local/bin
    4. 快速設(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/')
    
    
  5. 補(bǔ)充:安裝三大瀏覽器驅(qū)動(dòng)(driver)

    • chromedriver 下載地址:參考第三點(diǎn)
    # 啟動(dòng)谷歌瀏覽器
    from selenium import webdriver
    browser = webdriver.Chrome()
    browser.get('http://www.baidu.com/') 
    
    
    # 啟動(dòng)火狐瀏覽器
    from selenium import webdriver
    browser = webdriver.Firefox()
    browser.get('http://www.baidu.com/')
    
    
    # 啟動(dòng)IE瀏覽器
    from selenium import webdriver
    browser = webdriver.Ie()
    browser.get('http://www.baidu.com/')
    
    
  6. 簡(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/
    
    

元素選擇之常規(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')

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ǔ)充)

學(xué)習(xí)地址

查找時(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
  • 當(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ù)屬性查找

    1. 所有屬性,包括id和class
    2. 示例01:查找屬性含style的所有元素//*[@style]
    3. 示例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()]
  • 根據(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
  • 當(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']/..
  • 當(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'
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
image

查詢12306列車

查詢有票的列車,并輸出列車車次

    1. 要求
    • 南京南-杭州東
    • 當(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()

    1. 結(jié)果
image
    1. 點(diǎn)擊查看補(bǔ)充知識(shí)本文采用其他方法實(shí)現(xiàn)功能,暫未涉及鏈接中介紹的方法,但此方法很實(shí)用
image

使用技巧

<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

  1. 直接發(fā)送鍵盤消息給 當(dāng)前應(yīng)用程序。
  2. 前提是瀏覽器必須是當(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è)試框架解決
selenium.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。