網頁自動化最基本的要求就是要定位到各個元素,然后才能對該元素進行各種操作(輸入,點擊,清除,提交等),所以筆者今天來總結下Selenuim+Python最基本的幾種定位方式及實例說明,希望能幫助到大家。
另外:學習元素定位方法前,建議先前往http://www.w3school.com.cn/html/index.asp 學習html前端基礎知識,這個更加有利於定位。
1.通過id定位元素
2.通過class_name定位元素
3.通過tag_name定位元素
4.通過name定位元素
5.通過link文字精確定位元素
6.通過link文字模糊定位元素
7.通過CSS定位元素
8.通過XPath定位元素
9.通過By定位元素
10.具體實例說明
以百度搜索輸入框為例,具體說明各個定位方式的用法:
(通過chrome瀏覽器查看元素或者搜狐瀏覽器的firebug查看,即可看到html源碼)
注意點:第三行的元素是灰色的,該元素是不可定位到的,下方會說明。
1 <span class="bg s_ipt_wr quickdelete-wrap"> 2 <span class="soutu-btn"></span> 3 <input id="kw" class="s_ipt" autocomplete="off" maxlength="255" value="" name="wd"> 4 <a id="quickdelete" class="quickdelete" href="javascript:;" title="清空" style="top: 0px; right: 0px; display: none;"></a> 5 </span> 6 <span class="bg s_btn_wr"> 7 <input id="su" class="bg s_btn" type="submit" value="百度一下"> 8 </span>
如果id不是動態的,一個頁面的id是唯一的。最簡單的定位方式。
使用:find_element_by_id("id_vaule")
實例:find_element_by_id("kw")
注意點:有些id值是動態變化的,則不能使用該方法定位。如下:id就是動態的,每次進入頁面,該id都會改變。
<label style="display: block;" id="auto-id-1469758879170" class="u-label f-dn">郵箱帳號或手機號</label>
classname有可能重復哦。
使用:find_element_by_class_name("class_name_vaule")
實例:find_element_by_class_name("s_ipt")
標簽名字最容易重復,不過,當定位一組數據時,可使用。
使用:find_element_by_tag_name("tag_name_vaule")
實例:find_element_by_tag_name("input")
注意點:當定位一組元素時:可勾選一組復選框。如下:
find_element_by_tag_name("input")
<body> <h3>checkbox</h3> <div class="well"> <form class="form-horizontal"> <div class="control-group"> <label class="control-label" for="c1">checkbox1</label> <div class="controls"> <input type="checkbox" id="c1"/> </div> </div> <div class="control-group"> <label class="control-label"for="c2">checkbox2</label> <div class="controls"> <input type="checkbox"id="c2"/> </div> </div> <div class="control-group"> <label class="control-label"for="c3">checkbox3</label> <div class="controls"> <input type="checkbox"id="c3"/> </div> </div> </form> </div> </body>
name有可能會重復哦。
使用:find_element_by_name("name_vaule")
實例:find_element_by_name("wd")
<a onclick="return false;" class="lb" name="tj_login" href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F">登錄</a>
使用:find_element_by_link_text("text_vaule")
實例:find_element_by_link_text("登錄")
使用:find_element_by_partial_link_text("部分text_vaule")
實例:find_element_by_partial_link_text("登")
可查看我的另外一篇博文:w3school之CSS學習筆記 學習css知識,更加有助於定位。
CSS(Cascading Style Sheets)是一種語言,它用來描述HTML和XML文檔的表現。CSS可以較為靈活的選擇控件的任意屬性,一般情況下會比XPath快。且語法也比較簡潔。
不過CSS對於初學者而言比較復雜。
使用:find_element_by_css_selector("CSS")
實例:
#號表示通過id屬性來定位元素
find_element_by_css_selector("#kw")
7.2通過class屬性定位元素
.號表示通過class屬性來定位元素
find_element_by_css_selector(".s_ipt")
7.3通過標簽名定位元素
find_element_by_css_selector("input")
7.4通過屬性定位元素(挺常用的)
find_element_by_css_selector("[name='wd']")
find_element_by_css_selector("[maxlength='255']")
屬性值包含某個值
屬性值包含wd:適用於由空格分隔的屬性值。
find_element_by_css_selector("[name~='wd']")
7.5父子定位元素
查找有父親元素的標簽名為span,它的所有標簽名叫input的子元素
find_element_by_css_selector("span>input")
7.6組合定位元素
標簽名#id屬性值:指的是該input標簽下id屬性為kw的元素
find_element_by_css_selector("input#kw")
標簽名.class屬性值:指的是該input標簽下class屬性為s_ipt的元素
find_element_by_css_selector("input.s_ipt")
標簽名[屬性=’屬性值‘]:指的是該input標簽下name屬性為wd的元素
find_element_by_css_selector("input[name='wd']")
父元素標簽名>標簽名.class屬性值:指的是span下的input標簽下class屬性為s_ipt的元素
find_element_by_css_selector("span>input.s_ipt")
多個屬性組合定位元素(挺常用的)
指的是input標簽下id屬性為kw且name屬性為wd的元素
find_element_by_css_selector("input.s_ipt[name='wd']")
指的是input標簽下name屬性為wd且maxlength為255的元素
find_element_by_css_selector("input[name='wd'][maxlength='255']")
比較復雜的CSS定位可查看
http://www.360doc.com/content/13/1105/10/11675837_326750173.shtml
http://www.360doc.com/content/13/1105/10/11675837_326750240.shtml
比較懶惰的方法:
使用搜狐瀏覽器的firebug工具,復制CSS路徑,不過這種方式對層級要求高,到時候自己再修改下。
XPath是一種XML文檔中定位元素的語言。該定位方式也是比較常用的定位方式。
使用:find_element_by_xpath("XPath")
實例:
8.1通過屬性定位元素
find_element_by_xpath("//標簽名[@屬性='屬性值']")
id屬性:
find_element_by_xpath("//input[@id='kw']")
class屬性:
find_element_by_xpath("//input[@class='s_ipt']")
name屬性:
find_element_by_xpath("//input[@name='wd']")
maxlength屬性:
find_element_by_xpath("//input[@maxlength='255']")
8.2通過標簽名定位元素
指所有input標簽元素
find_element_by_xpath("//input")
8.3父子定位元素
查找有父親元素的標簽名為span,它的所有標簽名叫input的子元素
find_element_by_xpath("//span/input")
8.4根據元素內容定位元素(非常實用)
find_element_by_xpath("//p[contains(text(),'京公網')]")
<p id="jgwab">
<i class="c-icon-jgwablogo"></i>
京公網安備11000002000001號
</p>
注:contains的另一種用法
//input[contains(@class,'s')]
說明class屬性包含s的元素。
8.5組合定位元素
//父元素標簽名/標簽名的屬性值:指的是span下的input標簽下class屬性為s_ipt的元素
find_element_by_xpath("//span/input[@class='s_ipt']")
多個屬性組合定位(挺常用的)
指的是input標簽下id屬性為kw且name屬性為wd的元素
find_element_by_xpath("//input[@class='s_ipt' and @name='wd']")
指的是p標簽下內容包含“京公網”且id屬性為jgwab的元素
find_element_by_xpath("//p[contains(text(),'京公網') and @id='jgwab']")
比較懶惰的方法:
使用搜狐瀏覽器的firebug工具,復制XPath路徑,不過這種方式對層級要求高,到時候自己再修改下。
使用:find_element(定位的類型,具體定位方式)
定位的類型包括By.ID,By.NAME,By.CLASS_NAME,By.TAG_NAME,By.LINK_TEXT,By.PARTIAL_LINK_TEXT,By.XPATH,By.CSS_SELECTOR
具體定位方式參考上方1-8的說明。
實例:find_element(By.ID,'kw')
注意:使用By定位方式,需先導入By類。
from selenium.webdriver.common.by import By
下方例子是登陸126郵件,然后發送郵件。
1 # coding=utf-8 2 ''' 3 Created on 2016-7-27 4 @author: Jennifer 5 Project:發送郵件 6 ''' 7 from selenium import webdriver 8 import time 9 10 from test_5_2_public import Login #由於公共模塊文件命名為test_5_2_public 11 driver=webdriver.Firefox() 12 driver.implicitly_wait(30) 13 driver.get(r'http://www.126.com/') #字符串加r,防止轉義。 14 time.sleep(3) 15 driver.switch_to.frame('x-URS-iframe') 16 #調用登錄模塊 17 Login().user_login(driver) 18 time.sleep(10) 19 #發送郵件 20 #點擊發件箱 21 #_mail_component_61_61是動態id,所以不能用於定位 22 #driver.find_element_by_css_selector('#_mail_component_61_61>span.oz0').click() 23 #不能加u"//span[contains(text(),u'寫 信')]",否則定位不到。 24 #以下定位是查找span標簽有個文本(text)包含(contains)'寫 信' 的元素,該定位方法重要 25 driver.find_element_by_xpath("//span[contains(text(),'寫 信')]").click() 26 #填寫收件人 27 #driver.find_element_by_class_name('nui-editableAddr-ipt').send_keys(r'xxx@doov.com.cn') 28 driver.find_element_by_class_name('nui-editableAddr-ipt').send_keys(r'xxx@163.com') 29 #填寫主題 30 #通過and連接更多的屬性來唯一地標志一個元素 31 driver.find_element_by_xpath("//input[@class='nui-ipt-input' and @maxlength='256']").send_keys(u'自動化測試') 32 #填寫正文 33 #通過switch_to_frame()將當前定位切換到frame/iframe表單的內嵌頁面中 34 driver.switch_to_frame(driver.find_element_by_class_name('APP-editor-iframe')) 35 #在內嵌頁面中定位郵件內容位置 36 emailcontext=driver.find_element_by_class_name('nui-scroll') 37 #填寫郵件內容 38 emailcontext.send_keys(u'這是第一封自動化測試郵件') 39 #通過switch_to().default_content()跳回最外層的頁面 40 #注:不要寫成switch_to().default_content(),否則報AttributeError: SwitchTo instance has no __call__ method 41 driver.switch_to.default_content() 42 #driver.switch_to.parent_frame() 43 #點擊發送 44 time.sleep(3) 45 #有可能存在元素不可見(查看元素是灰色的),會報ElementNotVisibleException錯誤 46 #包含發送二字的元素很多,所以還得再加上其他限制 47 #sendemails=driver.find_element_by_xpath("//span[contains(text(),'發送')]") 48 sendemails=driver.find_element_by_xpath("//span[contains(text(),'發送') and @class='nui-btn-text']") 49 time.sleep(3) 50 51 #校驗郵件是否發送成功 52 try: 53 assert '發送成功' in driver.page_source 54 except AssertionError: 55 print '郵件發送失敗' 56 else: 57 print '郵件發送成功' 58 59 #調用退出模塊 60 Login().user_logout(driver)
元素定位說明:
1.代碼22行,定位不到是因為id是動態的,所以需采取其他方式定位元素。
2.代碼25行,是根據元素內容來定位的,具體用法詳看8.4.
3.代碼28行,是根據class名來定位元素的,由於該值在該頁面上是唯一的,所以可以用它來定位。
4.代碼31行,是使用邏輯運算符and連接更多的屬性從而唯一的標志一個元素,具體用法詳看8.5.
5.代碼34行,由於使用內嵌的iframe框架,所以需要先使用switch_to_frame()移到該表單上,才能定位該表單上的元素,非常重要,否則無論怎么定位都會報“NoSuchElementException”,找不到該元素。
6.代碼41行,跳出iframe框架,當框架內的動作操作完畢后,需要使用switch_to.default_content跳出iframe框架,非常重要。
7.代碼47行,由於內容包括“發送”的元素中包含不可見元素(html查看元素可以看到此行是灰色的),這樣有可能定位到不可見元素,會報“ElementNotVisibleException”。
8.代碼48行,是使用邏輯運算符and連接更多的屬性從而唯一的標志一個元素,具體用法詳看8.5.這樣可以排除掉那個不可見元素。
(尊重筆者的勞動哦,轉載請說明出處哦。)