跳到主要内容

💥 4.2 功能介绍


🐞 测试版

4.2 目前处于测试阶段,欢迎试用。

pip install DrissionPage --pre --upgrade

反馈:https://gitcode.com/g1879/DrissionPage/issues
联系邮箱:DrissionPage@qq.com

作者 2024 年底开始非常忙碌,一年多没空推进开发。到 2026 年终于能抽出时间继续了。
但此时 AI 已变天,自动化工具不知道是否还有必要。
迷惘后决定还是继续前进,因为写程序本身是我的乐趣,不想失去,并且 AI 也给我带来了很大的便利。
在 AI 的大趋势下,自动化工具该怎么设计,希望大家留言交流。

‼️ 不要再用 Page 对象了!

4.1 开始我就呼吁不要再用ChromiumPageWebPage,因已有大量项目在使用而保留。

不知道为什么,网上搜一下很多教程都在使用,AI 给的结果也是,导致用的人数似乎没有减少。

但是,随着新功能的开发,这种混合设计逐渐成为阻碍,带来逻辑混肴和维护复杂性。

为了后续发展,统一使用体验,再三思考后决定进行优化。

先将WebPage功能合并到ChromiumPageMixTab功能合并到ChromiumTab

在 IDE 提示中隐藏ChromiumPage的存在(实际仍可使用)。

然后,在调用ChromiumPage时,会打印一句提示,告知尽快修改代码,ChromiumPage将在后续大版本中删除。

请用Chromium()代替ChromiumPage()

✔️ 推荐写法

from DrissionPage import Chromium

browser = Chromium()
tab = browser.latest_tab

❌️ 不推荐写法

from DrissionPage import ChromiumPage

page = ChromiumPage()

✅️ 重构底层逻辑,优化资源占用

4.2 对底层逻辑进行了全面重构,大幅降低内存占用,提升运行效率。

同时优化底层逻辑,为后续更多功能铺路。

早期 DrissionPage 开发摸着石头过河,留下了一些顽疾,希望在这个版本能很好地解决。


✅️ 支持独立浏览器上下文

4.2 可以创建建独立的上下文对象。
每个上下文对象的 cookies 是独立的,可视作一个无痕浏览器,并且可以独立设置代理。
因此可以实现一个浏览器登录多个账号及动态设置代理的功能。

📌 新建上下文

Chromium对象的new_context()方法新建一个BrowserContext对象。

刚新建时这个浏览器是不可见的,需用这个对象新建一个标签页才会出现。

from DrissionPage import Chromium

browser = Chromium()
context = browser.new_context(proxy='127.0.0.1:7890') # 创建新上下文并独立设置代理
tab = context.new_tab()
tab.get('https://DrissionPage.cn')

📌 方法和属性

  • tab_ids:返回该上下文中所有标签页 id
  • latest_tab:返回该上下文中最后一个激活的标签页对象
  • cookies():返回该上下文中所有 cookies
  • new_tab():在该上下文中新建一个标签页
  • get_tab():按照指定条件在该上下文中查找一个标签页
  • get_tabs(): 按照指定条件在该上下文中查找标签页,返回所有
  • close():关闭该上下文,内部标签页会同时被关闭
  • set.cookies():设置该上下文 cookies
  • set.cookies.clear():清空该上下文 cookies
  • set.perm.****():设置该上下文各种权限
  • wait.new_tab():等待新标签页出现

✅️ 支持跨域操作

📌 直接获取跨域 iframe 内元素

现在可以直接用 tab 对象获取跨域<iframe>内的元素,而不用先获取元素对象了。

可用在此测试页面进行测试。

说明

此功能需用 DrissionPage 启动的浏览器,或使用'--disable-site-isolation-trials'参数启动的浏览器才能实现。

新版本:

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.get('https://drissionpage.cn/demos/iframe_diff_domain.html')
ele = tab('新闻')
print(ele)

旧版本

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.get('https://drissionpage.cn/demos/iframe_diff_domain.html')
iframe = tab.get_frame('t:iframe')
ele = iframe('新闻')
print(ele)

📌 跨域数据包监听

现在可以直接用 Tab 对象直接监听内部跨域<iframe>的数据包,而不用先获取元素。

说明

此功能需用 DrissionPage 启动的浏览器,或使用'--disable-site-isolation-trials'参数启动的浏览器才能实现。

新版本:

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.listen.start('https://www.163.com')
tab.get('https://drissionpage.cn/demos/iframe_diff_domain.html')
res = tab.listen.wait()
print(res)

旧版本:

from DrissionPage import Chromium

tab = Chromium().latest_tab
iframe = tab.get_frame('t:iframe')
iframe.listen.start('163.com')
iframe.get('https://www.163.com')
res = iframe.listen.wait()
print(res)

✅️ 升级数据监听

4.2 新增支持 ws 和 ess 监听,优化了监听目标设置方式。

📌 API 变化

  • listen.start()方法删除methodres_type参数
  • listen.set_targets()方法删除methodres_type参数
  • 新增listen.set_method()listen.set_res_type()方法

如果要设置监听的 method 或 resourceType,以前的写法是:

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.listen.set_targets(method=('GET', 'POST'), res_type='WebSocket')

这种写法有几个弊端:

  1. 需要用户记住和拼对要设置的字符串,resourceType类型繁多,要写对比较麻烦。
  2. 不灵活,有时只想忽略一种类型,就要将所有其它类型都写进去。
  3. 当要支持新的监听类型时,不便于扩展。

于是新版改用下面的写法:

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.listen.set_method.GET(only=True)
tab.listen.set_res_type.all().remove_WebSocket()

将 method 和 resourceType 的设置提取出来成为两个独立的方法,与set_targets()并列。
set_targets()则专注设置 url 目标。

用类型名称作为添加监听的方法名,名称前加'remove_'则忽略这个类型。设置only参数为True,则可只监听指定类型。 能够设置的值都可以在输入'.'后自动提示,并且支持链式写法,设置更便捷。

示例:

tab.listen.set_method.all()  # 监听所有类型请求
tab.listen.set_method.GET().POST() # 监听get和post类型的请求
tab.listen.set_method.all().remove_GET() # 要只监听get请求
tab.listen.set_method.GET(only=True) # 要只监听get请求

# resourceType设置同理:
tab.listen.set_res_type.WebSocket(only=True)
tab.listen.set_res_type.all()

📌 WebSocketPacket数据包

监听到 ws 请求产生的专属数据包。

属性:

  • is_sent:是否发送的包
  • connect_info:连接信息,需要创建连接前就监听才能获取
  • payload:数据包内容,可能是dictstrbytes类型
  • timestamp:时间戳

📌 SSEPacket数据包

监听到的 sse 请求产生的专属数据包。

属性:

  • timestamp:时间戳
  • name:信息类型
  • id:服务器保存的信息 id
  • data:包含的数据
  • connect_info:连接信息,需要创建连接前就监听才能获取

✅️ 支持账密形式代理

格式: '协议://用户名:密码@地址:端口'

📌 浏览器启动前设置

浏览器启动前,使用ChromiumOptionsset_porxy()方法设置。

在浏览器启动前设置的代理,所有上下文通用。

from DrissionPage import Chromium, ChromiumOptions

# 浏览器创建时设置
co = ChromiumOptions().set_proxy('http://zhangsan:abc123@12.34.56.78:9101')
browser = Chromium(co)
tab = browser.latest_tab
tab.get('https://ipv4.webshare.io/')

📌 浏览器启动后设置

浏览器启动后,使用new_context()新建一个上下文,使用proxy参数设置。

新建上下文时设置的,只有当前上下文可使用。

from DrissionPage import Chromium

browser = Chromium()
# 新建上下文,使用不同的代理
context = browser.new_context(proxy='http://lisi:abc123@123.4.56.78:9101')
tab = context.new_tab()
tab.get('https://ipv4.webshare.io/')

✅️ get()方法返回连接状态信息

get()方法现在返回一个NavResult对象,包含以下信息:

  • url:最终网址
  • status:连接状态码(如200),出错时返回文本(如:'net::ERR_TIMED_OUT'
  • headers:接收的 headers 信息
  • request:发出的 request 信息
  • Response:仅 s 模式下会包含连接的Response对象
  • ok:是否成功
from DrissionPage import Chromium

tab = Chromium().latest_tab
res = tab.get('https://DrissionPage.cn')
print(res.status)
print(res.ok)
print(res.url)
print(res.headers)
print(res.request)

✅️ 启动设置

📌 增加remove_test_type()方法

为实现跨域监听和获取元素,使用了'--disable-site-isolation-trials'启动参数,未进行大规模测试。

如出现问题,启动浏览器时可用ChromiumOptionsremove_test_type()方法删除。

from DrissionPage import Chromium, ChromiumOptions

co = ChromiumOptions().remove_test_type()
browser = Chromium(co)

📌 可指定使用 edge

set_browser_path()方法增加edge参数,可指定使用 edge 浏览器。

from DrissionPage import ChromiumOptions

co = ChromiumOptions().set_browser_path(edge=True)

📌 支持账密形式代理设置

set_proxy()方法现在可以接收'http://user:password@url:prot'形式的代理。


📌 适配新版使用系统用户文件夹问题

由于新版 Chrome 浏览器的限制,不能直接使用系统浏览器用户文件夹。

4.2 的use_system_user_path()会将系统用户文件夹复制一份出来使用。

同时支持 edge 浏览器。

可以把系统用户信息和插件等带出来,但不一定保留登录状态。

如果电脑安装的是旧版 Chrome,可设置old_ver参数为True,以继续用旧方法使用浏览器用户文件夹。


📌 调整用户文件夹设置逻辑

  • set_user_data_path()auto_port()不再互斥
  • use_system_user_path()优先级比new_env()

📌 禁用 pdf 预览

有时想下载 pdf 文件,但点击链接后浏览器却打开了文件。

可用disable_pdf_preview()禁用此功能。

from DrissionPage import Chromium, ChromiumOptions 

co = ChromiumOptions().disable_pdf_preview()
browser = Chromium(co)

✅️ 主动触发浏览器下载

有些时候,可获取到文件 url,但不容易下载,如一些 blob,可能需要用抓包获取,较为麻烦。

可用download.by_browser()主动触发下载:

from DrissionPage import Chromium, ChromiumOptions

co = ChromiumOptions().disable_pdf_preview() # 可先阻止pdf预览
tab = Chromium(co).latest_tab
mission = tab.download.by_browser('http://****.com/abc.pdf')
mission.wait()

📌 参数一览

download.by_browser()参数:

  • url: 下载地址
  • save_path:保存路径,为None保存在原来设置的,如未设置保存到当前路径
  • rename:重命名文件名
  • suffix:指定文件后缀
  • timeout:等待下载触发的超时时间,为None则使用页面对象设置
  • file_exists:可在'rename', 'overwrite', 'skip', 'r', 'o', 's'中选择

返回DownloadMission对象,与浏览器下载管理功能的一样。


✅️ 权限设置

浏览器对象增加set.****()方法,可设置各种权限。

BrowserContext对象页支持这些方法。

用法:

from DrissionPage import Chromium

browser = Chromium()
browser.set.perm.camera() # 允许使用摄像头
browser.set.perm.geolocation() # 允许读取地理信息

所有设置见文档。


✅️ 元素定位

📌 增加'ax:'定位元素方法

新增'ax:'前缀的定位方法,支持无障碍模式定位。

无障碍模式是 Chrome 新增的功能,基于语义描述元素,更适合 AI 读取。

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.get('https://DrissionPage.cn')
ele = tab('ax:@name=主导航@role=navigation') # 在tab中定位
print(ele)
ele = ele('ax:@name=文档@role=link') # 在元素中获取
print(ele)
ele.click()

📌 自动匹配模式

当前定位符不写前缀(如'x:')时,会自动在文本、xpath 或 css selector 中匹配。

就是说可以直接填入 xpath 或 css selector 查找元素了。

from DrissionPage import Chromium

tab = Chromium().latest_tab
ele = tab('//div[@id="abc"]') # 新写法
ele = tab('x://div[@id="abc"]') # 旧写法

📌 标签页对象查找元素不再返回str类型

4.2 中标签页的ele()方法不再匹配文本本身,只返回元素对象。


✅️ 显示鼠标运动轨迹

页面对象增加show_trail()方法,可显示运动轨迹。

from DrissionPage import Chromium

tab = Chromium().latest_tab
tab.set.show_trail() # 显示轨迹
tab.get('https://DrissionPage.cn')
ele = tab('ax:@name=文档@role=link')
tab.actions.move_to(ele).click()

✅️ 其它 API 和行为变化

  • console监听返回的结果更全面
  • Chromium对象的new_tab()方法增加hidden参数,可创建隐藏的标签页
  • Chromium对象的new_tab()方法删除new_context()参数
  • Chromium删除tabs_count属性
  • Chromium对象的get_tab()补回以前漏掉的as_id参数
  • ChromiumTab对象的set.activate()方法改为activate()方法
  • ChromiumTab对象的drag_in()方法增加offset_xoffset_y参数,支持设置偏移量。
  • ChromiumTab对象的add_ele()改名为new_ele()new_tab()等保持一致
  • ChromiumTab对象的wait.upload_paths_inputted()增加timeout参数
  • 页面对象get()方法的show_errmsg改为raise_err,且修改位置
  • 元素对象的click()方法点击元素随机位置
  • 元素对象的click()wait_stop参数默认改为False
  • 元素对象的click.to_download()增加file_exists参数
  • 元素对象的css_path属性改名为css_selector
  • 元素对象的wait.clickable()wait_moved改为wait_stop
  • 元素对象的check()方法的uncheck参数改为checked,默认值改为True
  • Settings增加wait_stop_before_click属性和set_wait_stop_before_click()方法

✅️ 问题修复和优化

  • 修复按键不兼容 MAC 问题
  • 修复 146+ 浏览器新页面获取到子<iframe>问题
  • 修复从 playwright 对象迁移时的问题
  • 修复下载等待没有判断超时前结束的问题
  • 修复drag_in()拖拽文件不正确问题
  • 修复 url 为 ip 时设置 cookies 问题
  • 修复 electron 应用打开报错问题
  • 修复 id 为数字开头的元素 css_selector 获取错误问题
  • 修复 SVG 元素 js 点击问题
  • 修复SessionPageget()post()方法timeout设置失效问题
  • 修复标签页对象获取元素全是文本时报错问题
  • 修复<iframe>wait.title_change()wait.url_change()不正确问题
  • 修复打开就弹出 alert 的页面卡住问题
  • 修复监听stop()后再start()不生效问题
  • 修复quit()删除文件夹可能报错问题
  • 修复若干小问题
  • 优化报错信息
  • 大量优化各种逻辑