Python Selenium.WebDriver 网页加载策略『详细』
文章目录
一、网页加载策略🍗
在通过Selenium加载一个网页时,Selenium都会等待页面加载完了才会运行下面的代码,这是因为
webdriver.get
方法会阻塞直到网页全部加载完成。
通常如果当页面加载花费大量时间时,可能是加载了很多外部资源「如:图像、css」,又或则是浏览的是国外网站,使用的网络环境差等问题,这些都是造成页面加载慢的原因。
**但对于某些网页来说,需要加载的元素往往比不需要使用到的网页更快的加载出来,那么如何才能在加载到需要的数据之后就停止阻塞并且执行
webdriver.get
方法下的代码是本文章要探究的问题。**
二、加载策略种类
Selenium支持的加载策略有三种,分别是
none
、
eager
、
normal
,且提供自带的方法让我们去设置启动策略。
关键字加载策略状态描述none****没有等待html下载完成,不等待解析完成就开始执行操作,
selenium
会直接返回eager****渴望等待整个dom树加载完成,即DOMContentLoaded这个事件完成。
只要 HTML 完全加载和解析完毕就开始执行操作,忽略加载样式表、图像和子框架normal****正常(默认)等待整个页面加载完毕再开始执行操作
在浏览器选项类的源码中能够看到,Selenium已经写好了设置加载策略的方法,同时也限制了加载策略的种类『源码第13行』
classOptions(object):def__init__(self):
self._page_load_strategy ="normal"
self._caps = DesiredCapabilities.EDGE.copy()@propertydefpage_load_strategy(self):return self._page_load_strategy
@page_load_strategy.setterdefpage_load_strategy(self, value):if value notin['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选项类部分源码
classOptions(object):def__init__(self):
self._page_load_strategy ="normal"
self._caps = DesiredCapabilities.EDGE.copy()......@propertydefpage_load_strategy(self):return self._page_load_strategy
@page_load_strategy.setterdefpage_load_strategy(self, value):if value notin['normal','eager','none']:raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
@propertydefcapabilities(self):return self._caps
......defto_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 部分源码
classDesiredCapabilities(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 webdriverfrom selenium.webdriver.edge.options import Optionsdeftimer(func):"""计时装饰器,用于计算程序运行时间"""definner(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs)print(f"加载时间:{time.time()- start_time}")return res return inner@timerdefget_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.539372682571411eager加载时间: 2.0514888763427734none加载时间: 0.003000974655151367 - 使用原生方法手动配置加载策略:可以看到其实就是先将选项类的配置转换为字典,再为这个字典添加键为
pageLoadStrategy
的键值对,再将这个字典传入浏览器的实例化参数中。from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsdeftimer(func):"""计时装饰器,用于计算程序运行时间"""definner(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs)print(f"加载时间:{time.time()- start_time}")return res return inner@timerdefget_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.847010850906372eager加载时间: 2.529080390930176none加载时间: 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封装加载策略类
classChromeOptions(Options):def__init__(self):super(ChromeOptions, self).__init__()
self._page_load_strategy ="normal"@propertydefpage_load_strategy(self):return self._page_load_strategy
@page_load_strategy.setterdefpage_load_strategy(self, value):"""设置加载策略方法"""if value notin['normal','eager','none']:raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
defto_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
classChromeOptions(Options):def__init__(self):super(ChromeOptions, self).__init__()
self._page_load_strategy ="normal"@propertydefpage_load_strategy(self):return self._page_load_strategy
@page_load_strategy.setterdefpage_load_strategy(self, value):"""设置加载策略方法"""if value notin['normal','eager','none']:raise ValueError("Page Load Strategy should be 'normal', 'eager' or 'none'.")
self._page_load_strategy = value
defto_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
deftimer(func):"""计时装饰器,用于计算程序运行时间"""definner(*args,**kwargs):
start_time = time.time()
res = func(*args,**kwargs)print(f"加载时间:{time.time()- start_time}")return res
return inner
@timerdefget_url(browser_, url_):"""对页面发起请求"""
browser_.get(url_)deflike(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类部分源码 🐾
classBaseOptions(metaclass=ABCMeta):"""
Base class for individual browser options
"""......@platform_name.setterdefplatform_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)@propertydefpage_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
defget_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
defget_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的处理及应用『模拟登录』
版权归原作者 XianZhe_ 所有, 如有侵权,请联系我们删除。