DrissionPage 監聽器 API 完全指南
一、方法概覽
| 方法 | 參數 | 返回類型 | 阻塞/超時 | 適用場景 |
|---|---|---|---|---|
steps(count=XX) |
count:循環次數或批量數據數量 |
生成器,每次 yield 一條數據對象 | 阻塞直到 count 條數據完成 | 批量同步處理接口數據,已知數據量或固定次數獲取 |
wait(timeout=XX) |
timeout:最大等待時間(秒) |
單條數據對象,如果超時返回 None |
阻塞最多 timeout 秒 | 異步或下拉事件觸發 API,數據量不固定時使用 |
wait(count=XX, timeout=XX) |
count:最多獲取數據條數
timeout:最大等待時間 |
列表 [data1, data2, ...]
實際條數 ≤ count |
阻塞最多 timeout 秒 | 一次性獲取多條數據,安全處理數據量不確定的場景 |
二、steps() 的執行機制
示例代碼
for item in page.listen.steps(count=10):
print(item.response.body)
執行流程
steps(count=10)返回一個生成器對象-
for循環調用生成器的next()獲取第一條數據- 如果接口返回了數據 →
yield出來 - 如果接口沒有數據 → 阻塞等待
- 如果接口返回了數據 →
- 打印
item.response.body -
循環繼續獲取下一條數據(第二次
next())- 如果沒有數據 → 阻塞
- 重複,直到收夠 10 條數據
⚠️ 注意:如果接口數據不足 count 條,生成器會一直阻塞,可能造成"死等"
結論
steps() 適合數據量固定或可批量處理的場景,不適合異步或下拉加載的 API,否則會阻塞等待。
三、wait() 的使用
單條 wait
result = page.listen.wait(timeout=3)
if result:
print(result.response.body)
- 返回類型:單條數據對象
- 超時未返回數據 →
None - 適合等待單條異步數據,不會死等
多條 wait
results = page.listen.wait(count=3, timeout=1)
for item in results:
print(item.response.body)
- 返回類型:列表
[data1, data2, ...] - 實際條數 ≤ count
- 超時未獲取數據 → 空列表
[] - 適合一次性獲取多條數據,結合下拉操作更加安全
四、下拉加載場景推薦
❌ 錯誤做法:把下拉放在 steps 循環中
while True:
for item in page.listen.steps(count=10):
page.run_js("window.scrollBy(0,2000);")
print(item.response.body)
問題:
steps阻塞在next(),第一次循環就可能等待數據,JS 下拉還沒執行- 仍然可能死等,無法保證獲取 count 條數據
- 原因:
steps必須收到 count 條數據才能結束,for循環中觸發下拉動作不能改變阻塞順序
✅ 推薦做法:使用 wait()
while True:
page.run_js("window.scrollBy(0,2000);") # 觸發下拉
results = page.listen.wait(count=3, timeout=2) # 等待最多 3 條數據
if not results: # 空列表説明沒有新數據
break
for item in results:
print(item.response.body)
優點:
- 下拉動作在等待數據前執行
- 有
timeout,避免死等 - 數據量不確定時最安全
五、多接口監聽
思路
- 每個 API 接口對應一個獨立的監聽通道
- 每個監聽通道可以用獨立的
listen對象 -
每個
listen可以獨立調用:start()→ 啓動監聽wait()/steps()→ 獲取數據
示例結構
假設有兩個 API:api1 和 api2:
# 創建兩個 listen 對象
listen1 = page.listen(api='api1')
listen2 = page.listen(api='api2')
# 啓動監聽
listen1.start()
listen2.start()
# 循環獲取數據
while True:
data1 = listen1.wait(timeout=2) # api1 的新數據
data2 = listen2.wait(timeout=2) # api2 的新數據
if data1:
print("API1:", data1.response.body)
if data2:
print("API2:", data2.response.body)
if not data1 and not data2:
break # 超時沒有新數據,停止
- 每個
listen對象獨立收集數據 - 可以單獨設置
count/timeout - 互不干擾
併發獲取
如果你想同時等待多個接口數據併發處理:
- 可以用
asyncio或線程池配合wait(timeout),同時監聽多個 API - 或者在循環裏輪詢每個
listen對象,如上示例
⚠️ 注意:
- 每個
listen對象內部都有自己的阻塞邏輯 - 多個
listen同時調用wait()不會影響彼此
六、總結
steps(count)
- 返回生成器
- 按順序批量
yield數據 - 數據不足 count 條會阻塞
- ✅ 適合數據量已知、批量處理
wait(timeout)
- 返回單條數據對象
- 超時返回
None - ✅ 適合異步/事件驅動數據獲取
wait(count, timeout)
- 返回列表
[data1, data2, ...] - 一次獲取多條數據
- 實際條數 ≤ count
- 超時返回空列表
- ✅ 適合下拉加載或 API 返回條數不確定場景
下拉加載場景
- ❌
steps容易阻塞 → 不推薦 - ✅
wait(可配 count + timeout) → 安全可靠
多接口監聽
- ✅ 可以設置多個
listen對象來監聽不同 API 接口 - ✅ 每個
listen獨立啓動、等待和獲取數據 - ✅ 可以根據需要分別設置
count、timeout或使用異步方式併發獲取
💡 最佳實踐:對於動態加載場景,優先使用wait(count, timeout)方法,避免使用steps()造成的阻塞問題。