💥 4.0 功能介绍

3.x 是自主研发底层的初步尝试,很多地方摸着石头过河,存在一些不太成熟的地方。
经过一段时间的使用,积累一些经验之后,4.0 在 3.x 的基础上对底层进行了大幅重构,新增大量功能,改善运行效率和稳定性,优化项目结构,解决很多存在的问题。对比旧版本有质的提高。
但同时不少 api 发生了变化,不能完全兼容旧版本。
api 的变化有些是功能优化必需的改变,有些则是本人对命名简洁的执念,趁着大版本的更新顺便把长期不太满意的命名给改了。
给使用者造成一定不便感到抱歉,但长痛不如短痛,趁着项目用的人不多,干脆舍弃历史包袱果断改掉。
有些原来的写法在 4.0.0 中还能正常使用,但 IDE 会提示无效,将在以后的版本中完全删除。推荐尽快更新为新写法。
本节仅简述功能变化,具体使用方法详见各对应章节。
✅️ 新的抓包功能
3.2 中,抓包功能主要由 FlowViewer 和wait.data_packets()
提供。
FlowViewer 是本人的一个练手作品,写得比较随意,技术也还没到家。存在漏抓、信息不全、api 不够合理的问题。
4.0 中,每个页面对象都内置了监听器,能力全面升级,api 也更合理。
📌 旧 api 变化
- 弃用 FlowViewer,以后也不会再升级
- 删除
wait.set_targets()
- 删除
wait.stop_listening()
方法 - 删除
wait.data_packets()
方法 DrissionPage.common
路径删除FlowViewer
📌 新 api
- 每个标签页对象(包括
ChromiumFrame
)新增listen
属性,内置监听功能 - 用
listen.start()
和listen.stop()
启动和停止监听 - 用
listen.wait()
阻塞等待数据包 - 用
listen.steps()
同步获取监听结果 - 增加
listen.wait_silent()
等待所有请求完成(包含 targets 以外的) - 监听结果结构优化,request 和 response 数据分开存放
📌 示例
下面示例可直接运行查看结果。这个示例会计时,用于与下个示例对比。
from DrissionPage import ChromiumPage
from TimePinner import Pinner
from pprint import pprint
page = ChromiumPage()
page.listen.start('api/getkeydata') # 指定监听目标并启动监听
pinner = Pinner(True, False)
page.get('http://www.hao123.com/') # 访问网站
packet = page.listen.wait() # 等待数据包
pprint(packet.response.body) # 打印数据包正文
pinner.pin('用时', True)
输出:
{'hao123.new.shishi.bangdan.recom': [{'index': '1',
'pure_title': '以色列和哈马斯移交首批被扣押人员'},
{'index': '2',
'pure_title': '听到免签政策法国外长笑了'},
......
用时:3.3114853000151925
✅️ 新的页面访问逻辑
3.x 中存连接存在以下主要问题:
- 浏览器页面对象
get()
方法的timeout
参数只对加载阶段生效,无法覆盖连接阶段; - 加载策略
none
模式没有实际用处。
这两个问题都在 4.0 中解决,且能够让用户自主控制终止连接的时机。 另外还对连接逻辑进行了优化,避免卡死情况出现。
📌 api 变化
- 页面对象
page_load_strategy
属性改名为load_mode
set.load_strategy
改为set.load_mode
📌 行为变化
get()
方法的timeout
参数现在可覆盖整个过程timeout
参数对非get()
方法触发的加载(如点击链接)也能生效SessionPage
和WebPage
的 s 模式,如收到空数据,也会重试SessionPage
的get()
方法可以指向本地文件
📌 新的none
加载模式
旧版中,none
加载策略是当页面 连接成功就立刻停止加载,这在实际使用时没有什么意义。
新版中,这个模式改成:除非加载完成,否则程序不会主动将其停止(即使已超时),同时连接状态不再阻塞程序,而允许用户进行状态判断,主动停止加载。
这样提供给用户非常大的自由度,可等到关键数据包或元素出现就主动停止页面加载,大幅提升执行效率。
📌 示例
我们继续使用上一个示例的代码,但把加载模式设为none
,且获取到数据时主动停止加载。
from DrissionPage import ChromiumPage
from TimePinner import Pinner
from pprint import pprint
page = ChromiumPage()
page.set.load_mode.none() # 设置加载模式为none
page.listen.start('api/getkeydata') # 指定监听目标并启 动监听
pinner = Pinner(True, False)
page.get('http://www.hao123.com/') # 访问网站
packet = page.listen.wait() # 等待数据包
page.stop_loading() # 主动停止加载
pprint(packet.response.body) # 打印数据包正文
pinner.pin('用时', True)
输出:
{'hao123.new.shishi.bangdan.recom': [{'index': '1',
'pure_title': '以色列和哈马斯移交首批被扣押人员'},
{'index': '2',
'pure_title': '听到免签政策法国外长笑了'},
......
用时:1.2575092000188306
可见节省了2秒时间。 当网站要访问一些不稳定资源时,节省的时间相当客观,也能提高程序的稳定性。
✅️ 新的下载管理功能
在旧版中,下载管理功能存在以下问题:
- 浏览器下载管理和内置下载器
DownloadKit
的配置都使用download_set
属性进行设置,容易造成混淆。 - 浏览器下载任务不能在下载前指定文件名
- 该功能有随着浏览器版本更新失效的风险
4.0 对浏览器下载管理功能进行了完完全全的重构,结构更为合理,功能更多。 同时,内置下载器的设置和浏览器下载任务设置进行了分离。
📌 api 变化
- 页面对象删除
download_set
属性 - 增加
set.download_path()
方法 - 增加
set.download_file_name()
方法
📌 新增功能
- Tab 对象和 Frame 对象也支持
download()
方法 - 每个 Tab 对象可单独设置下载路径和重命名文件名
- 可拦截浏览器下载任务并获取其信息
- 可取消浏览器下载任务、获取下载进度、等待任务完成
- 可设置遇到文件夹已存在时的处理方式
📌 行为变化
4.0 中默认不启用浏览器下载任务管理,只有在启动参数中设置了下载路径,或调用set.download_path()
方法时才会启动。
未启动任务管理功能时,下载行为和普通使用一样。
📌 示例
以下示例可直接运行。
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.get('https://office.qq.com/download.html')
page.set.download_path('tmp') # 设置文件保存路径
page.set.download_file_name('qq') # 设置文件名
page('#downloadWin').click() # 点击触发下载
mission = page.wait.download_begin() # 等待下载开始并获取任务对象
mission.wait() # 等下下载任务完成
输出:
url:https://dldir1.qq.com/qqfile/qq/TIM3.4.8/TIM3.4.8.22124.exe
文件名:qq.exe
目标路径:D:\coding\projects\DrissionPage\tmp
100.0% 下载完成 D:\coding\projects\DrissionPage\tmp\qq.exe
✅️ 页面对象
这里说的页面对象包括 Page 对象(ChromiumPage
、WebPage
)、Tab 对象(ChromiumTab
、WebPageTab
)、ChromiumFrame
对象。
📌 启动参数变化
4.0 中,创建WebPage
和ChromiumPage
对象时,不再接收ChromiumDriver
对象。
意思是不再支持传递控制权的方式创建页面对象。
因为本身支持多个页面对象控制同一个标签页,如果需要多页面对象协同,只要get_tab()
创建一个新对象就行,可和原有对象并行使用。
而且,传递控制权本身有稳定性方面隐患,因此新版中将其删除。
相应地,启动参数的名称也发生了变化:
WebPage
对象的driver_or_options
参数改名为chromium_options
ChromiumPage
对象的addr_driver_opts
参数改名为addr_or_opts
另外,ChromiumPage
的启动参数addr_or_opts
现在可以接收int
数据,直接传入端口号。
📌 内置动作链
4.0 中,每个页面对象内置actions
属性,即动作链。
内置的动作链与直接创建的动作链对象有一个不同点,每次操作会等待页面加载完成再执行。
示例:
page.actions.hold(ele).move(50).release()
📌 状态信息
旧版中,页面对象拥有ready_state
、is_loading
、is_alive
属性,现在都合并到states
属性中。
# ------ 旧版代码 ------
print(page.is_loading)
# ------ 新版代码 ------
print(page.states.is_loading)
📌 其它
ChromiumPage
和WebPage
改为固定单例get_tab()
获取的 Tab 对象默认单例,可用Settings
设置允许多例- 页面对象增加
raw_data
参数,s 模式下返回原始数据 - 所有页面对象增加
close()
方法,SessionPage
用于关闭连接,浏览器页面对象用于关闭标签页 - 浏览器页面对象增加
wait()
方法,用于等待若干秒 - 浏览器页面对象增加
wait.ele_loaded()
方法,等待元素加载到DOM - 浏览器页面对象增加
wait.title_change()
和wait.url_change()
方法,用于等待 title 和 url 变化 - 浏览器页面对象增加
wait.alert_closed()
方法,用于等待弹窗被手动关闭 - 浏览器页面对象增加
set.cookie()
方法,可设置单个 cookie - 浏览器页面对象增加
set.blocked_urls()
方法,可设置忽略的连接 - Tab 和 Page 对象增加
disconnect()
方法,用于断开与网页连接 - Tab 和 Page 对象增加
reconnect()
方法,用于断开并重新连接网页 - Tab 和 Page 对象增加
save()
方法,用于把网页保存为 mhtml - Tab 和 Page 对象增加
add_init_js()
和remove_init_js()
方法 quit()
方法增加force
参数,可强制关闭浏览器进程ChromiumFrame
增加ract
属性ChromiumFrame
的frame_size
属性改为rect.size
wait.ele_delete()
方法改为wait.ele_deleted()
wait.ele_display()
方法改为wait.ele_displayed()
wait.load_complete()
方法改为wait.doc_loaded()
- 优化
SessionPage
和WebPage
s 模式访问速度 WebPage
在 d 模式时,post()
返回Response
对象
✅️ cookies 设置
set.cookies()
可接收单个 cookie- 增加
set.cookies.clear()
方法用于清除 cookies - 增加
set.cookies.remove()
方法用于删除一个 cookie 项