開發(fā)時(shí)有時(shí)會遇到網(wǎng)頁爬取限制的情況,那么此時(shí)可以通過 Selenium 來解決這個(gè)問題,因?yàn)?Selenium 是模擬瀏覽器執(zhí)行網(wǎng)頁爬取,相比 Request/API 操作更安全,服務(wù)器會完全認(rèn)為是用戶在用瀏覽器進(jìn)行操作,如此可以實(shí)現(xiàn)網(wǎng)頁自動化操作,由于 Selenium 是完全模擬瀏覽器操作,因此效率相比 API 更低。
1?Selenium 介紹
Selenium 簡單來說是一個(gè)用于Web應(yīng)用程序的自動化工具。
- 官方網(wǎng)址:Selenium
- 中文文檔:Selenium with Python中文翻譯文檔
- 安裝:pip install selenium?
它允許用戶使用各種編程語言(如Python, Java, C#等)來驅(qū)動自動化,實(shí)現(xiàn)模擬真實(shí)用戶在瀏覽器中的操作,如點(diǎn)擊、輸入、選擇、滾動等,可用于自動化測試或爬蟲開發(fā)。
Selenium與各種瀏覽器(如Chrome,F(xiàn)irefox,IE等)兼容,并提供交互式界面便于開發(fā)和調(diào)試。
2?驅(qū)動下載及測試
瀏覽器驅(qū)動是 Selenium 構(gòu)建瀏覽器對象的基礎(chǔ),它是一種可以讓 Selenium 與特定的瀏覽器進(jìn)行交互的組件,能將 Selenium 命令翻譯成與特定瀏覽器對應(yīng)的命令,以實(shí)現(xiàn)對瀏覽器的自動化操作。
因此瀏覽器驅(qū)動對于 Selenium 非常重要,同時(shí)針對不同的瀏覽器,需要安裝不同的驅(qū)動。下面以下載 Chrome 驅(qū)動作為演示:
2.1 確定瀏覽器版本
首先點(diǎn)擊 chrome 瀏覽器最右側(cè)的“...”圖標(biāo),然后點(diǎn)擊彈出的“幫助”中的“關(guān)于Google Chrome”,查看自己的版本信息。
這里我的版本是112.0.5615,下載對應(yīng)版本的 Chrome 驅(qū)動。
2.2 下載驅(qū)動
Chrome 驅(qū)動鏈接:https://chromedriver.storage.googleapis.com/index.html
打開該鏈接,選擇對應(yīng)的版本單機(jī)(二選一)
?由于我是使用 Window 環(huán)境進(jìn)行開發(fā),因此下載 window 版本驅(qū)動,按操作系統(tǒng)進(jìn)行下載即可。
解壓后有兩個(gè)文件,我們需要的是 .exe 后綴的驅(qū)動。
2.3 測試驅(qū)動
接下來就是測試驅(qū)動成功與否了,我將其放到項(xiàng)目的根目錄下(大家可自行選擇放位置,Selenium 需要的是讀取該驅(qū)動的路徑)
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
執(zhí)行該文件,驅(qū)動成功啟動 Chrome 瀏覽器 ??
3 模擬瀏覽器及頁面相關(guān)操作
Selenium 實(shí)現(xiàn)網(wǎng)頁自動化首先是從一個(gè)網(wǎng)站開始的,簡單來說就是如何操作瀏覽器,有了瀏覽器對象,我們才可以針對請求頁面進(jìn)行操作。
3.1 創(chuàng)建及關(guān)閉瀏覽器對象
executable_path 指定的是瀏覽器驅(qū)動的路徑,我這里是相對路徑,絕對路徑也可。
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#關(guān)閉瀏覽器
driver.close() #關(guān)閉當(dāng)前頁面,但瀏覽器驅(qū)動會殘留影響內(nèi)存
driver.quit() #關(guān)閉當(dāng)前頁面 + 瀏覽器驅(qū)動
3.2 設(shè)置瀏覽器大小
而maximize_window則是設(shè)置瀏覽器為全屏,set_window_size()方法用來設(shè)置瀏覽器大?。ň褪欠直媛剩?/p>
import time
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#1.瀏覽器最大化
driver.maximize_window()
time.sleep(2)
#2.獲取當(dāng)前瀏覽器尺寸
size = driver.get_window_size()
print(size)
#3.設(shè)置當(dāng)前瀏覽器尺寸
driver.set_window_size(400, 400)
time.sleep(2)
size = driver.get_window_size()
print(size)
#關(guān)閉瀏覽器
driver.quit()
3.3 訪問頁面
通過 driver.get 方法進(jìn)行頁面訪問,傳入?yún)?shù)即為 url 地址。
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#打開網(wǎng)頁地址
driver.get('https://www.baidu.com/')
#關(guān)閉瀏覽器
driver.quit()
3.4 獲取頁面相關(guān)屬性
通過 Selenium 打開網(wǎng)頁,可以獲取網(wǎng)頁標(biāo)題、網(wǎng)址、頁面源碼等信息。
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#打開網(wǎng)頁地址
driver.get('https://www.baidu.com/')
#1.獲取當(dāng)前頁面標(biāo)題
title = driver.title
print(title)
#2.獲取當(dāng)前頁面地址
url = driver.current_url
print(url)
#3.獲取當(dāng)前頁面標(biāo)源代碼
source = driver.page_source
print(source)
#關(guān)閉瀏覽器
driver.quit()
控制臺輸出:
?3.5 頁面前進(jìn)、后退、截圖
import time
# 導(dǎo)入webdriver
from selenium import webdriver
# 創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path='./chromedriver.exe')
#1.打開 baidu
driver.get('https://www.baidu.com/')
time.sleep(2)
#2.打開bilibili頁面
driver.get('https://www.bilibili.com/')
time.sleep(2)
#3.頁面回退到 baidu
driver.back()
#4.頁面前進(jìn)
driver.forward()
#5.頁面刷新
driver.refresh()
#6.頁面截圖
#(1)方式一
data = driver.get_screenshot_as_png()
with open('bi1.jpg','wb') as f:
f.write(data)
#(2)方式二
driver.get_screenshot_as_file('bi2.png')
#關(guān)閉瀏覽器
driver.quit()
4 頁面元素定位
通過 Selenium 進(jìn)入對應(yīng)的頁面后,便可對頁面中的元素(按鈕、輸入框等)進(jìn)行操作,可分為兩步:
- 定位元素信息,返回元素對象
- 調(diào)用方法完成元素的模擬操作
通過 Selenium 進(jìn)行頁面元素定位的前提是基本了解前端的頁面布局及各種標(biāo)簽含義,首先我們簡單地過一下。以百度官網(wǎng)為例,按【F12】或者右鍵檢查進(jìn)入開發(fā)者工具,紅框中顯示的就是頁面元素代碼(HTML樣式),我們要做的就是從元素代碼中定位獲取我們需要的元素。
接下來我們來進(jìn)行元素定位的學(xué)習(xí),Selenium 對此提供了一系列的方法,主要包括以下這七種,一般來說 id 和 name 在當(dāng)前頁面是唯一的,xpath 使用也較為普遍。
webdriver 對象的find_element 方法用于定位單個(gè)元素,find_elements 方法用于定位元素集合(如find_elements_by_id('')? )。
4.1?id 屬性定位
我們選擇輸入框并右鍵點(diǎn)擊檢查元素,即可定位到該輸入框的元素信息。其中 input 是該元素的標(biāo)簽名(tag_name);id、name、calss 等鍵值對均為該元素的屬性,可用于元素定位。因此該輸入框元素的 id 屬性為 'kw'。
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#1.id屬性定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_id('kw')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
4.2?name 屬性定位
同上,該輸入框元素的 name 屬性為 'wd'。
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#2.name屬性定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_name('wd')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
4.3?class 屬性定位
該輸入框元素的 class 屬性為 's_ipt',但是 class 屬性經(jīng)常會重復(fù),需要保證其唯一方可正確定位,該頁面的 class 屬性正好唯一,因此可進(jìn)行 class 屬性定位。
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#3.class屬性定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_class_name('s_ipt')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
4.4?tag 標(biāo)簽定位
tag 標(biāo)簽若要正確定位,也必須保證其唯一性,但是輸入框元素的 tag name = input,不符合唯一性的要求,因此用 tag name = textarea 的元素進(jìn)行測試~
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#4.tag標(biāo)簽定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_tag_name('textarea')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
4.5 link_text 鏈接文本定位
①?find_element_by_link_text 全文本
如上圖,標(biāo)簽的><之間存在文本,這種元素則可以通過鏈接文本定位的方式定位。
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#5.link_text 全鏈接文本定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_link_text('更多')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
② find_element_by_link_text 部分文本
?如圖,我們通過鏈接文本形式進(jìn)行元素定位有時(shí)會遇到文本過長的情況,此時(shí)可以通過部分文本匹配元素!
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#5.link_text 部分鏈接文本定位,傳回一個(gè)元素對象
element_input = driver.find_element_by_partial_link_text('更')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
4.6?css 選擇器定位
大家如果有了解前端的話,對css應(yīng)該蠻熟悉,它用來描述THML和XML的元素顯示樣式,在css語言中有 css選擇器,在Selenium中也可以使用這種選擇器來定位元素。
①?css結(jié)合基本屬性定位
css選擇器也支持基本屬性(id、class、tag)定位方式。
語法:
- driver.find_element_by_css_selector("#id值") #css+id定位
- driver.find_element_by_css_selector(".class值") #css+class定位
- driver.find_element_by_css_selector("標(biāo)簽名") #css+標(biāo)簽定位
參數(shù)說明:
- #:井號代表id(類似 id = id值)
- . : 點(diǎn)代表class(類似 class = class值)
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.1css結(jié)合基本屬性定位(id,class,標(biāo)簽)
element_input1 = driver.find_element_by_css_selector('#kw') #id
element_input2 = driver.find_element_by_css_selector('.s_ipt') #class
element_input3 = driver.find_element_by_css_selector('textarea') #標(biāo)簽
print(element_input1)
print(element_input2)
print(element_input3)
#關(guān)閉瀏覽器
driver.quit()
② css結(jié)合其他屬性定位
語法:
- driver.find_element_by_css_selector('[屬性名=屬性值]') #css+其他屬性
- driver.find_element_by_css_selector('[屬性名1=屬性值1][屬性名2=屬性值2]') #css+多個(gè)其他屬性
參數(shù)說明:
- [] :用方括號來指定屬性
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.2css其他屬性定位
element_input = driver.find_element_by_css_selector("[id='kw'][name='wd']")
#其他屬性定位
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
③ css標(biāo)簽結(jié)合其他屬性定位
我們也可以通過標(biāo)簽+屬性來進(jìn)行定位
語法:
- driver.find_element_by_css_selector(‘標(biāo)簽名#id值’) #標(biāo)簽+id屬性定位
- driver.find_element_by_css_selector(‘標(biāo)簽名.class值’) #標(biāo)簽+class屬性定位
- driver.find_element_by_css_selector('標(biāo)簽名[屬性名=屬性值]') #標(biāo)簽+其他屬性定位
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.3css標(biāo)簽結(jié)合其他屬性定位
element_input1 = driver.find_element_by_css_selector('input#kw') #id
element_input2 = driver.find_element_by_css_selector('input.s_ipt') #class
element_input3 = driver.find_element_by_css_selector("input[name='wd']") #標(biāo)簽
print(element_input1)
print(element_input2)
print(element_input3)
#關(guān)閉瀏覽器
driver.quit()
④ css層級定位
在定位某個(gè)元素時(shí),若無簡潔標(biāo)簽屬性可供參考,我們可以先定位到該元素的上級或上上級元素,隨后通過層級關(guān)系獲取該元素的位置。
語法:
- driver.find_element_by_css_selector('標(biāo)簽1>標(biāo)簽2')
參數(shù)說明:
- 標(biāo)簽1>標(biāo)簽2: 表示父級定位到子級
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.4css層級定位
element_input = driver.find_element_by_css_selector('form>span>input#kw')
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
⑤?css索引定位
如上圖,“新聞”按鈕同級目錄下存在6個(gè)與他一樣的a標(biāo)簽,因此像這種有多個(gè)相同標(biāo)簽名的元素,可以使用索引定位,通過索引來指定具體哪個(gè) a 標(biāo)簽的元素。
注:與python列表索引的概念不同,此處的標(biāo)簽索引是從1開始;python列表的索引是從0開始。
語法:
- driver.find_element_by_css_selector('標(biāo)簽:nth-child(n)') #正著數(shù)第n個(gè)標(biāo)簽
- driver.find_element_by_css_selector('標(biāo)簽:nth-last-child(n)') #倒著數(shù)第n個(gè)標(biāo)簽
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.5css索引定位
element_input1 = driver.find_element_by_css_selector('div#s-top-left>a:nth-child(1)') #正著數(shù)第1個(gè)a
element_input2 = driver.find_element_by_css_selector('div#s-top-left>a:nth-last-child(7)') #倒著數(shù)第7個(gè)a
print(element_input1)
print(element_input2)
#關(guān)閉瀏覽器
driver.quit()
⑤?css模糊匹配
有時(shí)也會遇到屬性值過長的情況,此時(shí)我們可以通過模糊匹配來處理,只需要屬性值的部分內(nèi)容即可。
語法:
- driver.find_element_by_css_selector("[屬性名~='部分屬性值']")?#1.屬性值由多個(gè)空格隔開,匹配其中一個(gè)值的方法
- driver.find_element_by_css_selector("[屬性名^='屬性值開頭']") #2.匹配字符串開頭
- driver.find_element_by_css_selector("[屬性名$='屬性值結(jié)尾']")?#3.匹配字符串結(jié)尾
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#6.6css模糊匹配
element_input1 = driver.find_element_by_css_selector("input[class~='s_btn']")
element_input2 = driver.find_element_by_css_selector("input[class^='bg']")
element_input3 = driver.find_element_by_css_selector("input[class$='s_btn']")
print(element_input1)
print(element_input2)
print(element_input3)
#關(guān)閉瀏覽器
driver.quit()
4.7?xpath 表達(dá)式定位
其實(shí) xpath 定位和 css 選擇器類似,只是寫法有所區(qū)別。Selenium 元素定位的基礎(chǔ)方法(比如通過id、name、class_name等)局限性較大,首先各元素不一定都有 id 屬性,其次元素的id屬性也并非固定不變,因此我們真正需要熟練掌握的是通過 xpath 和 css 定位,一般掌握其中一種即可應(yīng)對大部分定位工作,xpath 更為常用。
xpath 使用路徑表達(dá)式在 XML 文檔中選取節(jié)點(diǎn)。節(jié)點(diǎn)是通過沿著路徑或者 step 來選取的。 下面列出了最有用的路徑表達(dá)式:
① xpath結(jié)合屬性定位
語法:
- driver.find_element_by_xpath(".//input[@id='kw']")? #單個(gè)屬性定位
- driver.find_element_by_xpath(".//input[@id='kw' and @name='wd']")? #多個(gè)屬性定位
參數(shù)說明:
- [] :表示要根據(jù)屬性找元素
- @ :后邊跟屬性的key,表示要通過哪個(gè)屬性定位
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#7.1xpath結(jié)合屬性定位
element_input1 = driver.find_element_by_xpath(".//input[@id='kw']")
element_input2 = driver.find_element_by_xpath(".//input[@id='kw' and @name='wd']")
print(element_input1)
print(element_input2)
#關(guān)閉瀏覽器
driver.quit()
②?xpath文本定位
標(biāo)簽文本是><里邊的字符串,非鍵值對。
語法:
- driver.find_element_by_xpath(".//a[text()='更多']")
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#7.2xpath文本定位
element_input = driver.find_element_by_xpath(".//a[text()='更多']")
print(element_input)
#關(guān)閉瀏覽器
driver.quit()
③ xpath層級定位
實(shí)際開發(fā)時(shí),若需求元素沒有像 id、name、class 等基本屬性,那么我們就需要借助相鄰的元素定位,首先我們可以定位到相鄰元素,然后通過層級關(guān)系來定位最終元素。
語法:
- driver.find_element_by_xpath(".//form[@id='form']/span/input") #由上到下的層級關(guān)系
- driver.find_element_by_xpath(".//input[@class='s_ipt']/parent::span") #父子元素定位
- driver.find_element_by_xpath(".//input[@class='s_ipt']//preceding-sibling::span") #哥哥元素定位
- driver.find_element_by_xpath(".//input[@class='s_ipt']//following-sibling::i") #弟弟元素定位
參數(shù)說明:
- parent::span :向父級定位,父級的標(biāo)簽名為span
- preceding-sibling::span :向哥哥級定位,哥哥級的標(biāo)簽名為span
- following-sibling::span :向弟弟級定位,弟弟級的標(biāo)簽名為i
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#7.3 xpath層級定位
element_input1 =driver.find_element_by_xpath(".//form[@id='form']/span/input")#由上到下的層級關(guān)系
element_input2 =driver.find_element_by_xpath(".//input[@class='s_ipt']/parent::span")#父子元素定位
element_input3 =driver.find_element_by_xpath(".//input[@class='s_ipt']//preceding-sibling::span") #哥哥元素定位
element_input4 =driver.find_element_by_xpath(".//input[@class='s_ipt']//following-sibling::i") #弟弟元素定位
print(element_input1)
print(element_input2)
print(element_input3)
print(element_input4)
#關(guān)閉瀏覽器
driver.quit()
④ xpath索引定位
xpath 的標(biāo)簽索引也是從1開始的。
語法:
- driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")? #根據(jù)索引選擇標(biāo)簽
- driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()]")? #最后一個(gè)標(biāo)簽
- driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()-1]")? #倒數(shù)第二個(gè)標(biāo)簽
參數(shù)說明:
- 1 :指同名標(biāo)簽的第一個(gè)標(biāo)簽
- last() :指同名標(biāo)簽的最后一個(gè)標(biāo)簽
- last()-1 :指同名標(biāo)簽的倒數(shù)第二個(gè)標(biāo)簽
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#7.4xpath索引定位
element_input1 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]") #根據(jù)索引選擇標(biāo)簽
element_input2 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()]") #最后一個(gè)標(biāo)簽
element_input3 = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[last()-1]") #倒數(shù)第二個(gè)標(biāo)簽
print(element_input1)
print(element_input2)
print(element_input3)
#關(guān)閉瀏覽器
driver.quit()
⑤?xpath模糊匹配
語法:
- driver.find_element_by_xpath(".//span[starts-with(@class, 'soutu-hover')]")? #匹配開頭
- driver.find_element_by_xpath(".//span[ends-with(@class, 'hover-tip')]")? #匹配結(jié)尾
- driver.find_element_by_xpath(".//span[contains(text(), '搜索')]") #包含“搜索”
ends-with方法是xpath 2.0的語法,而瀏覽器只支持xpth 1.0,因此可能會出現(xiàn)報(bào)錯(cuò)。
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#7.5xpath模糊定位
element_input1 = driver.find_element_by_xpath(".//span[starts-with(@class,'soutu-hover')]") #匹配開頭
element_input2 = driver.find_element_by_xpath(".//span[ends-with(@class,'hover-tip')]") #匹配結(jié)尾
element_input3 = driver.find_element_by_xpath(".//span[contains(text(), '搜索')]") #包含匹配
print(element_input1)
print(element_input2)
print(element_input3)
#關(guān)閉瀏覽器
driver.quit()
5?模擬操作頁面元素
定位元素后,我們將得到一個(gè)元素對象,接下來便是針對這個(gè)元素對象做模擬操作。
5.1?按鈕點(diǎn)擊操作
語法:
- element.click() #對象.方法
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#1.按鈕點(diǎn)擊操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
#關(guān)閉瀏覽器
driver.quit()
5.2?文本框操作
語法:
- element.send_keys('python') #輸入
- element.clear() #清空文本框
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#2.文本框操作
element = driver.find_element_by_id("kw")
element.send_keys('python') #輸入
element.clear() #清空文本框
#關(guān)閉瀏覽器
driver.quit()
5.3 獲取元素文本
語法:
- element.text? #text不是方法,不加括號
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#3.獲取標(biāo)簽文本
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
s = element.text #獲取文本
print(s)
#關(guān)閉瀏覽器
driver.quit()
5.4 獲取元素屬性
語法:
- element.get_attribute(屬性名) #入?yún)榫唧w屬性名,如 id、class 等
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
#4.獲取標(biāo)簽屬性值
element = driver.find_element_by_xpath(".//input[@id='su']")
s1 = element.get_attribute('class') #獲取 class 屬性值
s2 = element.get_attribute('value') #獲取 value 屬性值
print(s1)
print(s2)
#關(guān)閉瀏覽器
driver.quit()
6 切換頁面的iframe、handlers
實(shí)際開發(fā)時(shí),我們經(jīng)常會遇到iframe和handler兩種窗口切換。Iframe指的是在主html中嵌入子html頁面,即一個(gè)頁面中嵌套著一個(gè)或多個(gè)頁面;Handler指的是新的頁面選項(xiàng)卡,即瀏覽器上方增加了一個(gè)頁面。在使用Handler切換后,我們的操作仍然在原來的窗口,如果需要在新的窗口中繼續(xù)操作元素,則需要使用handle窗口切換方法。
6.1?iframe切換
圖中陰影部分就是 iframe,可以理解為頁面中嵌套著一個(gè)小頁面,如果我們想要定位賬號密碼輸入框,必須先切換到小頁面才能定位,否則將會報(bào)錯(cuò)。
語法:
- driver.switch_to.frame(value) #1.直接使用id值切換,如果iframe標(biāo)簽中有id屬性,可以用這個(gè)方法直接傳id的值
- driver.switch_to.frame(driver.find_element_by_xxx(value)) #2.通過出入元素對象切換
- driver.switch_to.parent_frame()?#3.跳回上層的頁面
- driver.switch_to.default_content()?#4.跳回最外層的頁面
import time
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://mail.163.com/')
# 定位到iframe,并切換
el_iframe = driver.find_element_by_xpath(".//div[@id='loginDiv']/iframe")
driver.switch_to.frame(el_iframe)
# 先定位,輸入用戶名
el_username = driver.find_element_by_name("email")
el_username.send_keys('yinyu123')
time.sleep(2)
# 關(guān)閉瀏覽器
driver.quit()
6.2?handler切換
當(dāng)我們點(diǎn)擊百度首頁的新聞按鈕,會彈出一個(gè)新窗口。若要訪問新聞頁的元素,則需要先切換至該窗口,否則無法獲取。
語法:
- driver.window_handles #1.獲取當(dāng)前打開的所有窗口句柄,返回類型為一個(gè)列表,window_handles是對象屬性,沒有括號
- driver.current_window_handle #2.獲取當(dāng)前窗口的句柄
- driver.switch_to.window(handle_id)?#3.切換窗口,handle_id參數(shù)代表的是一個(gè)窗口句柄
import time
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
# 按鈕點(diǎn)擊操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]") #新聞按鈕
element.click()
time.sleep(3)
#1.獲取當(dāng)前瀏覽器的全部窗體
all_handles = driver.window_handles
#2.切換到最新的窗體
driver.switch_to.window(all_handles[-1])
#3.獲取當(dāng)前標(biāo)題
print(driver.title) #輸出【百度新聞——海量中文資訊平臺】,說明切換成功
# 關(guān)閉瀏覽器
driver.quit()
7?三種元素等待方式
實(shí)際開發(fā)中,定位元素時(shí)經(jīng)常會碰到元素加載慢的情況(元素加載需要一個(gè)時(shí)間,比如我們平時(shí)用瀏覽器也會遇到網(wǎng)頁加載慢情形)。如果元素還未加載完,此時(shí)進(jìn)行點(diǎn)擊操作則是無效的,前邊有提到使用 time.sleep() 方法進(jìn)行頁面等待,這就是元素等待的一種。
測試流程 ??
7.1 強(qiáng)制等待
最簡單粗暴的方式就是強(qiáng)制等待 sleep(xx),不論元素加載成功與否,都必須等待 xx 時(shí)間。但是該方式較為死板,嚴(yán)重影響執(zhí)行速度。
語法:
- time.sleep(3)
import time
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
# 按鈕點(diǎn)擊操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 強(qiáng)制等待3秒
time.sleep(3)
# 頁面跳轉(zhuǎn)
driver.switch_to.window(driver.window_handles[1]) # 此行代碼用來定位新跳出的頁面
print(driver.title)
# 獲取輸出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)
#關(guān)閉瀏覽器
driver.quit()
7.2 隱式等待
隱式等待設(shè)置了一個(gè)最長等待時(shí)間,若網(wǎng)頁在規(guī)定時(shí)間內(nèi)加載完成,程序執(zhí)行下一步,否則一直等待直至?xí)r間截止,才執(zhí)行下一步。然而,此方法存在一個(gè)缺陷,即程序會一直等待整個(gè)頁面加載完成,即使有時(shí)頁面所需元素早已加載完成,但是由于某些 js 等因素導(dǎo)致加載緩慢。
語法:
- driver.implicitly_wait(5)
import time
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
# 按鈕點(diǎn)擊操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 頁面跳轉(zhuǎn)
time.sleep(1) #保證頁面跳轉(zhuǎn)成功
driver.switch_to.window(driver.window_handles[1]) # 此行代碼用來定位新跳出的頁面
#隱式等待
driver.implicitly_wait(5)
# 獲取輸出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)
#關(guān)閉瀏覽器
driver.quit()
7.3 顯式等待
使用顯式等待,結(jié)合WebDriverWait類的until()和until_not()方法,即可根據(jù)需求靈活等待。通俗來講,程序每隔一定時(shí)間檢查一次條件是否成立,如果成立則繼續(xù)執(zhí)行,否則持續(xù)等待直至超時(shí),最后拋出TimeoutException異常。
①?WebDriverWait 舉例
語法:
- WebDriverWait(driver,10,0.5).until(EC.presence_of_element_located(locator)) #最長時(shí)間10秒鐘,每0.5秒判斷該元素是否加載成功
import time
# 導(dǎo)入webdriver
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://www.baidu.com/')
# 按鈕點(diǎn)擊操作
element = driver.find_element_by_xpath(".//div[@id='s-top-left']/a[1]")
element.click()
# 頁面跳轉(zhuǎn)
time.sleep(1) #保證頁面跳轉(zhuǎn)成功
driver.switch_to.window(driver.window_handles[1]) # 此行代碼用來定位新跳出的頁面
# 顯性等待
locator = (By.XPATH,".//a[@data-control='pane-news']")
WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located(locator))
# 獲取輸出文本
text = driver.find_element_by_xpath(".//a[@data-control='pane-news']").text
print(text)
#關(guān)閉瀏覽器
driver.quit()
② 顯性等待之EC模塊
顯示等待經(jīng)常會使用 EC 模塊,WebDriverWait的until和until_not方法中我們經(jīng)常要用到,它會根據(jù)網(wǎng)頁標(biāo)題、網(wǎng)址以及元素是否可見等條件來決定我們是否需要繼續(xù)等待。
引入相關(guān)模塊:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
判定方法匯總:
#1.判斷當(dāng)前頁面的title是否完全等于(==)預(yù)期字符串,返回是布爾值
title_is
#2.判斷當(dāng)前頁面的title是否包含預(yù)期字符串,返回布爾值
title_contains
#3.判斷某個(gè)元素是否已被加載,并不代表該元素一定可見
presence_of_element_located
#4.判斷某個(gè)元素是否可見,可見代表元素非隱藏,并且元素的寬和高都不等于0
visibility_of_element_located
#5.跟上面的方法做一樣的事情,只是上面的方法要傳入locator,這個(gè)方法直接傳定位到的element
就好了
visibility_of
#6.判斷是否至少有1個(gè)元素存在于dom樹中。舉個(gè)例子,如果頁面上有n個(gè)元素的class都是'column-md-3',那么只要有1個(gè)元素存在,這個(gè)方法就返回True
presence_of_all_elements_located
#7.判斷某個(gè)元素中的text是否包含了預(yù)期的字符串
text_to_be_present_in_element
#8.判斷某個(gè)元素中的value屬性是否包含了預(yù)期的字符串
text_to_be_present_in_element_value
#9.判斷該frame是否可以switch進(jìn)去,如果可以的話,返回True并且switch進(jìn)去,否則返回False
frame_to_be_available_and_switch_to_it
#10.判斷某個(gè)元素中是否不存在于dom樹或不可見
invisibility_of_element_located
#11.判斷某個(gè)元素中是否可見并且是enable的,這樣的話才叫clickable
element_to_be_clickable
#12.等某個(gè)元素從dom樹中移除,注意,這個(gè)方法也是返回True或False
staleness_of
#13.判斷某個(gè)元素是否被選中了,一般用在下拉列表>* element_selection_state_to_be:判斷
某個(gè)元素的選中狀態(tài)是否符合預(yù)期
element_to_be_selected
#14.跟上面的方法作用一樣,只是上面的方法傳入定位到的element,而這個(gè)方法傳入locator
element_located_selection_state_to_be
#15.判斷頁面上是否存在alert彈出框
alert_is_present
8 實(shí)現(xiàn)163郵箱自動化登錄
8.1 元素定位快速驗(yàn)證
比如我想定位“賬號登陸”元素,編寫完 xpath 信息后,可在右邊代碼處 ctrl+f 彈出定位輸入框,將編寫完的 xpath 信息填入即可,若匹配準(zhǔn)確將自動定位, 該定位輸入框也支持 css 選擇器。
id、name、class 等單屬性的 xpath 表達(dá)式:
//*[@id='id值']
//*[@name='name值']
//*[@iclass ='class 值']文章來源:http://www.zghlxwxcb.cn/news/detail-424228.html
8.2 163郵箱登錄實(shí)戰(zhàn)
最后來實(shí)戰(zhàn)下,通過 Selenium 實(shí)現(xiàn)163郵箱自動化登錄!文章來源地址http://www.zghlxwxcb.cn/news/detail-424228.html
# 導(dǎo)入webdriver
from selenium import webdriver
#獲取驅(qū)動路徑
driver_path = './chromedriver.exe'
#創(chuàng)建一個(gè)瀏覽器對象
driver = webdriver.Chrome(executable_path=driver_path)
#設(shè)置全屏
driver.maximize_window()
#請求某個(gè)url
driver.get('https://mail.163.com/')
#定位到iframe,并切換
el_iframe = driver.find_element_by_xpath(".//div[@id='loginDiv']/iframe")
driver.switch_to.frame(el_iframe)
#先定位,輸入用戶名
el_username = driver.find_element_by_name("email")
el_username.send_keys('yinyu123')
#先定位,輸入密碼
el_psw = driver.find_element_by_name("password")
el_psw.send_keys('xxxx')
#先定位,點(diǎn)擊登錄
el_login = driver.find_element_by_id("dologin")
el_login.click()
#切到最外層iframe
driver.switch_to.default_content()
#隱式等待
driver.implicitly_wait(5)
#斷言是否登錄成功
username_text = driver.find_element_by_xpath(".//div[@class='gWel-greet']/span/span[1]").text
assert username_text == 'yinyu123','斷言失敗:{}'.format(username_text)
print("登錄成功")
#關(guān)閉瀏覽器
driver.quit()
到了這里,關(guān)于【RPA開發(fā)】Selenium 實(shí)現(xiàn)網(wǎng)頁自動化的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!