This release is a pre-release and may not be stable for production use.
DrissionPageAsync
DrissionPage 5.0.0b1 的异步(asyncio)版本。
功能与同步版一一对应,区别在于所有会产生通信的操作都变成了协程:等待元素、等待页面加载时会让出事件循环, 因此可以用一个线程同时驱动多个标签页。
import asyncio
from DrissionPageAsync import Chromium
async def main():
browser = await Chromium.connect()
tab = await browser.latest_tab()
await tab.get('https://www.baidu.com')
await tab.ele('#kw').input('DrissionPage')
await tab.ele('#su').click()
print(await tab.title())
await browser.quit()
asyncio.run(main())
更多可运行示例见 examples/。
安装
pip install DrissionPageAsync
需要 Python 3.9+。也可以从源码安装:
pip install .
从同步版迁移
1. 入口改为 await Chromium.connect(...)
启动/接管浏览器需要通信,而 __init__ 不能是协程:
browser = Chromium() # 同步版
browser = await Chromium.connect() # 异步版
SessionPage 不需要通信即可创建,用法不变:page = SessionPage()。
2. 会通信的属性变成了协程方法
这是改动最大的一处 —— 加一对括号,再 await:
| 同步版 | 异步版 |
|---|---|
tab.html |
await tab.html() |
tab.url / tab.title |
await tab.url() / await tab.title() |
ele.text / ele.tag / ele.attrs |
await ele.text() / await ele.tag() / await ele.attrs() |
ele.states.is_displayed |
await ele.states.is_displayed() |
ele.rect.size / ele.rect.location |
await ele.rect.size() / await ele.rect.location() |
browser.latest_tab / browser.tab_ids |
await browser.latest_tab() / await browser.tab_ids() |
只返回子对象、不产生通信的访问器仍然是属性,不要加括号:
tab.set tab.wait tab.scroll tab.rect tab.states
tab.listen tab.console tab.actions ele.click ele.select(例外,见下)
判断规则:x.y 拿到的还是个"工具对象"就是属性;拿到的是数据(文本、坐标、布尔值)就是协程方法。
states 和 set 下的成员一律是协程方法(其中少数并不通信,为了少一条例外规则而统一)。
ele.select() 因为要先读标签名判断是不是 <select>,也是协程方法。
3. 链式调用只需 await 一次
动作链、筛选器,以及 ele() / eles() 的后续操作,如果每步都 await 会很难读。
中间步骤只是记录下来,整条链 await 一次才真正执行。写法和同步版几乎一样:
# 查找后立刻点击/取值,不必套两层 await
await tab.ele('#su').click()
title = await tab.ele('t:h1').text()
await tab.ele('#form').ele('#su').click() # 元素内再查找,仍只 await 一次
ele = await tab.ele('#kw') # 仍然可以先拿到元素本身
await (await tab.ele('#su')).click() # 旧写法继续有效
# 动作链
await tab.actions.move_to(ele).click().type('abc')
await tab.actions.hold(ele).move_to((100, 200)).release()
# 筛选器(返回多个)
eles = await tab.eles('tag:div')
r = await eles.filter.tag('div').text('abc')
r = await eles.filter.displayed().attr('class', 'box')
r = await tab.eles('tag:div').filter.tag('div').text('abc')
# 筛选器(返回一个)本身就是终结操作
e = await eles.filter_one.tag('div')
注意:筛选器和未 await 的 eles() 在 await 之前不能迭代/取长度/取下标,需要先 await 拿到列表。
4. 迭代器改为异步迭代
await tab.listen.start('api/data')
async for packet in tab.listen.steps(count=3):
print(packet.url)
async for msg in tab.console.steps(timeout=5):
print(msg.text)
5. 数据包对象保持同步
listen 捕获到的 DataPacket、Request、Response 等只是对已收到数据的包装,
不产生任何通信,因此它们的属性不用 await:
packet = await tab.listen.wait()
print(packet.url, packet.response.status, packet.response.body) # 都是普通属性
6. 内部工厂函数
如果你的代码直接构造过元素或标签页对象,需要改用协程工厂(补全 id 要通信):
| 同步版 | 异步版 |
|---|---|
ChromiumElement(owner, ...) |
await make_chromium_ele(owner, ...) |
ShadowRoot(ele, ...) |
await make_shadow_root(ele, ...) |
ChromiumTab(browser, ...) |
await make_chromium_tab(browser, ...) |
ChromiumFrame(owner, ele) |
await make_chromium_frame(owner, ele) |
正常使用 tab.ele()、browser.new_tab() 等接口不受影响。
依赖变化
| 用途 | 同步版 | 异步版 |
|---|---|---|
| CDP 通信 | websocket-client | websockets |
| HTTP | requests | httpx |
| 文件下载 | DrissionGet | 内置 _units/http_downloader.py |
| 文件名工具 | DrissionRecord | 内置 _functions/paths.py |
| 大小写不敏感字典 | requests.structures | 内置 _functions/structures.py |
| 并发 | threading / queue | asyncio Task / Queue |
page.session 返回的是 httpx.AsyncClient,page.response 返回 httpx.Response。
已知限制
以下几处是底层库能力差异造成的,不是遗漏:
- httpx 的部分设置只能在创建客户端时指定,创建后无法修改。
set.verify()、set.cert()、set.proxies()、set.trust_env()、set.add_adapter()、set.stream()会抛出RuntimeError并提示改用SessionOptions在创建前设置。 - 下载器不支持单文件分块并行下载(同步版 DrissionGet 的
split参数),传入会被忽略; 多文件并发下载正常,由roads控制并发数。 SessionOptions.from_session()只能回读 httpx 公开的设置(headers、cookies、auth、params、 max_redirects、event_hooks),verify/cert/proxies 等无法回读,保持原值。__repr__不能 await,因此ChromiumElement/ChromiumFrame的 repr 只显示已缓存的标签名和 id, 要看完整内容请用await ele.html()。- 事件回调既可以是普通函数也可以是协程函数,两种都支持。
与同步版的一处行为修正
同步版 BaseWaiter._loading() 接收了 gap 参数却没有传给 wait_until(),
导致 wait.load_start() 指定的 .002 轮询间隔实际未生效。异步版已接上该参数。
类型提示
每个模块都配有翻译后的 .pyi 存根,签名已同步为 async def,IDE 补全和类型检查照常可用。
Metadata
Release files for DrissionPageAsync 5.0.0b1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| drissionpageasync-5.0.0b1.tar.gz | 263.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| drissionpageasync-5.0.0b1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 573.2 kB
Release files / drissionpageasync-5.0.0b1.tar.gz
| Download URL | drissionpageasync-5.0.0b1.tar.gz |
|---|---|
| Size | 263.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
853fa4f48f20eeb4a3c89a84d12e25fea9a58931516dc8f89019d49651420d4b
|
|
BLAKE2b-256 checksum How to use checksums |
c3851cec05b4e6d990728ed116f4181f2bf0aab80b23ac26c65859d3236be559
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / drissionpageasync-5.0.0b1-py3-none-any.whl
| Download URL | drissionpageasync-5.0.0b1-py3-none-any.whl |
|---|---|
| Size | 310.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ee555e27ed3203217f5904811b888f0df24a15b16b67bf5261f7bb3f4792ca3
|
|
BLAKE2b-256 checksum How to use checksums |
c3b2d0b8bf216f283eae0a8d0b7503b45462ff9ad22e05ed3d8d26c395f5e1e7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|