监听网络数据
本教程共 42 篇 · 第 29 篇 · 更新于 2026-07-29 · 约 8 分钟阅读
29. 监听网络数据
本节目标:学会用 listener 监听器捕获浏览器收发的数据包,掌握等待和实时两种获取方式,能根据 URL 特征过滤目标请求。
很多网页的数据不是直接嵌在 HTML 里的,而是通过 JS 动态加载。
比如翻页列表,点下一页时浏览器会悄悄发个请求,拿到 json 数据后再渲染到页面上。
如果你只从 DOM 去抓,可能遇到数据不全、加载来不及的问题。
DrissionPage 每个页面对象都内置了一个监听器,专门抓浏览器数据包。
它能帮你等待指定数据包到达,也能实时遍历所有经过的请求。
监听器的工作逻辑
监听器的使用有个关键顺序:先启动,再动作。
listen.start() 这行代码之前产生的数据包,是抓不到的。
from DrissionPage import Chromium
tab = Chromium().latest_tab
tab.get('https://gitee.com/explore/all') # 这行产生的数据包不会被监听
tab.listen.start('gitee.com/explore') # 启动监听,只抓 URL 包含该文本的数据包
for _ in range(5):
tab('@rel=next').click() # 点击下一页
res = tab.listen.wait() # 等待并拿到一个数据包
print(res.url)
输出:
https://gitee.com/explore/all?page=2
https://gitee.com/explore/all?page=3
https://gitee.com/explore/all?page=4
https://gitee.com/explore/all?page=5
https://gitee.com/explore/all?page=6
注意顺序
listen.start()必须在触发动作之前调用。否则动作产生的数据已经跑掉了,监听器还没开始工作。
两种获取方式
监听器提供两种消费数据的方式:等待获取和实时获取。
等待获取:listen.wait()
wait() 会阻塞等待,直到有符合条件的数据包到达。
适合”触发一个动作,等一个响应”的场景,比如点击按钮后等接口返回。
from DrissionPage import Chromium
tab = Chromium().latest_tab
tab.listen.start('api/data') # 启动监听
tab.get('https://example.com/list')
# 点击加载更多
tab('#load-more').click()
# 等待一个数据包
packet = tab.listen.wait()
if packet:
print(packet.url)
print(packet.response.body) # 拿到响应体
wait() 支持设置超时和数量:
# 等 3 个数据包,最多等 10 秒
packets = tab.listen.wait(count=3, timeout=10)
实时获取:listen.steps()
steps() 返回一个迭代器,用 for 循环逐个拿到数据包。
适合需要持续监听、边听边处理的场景。
from DrissionPage import Chromium
tab = Chromium().latest_tab
tab.listen.start('gitee.com/explore')
tab.get('https://gitee.com/explore/all')
i = 0
for packet in tab.listen.steps():
print(packet.url)
tab('@rel=next').click()
i += 1
if i == 5:
break
两种方式选哪个?
等一个响应用
wait(),持续监听用steps()。本质上wait()是从队列里取,steps()是迭代队列,数据都存着不会丢。
设置过滤规则
监听器默认不抓所有请求,你需要告诉它抓哪些。
按 URL 过滤
# 抓 URL 包含 'api' 的数据包
tab.listen.start('api')
# 抓多个特征
tab.listen.start(['api', 'data', 'json'])
使用正则
# 第二个参数开启正则匹配
tab.listen.start(r'api/\d+', is_regex=True)
按请求方法过滤
# 只抓 POST 请求
tab.listen.start('api', method='POST')
# 抓 GET 和 POST
tab.listen.start('api', method=['GET', 'POST'])
按资源类型过滤
# 只抓 XHR 类型的请求
tab.listen.start(res_type='XHR')
动态修改目标
监听过程中可以用 set_targets() 改规则,不用重启监听。
tab.listen.start('api/v1')
# 抓到几个后,改抓另一个接口
tab.listen.set_targets('api/v2')
控制监听器状态
tab.listen.start('api') # 启动
tab.listen.pause() # 暂停(不清队列)
tab.listen.resume() # 恢复
tab.listen.stop() # 终止(清空队列)
wait_silent() 可以等所有进行中的请求都结束:
tab.listen.wait_silent(timeout=5)
DataPacket 对象
每个数据包都是一个 DataPacket 对象,包含请求和响应的完整信息。
| 属性 | 说明 |
|---|---|
url | 请求网址 |
method | 请求方法 GET/POST |
resourceType | 资源类型 XHR/Document 等 |
request | 请求对象 |
response | 响应对象 |
is_failed | 是否失败 |
更多属性
DataPacket还有tab_id、frameId、target、fail_info等属性,按需使用。
Request 对象
packet.request 包含请求的详细信息:
packet = tab.listen.wait()
print(packet.request.url) # 请求 URL
print(packet.request.method) # 请求方法
print(packet.request.headers) # 请求头
print(packet.request.postData) # POST 提交的数据
print(packet.request.cookies) # 携带的 cookies
Response 对象
packet.response 包含响应内容:
print(packet.response.status) # 状态码 200/404
print(packet.response.headers) # 响应头
print(packet.response.body) # 响应体(json 自动转 dict)
print(packet.response.raw_body) # 原始文本
body 自动解析
response.body会自动识别 json 并转成 dict,base64 转 bytes,其他返回文本。raw_body始终是原始字符串。
等待附加信息
有些数据包的 extra_info 会晚于主体返回,需要额外等一下:
packet = tab.listen.wait()
packet.wait_extra_info(timeout=5) # 等附加信息到位
小结
监听器是抓接口数据的利器,核心就三步:
listen.start()启动并设过滤规则- 执行触发动作(点击、翻页等)
wait()或steps()拿到数据包
记住先启动再动作,这个顺序搞反了就什么都抓不到。