Python Selenium.WebDriverWait 網頁加載策略『詳細』
文章目錄
- Python Selenium.WebDriverWait 網頁加載策略『詳細』
- 一、網頁加載策略🍗
- 二、加載策略種類
- 三、配置加載策略
- 四、對加載策略進行封裝🎍
- 五、配合顯示等待使用加載策略
- 六、Selenium4對加載策略的改動💣
- 參考文獻💗
- 相關博客🤩
一、網頁加載策略🍗
在通過Selenium加載一個網頁時,Selenium都會等待頁面加載完了才會運行下面的代碼,這是因為 webdriver.get 方法會阻塞直到網頁全部加載完成,

通常如果當頁面加載花費大量時間時,可能是加載了很多外部資源「如:影像、css」,又或則是瀏覽的是國外網站,使用的網路環境差等問題,這些都是造成頁面加載慢的原因,
但對于某些網頁來說,需要加載的元素往往比不需要使用到的網頁更快的加載出來,那么如何才能在加載到需要的資料之后就停止阻塞并且執行 webdriver.get 方法下的代碼是本文章要探究的問題,
二、加載策略種類
Selenium支持的加載策略有三種,分別是none、eager、normal,且提供自帶的方法讓我們去設定啟動策略,
| 關鍵字 | 加載策略狀態 | 描述 |
|---|---|---|
| none | 沒有 | 等待html下載完成,不等待決議完成就開始執行操作,selenium 會直接回傳 |
| eager | 渴望 | 等待整個dom樹加載完成,即DOMContentLoaded這個事件完成, 只要 HTML 完全加載和決議完畢就開始執行操作,忽略加載樣式表、影像和子框架 |
| normal | 正常(默認) | 等待整個頁面加載完畢再開始執行操作 |
在瀏覽器選項類的原始碼中能夠看到,Selenium已經寫好了設定加載策略的方法,同時也限制了加載策略的種類『原始碼第13行』
class Options(object):
def __init__(self):
self._page_load_strategy = "normal"
self._caps = DesiredCapabilities.EDGE.copy()
@property
def page_load_strategy(self):
return self._page_load_strategy
@page_load_strategy.setter
def page_load_strategy(self, value):
if value not in ['normal', 'eager', 'none']:
raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
......
三、配置加載策略
每種型別的 webdriver 都有一個對應的組態檔放在特定的類 DesiredCapabilities 里面,這個組態檔的資料結構為字典格式,通過定義鍵為 pageLoadStrategy 的鍵值對,可以使webdriver的頁面加載策略發生改變,
模塊位置 👇
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
1)、原始碼中是這么去使用加載策略的👇
可以看到,原始碼實質上就是在 DesiredCapabilities 組態檔中增加了一個pageLoadStrategy屬性值『原始碼第32行』,而 page_load_strategy 則是 Selenium 提供設定加載策略的方法,
對于DesiredCapabilities類,在博客 Python Selenium.WebDriverWait 瀏覽器啟動引數設定『Edge如何使用啟動引數』 中也有提到過,不管是在瀏覽器啟動引數類 Options 原始碼中,還是自定義的 Options 啟動引數類中,都會用的上,本篇文章相當于對 Python Selenium.WebDriverWait 瀏覽器啟動引數設定『Edge如何使用啟動引數』 的擴展,
Options選項類部分原始碼
class Options(object):
def __init__(self):
self._page_load_strategy = "normal"
self._caps = DesiredCapabilities.EDGE.copy()
......
@property
def page_load_strategy(self):
return self._page_load_strategy
@page_load_strategy.setter
def page_load_strategy(self, value):
if value not in ['normal', 'eager', 'none']:
raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
@property
def capabilities(self):
return self._caps
......
def to_capabilities(self):
"""
Creates a capabilities with all the options that have been set and
returns a dictionary with everything
"""
caps = self._caps
caps['pageLoadStrategy'] = self._page_load_strategy
return caps
DesiredCapabilities 部分原始碼
class DesiredCapabilities(object):
......
FIREFOX = {
"browserName": "firefox",
"marionette": True,
"acceptInsecureCerts": True,
}
INTERNETEXPLORER = {
"browserName": "internet explorer",
"version": "",
"platform": "WINDOWS",
}
EDGE = {
"browserName": "MicrosoftEdge",
"version": "",
"platform": "WINDOWS"
}
CHROME = {
"browserName": "chrome",
"version": "",
"platform": "ANY",
}
......
2)、更改使用加載策略:👇
-
使用
page_load_strategy方法更改加載策略:from selenium import webdriver from selenium.webdriver.edge.options import Options def timer(func): """計時裝飾器,用于計算程式運行時間""" def inner(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(f"加載時間:{time.time() - start_time}") return res return inner @timer def get_url(browser_, url_): """對頁面發起請求""" browser_.get(url_) if __name__ == '__main__': url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501" op = Options() # 設定頁面加載策略為none # op.page_load_strategy = "none" # 設定頁面加載策略為normal # op.page_load_strategy = "eager" browser = webdriver.Edge("msedgedriver 97.exe", capabilities=op.to_capabilities()) get_url(browser, url)程式流程:
使用 Edge 瀏覽器對目標網址發起請求,timer為裝飾器方法進行計時,對發起請求的get_url函式進行計時,分別計算各瀏覽器加載策略的耗時
normal加載時間: 3.539372682571411
eager加載時間: 2.0514888763427734
none加載時間: 0.003000974655151367 -
使用原生方法手動配置加載策略:
可以看到其實就是先將選項類的配置轉換為字典,再為這個字典添加鍵為
pageLoadStrategy的鍵值對,再將這個字典傳入瀏覽器的實體化引數中,from selenium import webdriver from selenium.webdriver.chrome.options import Options def timer(func): """計時裝飾器,用于計算程式運行時間""" def inner(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) print(f"加載時間:{time.time() - start_time}") return res return inner @timer def get_url(browser_, url_): """對頁面發起請求""" browser_.get(url_) if __name__ == '__main__': url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501" op = Options() capabilities = op.to_capabilities() # 設定頁面加載策略為none capabilities["pageLoadStrategy"] = "none" # 設定頁面加載策略為normal # capabilities["pageLoadStrategy"] = "eager" browser = webdriver.Chrome("chromedriver 97.exe", desired_capabilities=capabilities) get_url(browser, url)程式流程:
使用 Chrome 瀏覽器對目標網址發起請求,timer為裝飾器方法進行計時,對發起請求的get_url函式進行計時,分別計算各瀏覽器加載策略的耗時
normal加載時間: 3.847010850906372
eager加載時間: 2.529080390930176
none加載時間: 0.002000093460083008
DesiredCapabilities類,其本質就是存放著關于瀏覽器啟動的組態檔,
在Selenium3中,不同瀏覽器的Options選項類原始碼存在部分差異,為方便展示,上述參考原始碼使用的是Edge瀏覽器的選項類,
對于每次運行的計時結果,都會有差異,
四、對加載策略進行封裝🎍
在上述 page_load_strategy 方法示例中,使用到 Edge 瀏覽器進行示例,不用 Chrome 瀏覽器是因為在 Chrome 的選項類中并沒有自帶加載策略方法供我們去使用,需要手動配置加載策略或則直接對這個方法進行自定義封裝,

將 Edge 和 Chrome 加載策略配置好之后,在寫法一樣的情況下分別呼叫 to_capabilities 方法輸出配置策略對其進行對比,會發現 Chrome 選項類的配置中少了 pageLoadStrategy 值,主要差異體現在有沒有配置 pageLoadStrategy 值的加載策略
1)、Edge瀏覽器加載配置
配置部分代碼
......
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = Options()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
# 列印配置策略
print(op.to_capabilities())
browser = webdriver.Edge("msedgedriver 97.exe", capabilities=op.to_capabilities())
get_url(browser, url)

2)、Chrome瀏覽器加載配置
配置部分代碼
......
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = Options()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
# 列印配置策略
print(op.to_capabilities())
browser = webdriver.Chrome("chromedriver 97.exe", options=op)
get_url(browser, url)

3)、Chrome加載策略封裝
在繼承原有 Chrome 選項類的基礎上,自定義加載策略方法,通過這種形式就可以彌補某些瀏覽器啟動引數類方法不全的問題,或撰寫提升效率的方法
Chrome封裝加載策略類
class ChromeOptions(Options):
def __init__(self):
super(ChromeOptions, self).__init__()
self._page_load_strategy = "normal"
@property
def page_load_strategy(self):
return self._page_load_strategy
@page_load_strategy.setter
def page_load_strategy(self, value):
"""設定加載策略方法"""
if value not in ['normal', 'eager', 'none']:
raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
def to_capabilities(self):
"""使用已設定的所有啟動引數,并回傳包含所有內容的字典"""
caps = self._caps
chrome_options = self.experimental_options.copy()
chrome_options["extensions"] = self.extensions
if self.binary_location:
chrome_options["binary"] = self.binary_location
chrome_options["args"] = self.arguments
if self.debugger_address:
chrome_options["debuggerAddress"] = self.debugger_address
# 添加加載策略鍵值對
caps["pageLoadStrategy"] = self._page_load_strategy
caps[self.KEY] = chrome_options
return caps
呼叫執行
可以看到,需要的 pageLoadStrategy 值已被成功添加,且程式也能正常使用自定義的加載策略
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = ChromeOptions()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
# 列印配置策略
print(op.to_capabilities())
browser = webdriver.Chrome("chromedriver 97.exe", options=op)
get_url(browser, url)

五、配合顯示等待使用加載策略
通過更改加載策略,Selenium不再等待頁面加載完畢后才會執行 webdriver.get 下面的代碼, 但這也會造成一個問題,在 webdriver.get 下面的代碼通常都是頁面元素的獲取代碼,但在頁面沒有加載結束的情況下去獲取會造成程式拋出例外,
1)、顯示等待
為了解決這個問題,這時候就需要用上 Selenium 的顯示等待,
使用 Selenium 時能用上的等待方式共有三種,分別是顯示等待、隱性等待、強制等待,這里只稍微提及一下顯示等待,顯示等待的作用:程式每隔xx秒看一眼,如果頁面元素存在了,則代碼繼續執行下一步,否則繼續回圈檢查,直到超過設定的最長時間拋出 TimeoutException 例外,
2)、配合顯示等待
現使用 Selenium 配置 none 加載策略并打開博客頁面,點擊頁面點贊標簽,觀察顯示等待效果,
顯示等待與加載策略配合使用,能夠在一定程度上提高程式的執行效率,對于使用Selenium來說這是一個常見的技巧,
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
class ChromeOptions(Options):
def __init__(self):
super(ChromeOptions, self).__init__()
self._page_load_strategy = "normal"
@property
def page_load_strategy(self):
return self._page_load_strategy
@page_load_strategy.setter
def page_load_strategy(self, value):
"""設定加載策略方法"""
if value not in ['normal', 'eager', 'none']:
raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
def to_capabilities(self):
"""使用已設定的所有啟動引數,并回傳包含所有內容的字典"""
caps = self._caps
chrome_options = self.experimental_options.copy()
chrome_options["extensions"] = self.extensions
if self.binary_location:
chrome_options["binary"] = self.binary_location
chrome_options["args"] = self.arguments
if self.debugger_address:
chrome_options["debuggerAddress"] = self.debugger_address
# 添加加載策略鍵值對
caps["pageLoadStrategy"] = self._page_load_strategy
caps[self.KEY] = chrome_options
return caps
def timer(func):
"""計時裝飾器,用于計算程式運行時間"""
def inner(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
print(f"加載時間:{time.time() - start_time}")
return res
return inner
@timer
def get_url(browser_, url_):
"""對頁面發起請求"""
browser_.get(url_)
def like(browser_: webdriver, sec=3, poll_frequency=0.5):
"""CSDN博客點贊方法
Args:
browser_: 瀏覽器物件
sec: 顯示等待時長
poll_frequency: 顯示等待輪詢頻率
"""
xpaths = "//li[@id='is-like']"
element = WebDriverWait(browser_, sec, poll_frequency=poll_frequency).until(
ec.presence_of_element_located((By.XPATH, xpaths)))
element.click()
if __name__ == '__main__':
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = ChromeOptions()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
browser = webdriver.Chrome("chromedriver 97.exe", options=op)
get_url(browser, url)
# 執行點贊
like(browser)

六、Selenium4對加載策略的改動💣
在Selenium4中對頁面的選項類進行了改動,每個瀏覽器的 Options選項類不再是單個存在的方式,在 Selenium4 每個選項類都繼承來自了 BaseOptions 類,
這是一個很重要的改進,對于各個瀏覽器來講,在原本沒有定義加載策略方法瀏覽器選項類中也能用上加載策略了,不需要自行另外再去自定義方法,我們只需直接呼叫自帶方法即可配置加載策略,
BaseOptions類部分原始碼 🐾
class BaseOptions(metaclass=ABCMeta):
"""
Base class for individual browser options
"""
......
@platform_name.setter
def platform_name(self, platform: str) -> NoReturn:
"""
Requires the platform to match the provided value: https://w3c.github.io/webdriver/#dfn-platform-name
:param platform: the required name of the platform
"""
self.set_capability("platformName", platform)
@property
def page_load_strategy(self) -> str:
"""
:returns: page load strategy if set, the default is "normal"
"""
return self._caps["pageLoadStrategy
......
Chrome瀏覽器啟動選項直接使用🐔
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
def get_url(browser_, url_):
"""對頁面發起請求"""
browser_.get(url_)
if __name__ == '__main__':
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = Options()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
driver = Service("chromedriver 97.exe")
browser = webdriver.Chrome(service=driver, options=op)
get_url(browser, url)
Edge瀏覽器啟動選項直接使用🐔
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
def get_url(browser_, url_):
"""對頁面發起請求"""
browser_.get(url_)
if __name__ == '__main__':
url = "https://blog.csdn.net/XianZhe_/article/details/120929106?spm=1001.2014.3001.5501"
op = Options()
# 設定頁面加載策略為none
op.page_load_strategy = "none"
# 設定頁面加載策略為normal
# op.page_load_strategy = "eager"
driver = Service("msedgedriver 97.exe")
browser = webdriver.Edge(service=driver, options=op)
get_url(browser, url)
參考文獻💗
- 官方手冊
- 檔案就緒狀態策略
- 升級到 Selenium 4
相關博客🤩
- Python Selenium.WebDriverWait 瀏覽器啟動引數設定『Edge如何使用啟動引數』
- Python Selenium.WebDriverWait 對Cookies的處理及應用『模擬登錄』
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/413885.html
標籤:其他
上一篇:微軟實用工具錦集
