博客 / 詳情

返回

Dp框架監聽接口數據方法總結(含 steps 與 wait 討論)

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)

執行流程

  1. steps(count=10) 返回一個生成器對象
  2. for 循環調用生成器的 next() 獲取第一條數據

    • 如果接口返回了數據 → yield 出來
    • 如果接口沒有數據 → 阻塞等待
  3. 打印 item.response.body
  4. 循環繼續獲取下一條數據(第二次 next()

    • 如果沒有數據 → 阻塞
  5. 重複,直到收夠 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:api1api2

# 創建兩個 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 獨立啓動、等待和獲取數據
  • ✅ 可以根據需要分別設置 counttimeout 或使用異步方式併發獲取

💡 最佳實踐:對於動態加載場景,優先使用 wait(count, timeout) 方法,避免使用 steps() 造成的阻塞問題。
user avatar wangyaxi 頭像 backofhan 頭像 qutianhang 頭像 xiaojiedian 頭像 u_16099302 頭像
5 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.