Selenium css選擇元素,元素驗(yàn)證

3.4 通過CSS選擇器選擇

W3CCSS是定義HTML頁面樣式的語言。它決定頁面元素顯示的效果,比如一段文本的字體,大小,間距等等。當(dāng)然,要修飾一個元素,首先它也要指定修飾的是哪個元素。所以CSS規(guī)范里面定義一種選擇頁面元素的語法。正好Selenium可以用它來定位頁面元素。CSS選擇器就是這種語法的使用。CSS選擇器選擇功能強(qiáng)大,不僅可以通過上述的屬性選擇,還可以根據(jù)元素的父子兄弟關(guān)系,子元素的順序,其他的任意元素屬性的有無或者屬性值,輸入焦點(diǎn),等等??傊浅5膹?qiáng)大,特別適用于上面方法都不好定位的時候使用。假如有如下的html片段。

  • 根據(jù) tag 名 選擇
p {color: red;} #表示選擇所有的 p 元素 
  • 根據(jù) id ,前面加個#號
#food {color: blue;} #表示選擇ID為 food的 元素 
  • 3.根據(jù)class 選擇,前面加個“.”
.special  {color: red;}#表示選擇class為 special 的 元素 ,

注意有的元素有兩個class 值:

<span class="vegetable good">黃瓜</span>

我們可以看到這個calss中間有一個空格,他不是整體是一個class而是說這個元素有兩個class屬性,是vegetablegood我們可以這樣寫:

.good  {color: red;}#表示選擇class為 good 的所有 元素 
.vegetable {color: blue;} #表示選擇所有的 class為 vegetable所有 的元素 

如果要選擇class屬性同時具有vegetablegood 的,可以這樣:

.vegetable.good

假如有如下的html片段:

<div id="food" style="margin-top:10px;color:red">
    <span class="vegetable good">黃瓜</span>
    <span class="meat">牛肉</span>
    <p class="vegetable">南瓜</p>
    <p class="vegetable">青菜</p>
</div>

<div id="food2" style="margin-top:10px">
    <span class="vegetable">黃瓜2</span>
    <span class="meat">牛肉3</span>
</div>

<select id="choose_car">
    <option value="volvo">沃爾沃</option>
    <option value="corolla">卡羅拉</option>
    <option value="fiat">菲亞特</option>
    <option value="audi">奧迪</option>
</select>

通過css選擇的方式如下:

  • 根據(jù)tag名,選中第一個span節(jié)點(diǎn)
find_element_by_css_selector('span')

選中所有的span節(jié)點(diǎn)

find_elements_by_css_selector('span')
  • 根據(jù)id名
#選中所有id為food2的節(jié)點(diǎn)
find_elements_by_css_selector('#food2')

根據(jù)class

#選中所有class屬性為vegetable的節(jié)點(diǎn)
find_elements_by_css_selector('.vegetable')

講到這里大家會想這些根據(jù)id,class,tag去找元素我們之前不是說過嗎,比如find_elements_by_id()、find_elements_by_class_name()這只是我們已前知識的另一種用法而已,我們?yōu)槭裁匆獙W(xué)它呢?這里就介紹它的強(qiáng)大之處,它有后代選擇的能力。

比如大家看這個表達(dá)式:

#food p

中間有個空格,剛才有說到空格在css里面不能亂加有特殊的含義,這個空格就是你要找的節(jié)點(diǎn),注意一定是找空格最后一個節(jié)點(diǎn),就是p節(jié)點(diǎn),空格前面是這個節(jié)點(diǎn)的上層節(jié)點(diǎn)的特性,這個表達(dá)式我們可以這樣理解:我們要找一個標(biāo)簽名是p的,然后這個標(biāo)簽有一個限制,他是在idfood 元素的內(nèi)部 ,我們要找idfood 里面的所有p,空格就是后代的意思。

看一個例子:

div span

就是查找所有 div 元素 里面的 span 元素。

發(fā)現(xiàn)spandiv的直接子元素, 就算不是直接子元素也可以,只要是內(nèi)部的就一樣可以。


3.4.1子元素選擇

前面我們學(xué)習(xí)了后代選擇器,比如后代選擇器:#choose_car option。選擇 id choose_car 的所有 option子元素,不管它們是否是直接子節(jié)點(diǎn)。如果您希望縮小范圍,只選擇某個元素的直接子節(jié)點(diǎn)元素,請使用子元素選擇器(Child selector)。

  • 子元(child)選擇器
    選擇元素的子元素,和后代選擇器不同(#food p )比如:
#choose_car > option 大于號表示你最終要選擇的option 元素是前面的這個元素的直接子節(jié)點(diǎn)
  • 可以是很多級
ul > ol > li > em

方法是可以混合使用的比如div li > #abc這個表達(dá)式意思就是div里面tag名為li,idabc的直接子元素。

3.4.2 組(group)選擇

組選擇 同時選擇多個元素,逗號隔開,語法:

語法 <s1>,<s2>

比如:
p,button 選擇所有的p元素和所有的button元素
#food , .cheese 選擇所有idfood的元素和classcheese的元素。

選擇 idfood的所有span子元素 和 所有的p(包括非food的子元素)逗號的優(yōu)先級要比后代的優(yōu)先級低,逗號是最后算的。

#food > span,p

選擇 idfood的 所有span子元素 和 idfood的 所有的p元素:

#food > span ,#food > p

可以這樣選擇idfood的的所有子元素:

#food > *

*代表所有元素的意思

p buttonp ,button大家能區(qū)分清楚嗎,p button意思是p元素里面所有的button元素,p ,button意思是所有的p和所有的button。

selenium也可以用這樣的語法:

eles = driver.find_elements_by_css_selector('p, button')

3.4.3 兄弟節(jié)點(diǎn)選擇

我們說過了 后代元素選擇、子元素選擇,現(xiàn)在我們說下相鄰兄弟選擇器。下面有這樣一段html

<div id="food2" style="margin-top:10px">
    <span class="vegetable">黃瓜2</span>
    <span class="meat">牛肉3</span>
</div>

<select id="choose_car">
    <option value="volvo">沃爾沃</option>
    <option value="corolla">卡羅拉</option>
    <option value="fiat">菲亞特</option>
    <option value="audi">奧迪</option>
</select>

選擇緊接在另一個元素后的元素,而且二者有相同的父元素。注意:兩個條件 緊接在后面、相同父元素 .這個表達(dá)式就是找到idfood2緊跟著的兄弟節(jié)點(diǎn)select節(jié)點(diǎn):

#food2 + select 

如果我們想選擇的 只是在另一個元素后的兄弟元素,不一定要緊挨著,二者有相同的父元素 ,用下面的語法。

#food2 ~ select 

大家注意“+”“~”都是選擇后面的元素,#food + div 表示idfood的緊跟著的div,#food ~ div不一定要緊接著,我們可以聯(lián)合其他語法使用,比如:

#many > div > p.special + p

選擇 #many 的子元素 div 里面的 子元素 p (類型為special) 的后面的兄弟節(jié)點(diǎn)。最后選中的元素是:

image.png

3.4.4 屬性選擇

比如:選擇所有具有style屬性的元素

*[style]

又比如:選擇P節(jié)點(diǎn)具有spec值為 len2 的元素,加引號一般用在 屬性值中間有空格的情況,如果沒有空格可以不加引號。這里有個特別要注意的地方,屬性選擇必須要完全一樣

p[spec='len2']

看下面的截圖,標(biāo)紅的部分是不會被選中的。

image.png

屬性選擇還有一種寫法,如果要選擇只要spec屬性包含len2的就被選擇那要怎么寫呢,在“=”前面加個“*”號就可以

p[spec*='len2']
或者
a[href*="baidu.com"]

len2開頭的:

p[spec^='len2']

len2結(jié)尾的:

p[spec$='len2']

同時滿足兩種屬性的:

p[class=special][name=p1] 

CSS選擇器有很多的語法, 詳細(xì)的大家可以參考 這里http://www.w3school.com.cn/cssref/css_selectors.asp

我們css選擇器還有一種常用的方法:nth-child(n)比如p:nth-child(2)意思是首先選擇所有的p節(jié)點(diǎn),冒號表示一個限定,就是p必須是父元素的第二個子元素,這就是nth-child(2),注意不是說第二個p類型的子元素而就是第二個p元素比我我們看個例子:


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>定位網(wǎng)頁元素</title>

<style>
    #choose_car option {color: blue;}
</style>

</head>

<body>
    <div style="">
      <h3>This is a heading</h3>
      <p>This is a paragraph.</p>
    </div>

    <button name='button'>按鈕1</button>
    <button name='button'>按鈕2</button>

    <div class="cheese"><span>Cheddar</span></div>
    <div class="cheese"><span>Gouda</span></div>

    <a  id="baidulink">轉(zhuǎn)到百度</a>

    <div id="food" style="margin-top:10px;color:red">
        <span class="vegetable good">黃瓜</span>
        <span class="meat">牛肉</span>
        <p class="vegetable">南瓜</p>
        <p class="vegetable">青菜</p>
    </div>

    <div id="food2" style="margin-top:10px">
        <span class="vegetable">黃瓜2</span>
        <span class="meat">牛肉3</span>
    </div>

    <select id="choose_car">
        <option value="volvo">沃爾沃</option>
        <option value="corolla">卡羅拉</option>
        <option value="fiat">菲亞特</option>
        <option value="audi">奧迪</option>
    </select>

    <footer>
        <div>
            <p>test1</p>
        </div>
    </footer>

    <p>test2</p>
    <div id="many">
        <div>
            <p class="special" name="p1">one</p>
            <p>two</p>
            <p class="special3">three</p>
        </div>
    </div>

    <p spec="len">test3</p>
    <p spec="len2">test4</p>
    <p spec="len2 len3">test5</p>


</body>
</html>

id等于food的下面有幾個p元素,是不是2個?

#food > p:nth-child(2)

這個表達(dá)式是什么意思呢?屬于其父元素的第二個子元素,并且要是p ,我們這里第二個子元素是span,所以上面這個表達(dá)式是找不到的。

比如:

#food > p:nth-child(3)

這個表達(dá)式的意思是,屬于其父元素的第3個子元素,并且要是p,這就可以找到。這是正數(shù)第3個我們還可以倒數(shù)nth-last-child(n),還有一種按照類型排序的方法nth-of-type(),p:nth-of-type()p:nth-child()區(qū)別是:p:nth-child(2)必須是父節(jié)點(diǎn)的第二個子節(jié)點(diǎn),p:nth-of-type(2)第二個p類型的子節(jié)點(diǎn)。

比如:屬于其父元素的倒數(shù)第二個子元素,并且是p

#food > p:nth-last-child(2) 

找到的是:


image.png

比如:屬于其父元素的第二個p 類型的子元素

#food > p:nth-of-type(2) 

找到的是:


image.png

比如:屬于其父元素的倒數(shù)第二個p 類型的子元素

#food > p:nth-last-of-type(2)

找到的是:


image.png

還有一種選擇元素的方式:not(p),選擇非 <p> 元素的每個元素。

比如:

#food > :not(p)

找到的是:


image.png

3.4.5 利用瀏覽器開發(fā)工具獲取 css seletor

對于不太好找的CSS selector的元素,我們可以通過瀏覽器開發(fā)工具幫助我們定位。在chrom瀏覽器里,按F12,打開開發(fā)工具窗口,點(diǎn)擊element標(biāo)簽,然后,在網(wǎng)頁窗口里面 點(diǎn)選我們要 選擇的元素,開發(fā)工具窗口會高亮顯示該元素對應(yīng)的html tag代碼。這時,我們可以 用鼠標(biāo)右鍵 點(diǎn)擊該代碼,在彈出的對話框中,依次選擇Copy --> Copy selector,如下圖所示,這樣,該元素的CSS selector就被拷貝到剪貼板了。

image.png

3.4.6 驗(yàn)證css表達(dá)式

當(dāng)我們要寫的自動化腳本比較復(fù)雜的時候,每次到python代碼中調(diào)試CSS選擇器(看看我們的css選擇器是否能選中元素)會非常的麻煩。因?yàn)楹苈?,我們可以利用瀏覽器的開發(fā)工具,直接在瀏覽器中進(jìn)行測試,看看我們寫的CSS選擇器是否能正確找到我們要的web元素。

兩種方法, 一種是chrome瀏覽器,按F12,打開開發(fā)窗口,點(diǎn)擊元素標(biāo)簽(英文叫Element),按contrl + f,直接輸入css選擇器即可。選中的元素會高亮顯示。

image.png

這種方法優(yōu)點(diǎn), 填入內(nèi)容完全就是 css 選擇器, 缺點(diǎn): 也會做 字符匹配, 讓人有點(diǎn)迷糊。

另一種是:
chrome瀏覽器,按F12,打開開發(fā)窗口,點(diǎn)擊控制臺標(biāo)簽(英文叫console),在里面執(zhí)行$$(‘css selector’),其中css selector 就是css選擇器字符串。chrom界面如下所示:

image.png

如果能找到對象,返回的結(jié)果就不是空數(shù)組,就表示能找到web元素。而且鼠標(biāo)放在數(shù)組元素上,會高亮顯示對應(yīng)的web元素。這種方法 優(yōu)點(diǎn), 不會做 字符串匹配, 很清晰。缺點(diǎn): 要多輸入點(diǎn)內(nèi)容。

下面是一次作業(yè),可以用今天講的知識做一下
登錄 51job:http://www.51job.com
輸入搜索關(guān)鍵詞 "python", 地區(qū)選擇 "杭州"(注意,如果所在地已經(jīng)選中其他地區(qū),要去掉),搜索最新發(fā)布的職位, 抓取頁面信息。 得到如下的格式化信息:
Python開發(fā)工程師 | 杭州納帕科技有限公司 | 杭州 | 0.8-1.6萬/月 | 04-27
Python高級開發(fā)工程師 | 中浙信科技咨詢有限公司 | 杭州 | 1-1.5萬/月 | 04-27
高級Python開發(fā)工程師 | 杭州新思維計算機(jī)有限公司 | 杭州-西湖區(qū) | 1-1.5萬/月 | 04-27

解析:這里面就只有一個難點(diǎn),怎么只保證選擇 杭州 呢,我們可以定位一下選中的元素有什么特征,我們發(fā)現(xiàn) class="on" 就是選中,如果不選中就沒有class="on" 的值,確保只有杭州是選中的,這里要綜合使用 pythonSelenium 的知識,我們可以先把所有的城市過一遍,如果他是杭州 class值不等于 on 我們就 click 一下,如果選中了就不動他,如果是其他城市是反之,選中了就 click 下沒選中就不管它。

#從selenium里面導(dǎo)入webdriver
from selenium import webdriver

#指定chrom的驅(qū)動
#執(zhí)行到這里的時候Selenium會到指定的路徑將chrome driver程序運(yùn)行起來
driver = webdriver.Chrome('E:\ChromDriver\chromdriver2.43\chromedriver.exe')
driver.implicitly_wait(10)

driver.get('https://www.51job.com/')
#根據(jù)id找到輸入框,輸入python
driver.find_element_by_id('kwdselectid').send_keys('python')
#點(diǎn)擊工作地點(diǎn)
driver.find_element_by_id('work_position_input').click()

import time
time.sleep(2)

#用css方法找到所有的城市
cityEles = driver.find_elements_by_css_selector('#work_position_click_center_right_list_000000 em')

#遍歷元素,一個個城市去找
for one in cityEles:
    #城市名
    cityname = one.text
    #用之前學(xué)過的attribute方法獲取class的值
    cassvalue = one.get_attribute('class')
    #
    if cityname == '杭州':
        if cassvalue != 'on':
            one.click()
    elif cityname != '杭州':
        if cassvalue == 'on':
            one.click()
#點(diǎn)擊確定按鈕
driver.find_element_by_id('work_position_click_bottom_save').click()
#點(diǎn)擊搜索按鈕
driver.find_element_by_css_selector('div.ush.top_wrap button').click()
#找職位
jobs = driver.find_elements_by_css_selector('#resultList div.el')

for job in jobs[1:]:
    #span是一個列表
    spans = job.find_elements_by_tag_name('span')
    #列表生成式
    fields = [span.text for span in spans]
    print(fields)

#退出
driver.quit()

代碼里為什么有 sleep?我們執(zhí)行到 cityEles = driver.find_elements_by_css_selector('#work_position_click_center_right_list_000000 em') 的時候其實(shí)界面不是一下子呈現(xiàn)出來的,導(dǎo)致我們?nèi)フ?em 的時候狀態(tài)沒來的急更新,有沒有選中是動態(tài)更新的,他在定位城市的時候前端的 js 動態(tài)的獲取了一些信息,然后再把這些城市有沒有選中呈現(xiàn)出來,這樣就導(dǎo)致了當(dāng)前獲取的東西并不是過了一段時間后更新的狀態(tài),就是不是穩(wěn)定的狀態(tài),之前一個臨時的狀態(tài),這里我們就得 sleep 等待一下,有人會有疑問不是有 implicitly_wait 嗎,implicitly_wait 是找不到才會等待這里是可以找到 em ,只是這里過了一段時間才刷新的,大家可以好好看下這段代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.class 和 id 的使用場景? 兩者都能選取DOM節(jié)點(diǎn)并給DOM節(jié)點(diǎn)添加樣式,但是W3C標(biāo)準(zhǔn)里規(guī)定頁面中只...
    饑人谷_米彌輪閱讀 508評論 0 1
  • class 和 id 的使用場景? class屬性: 指定標(biāo)簽的類名,CSS操作中,把一些特定的樣式放到一個類中,...
    我要認(rèn)真學(xué)前端閱讀 1,083評論 0 0
  • id與class的使用場景 id選擇器,匹配特定id的元素類選擇器,匹配class包含(不是等于)特定類的元素id...
    姚小帥閱讀 411評論 0 0
  • 一、CSS選擇器常見的有幾種? 基本選擇器 通配選擇器~選擇文檔中所有的html元素,用一個*表示 元素選擇器~選...
    dengpan閱讀 1,030評論 0 3
  • 其實(shí)平時用得多的選擇器無非也就是那么幾個,時間久了,許多不常用的選擇器就慢慢忘記了。為了不讓自己忘記這些選擇器,今...
    盛夏晚清風(fēng)閱讀 1,955評論 0 5

友情鏈接更多精彩內(nèi)容