當前位置:
首頁 > 科技 > Python如何爬取實時變化的WebSocket數據

Python如何爬取實時變化的WebSocket數據

作者 |韋世東


一、前言

作為一名爬蟲工程師,在工作中常常會遇到爬取實時數據的需求,比如體育賽事實時數據、股市實時數據或幣圈實時變化的數據。如下圖:

Web 領域中,用於實現數據"實時"更新的手段有輪詢和 WebSocket 這兩種。輪詢指的是客戶端按照一定時間間隔(如 1 秒)訪問服務端介面,從而達到 "實時" 的效果,雖然看起來數據像是實時更新的,但實際上它有一定的時間間隔,並不是真正的實時更新。輪詢通常採用 拉 模式,由客戶端主動從服務端拉取數據。

WebSocket 採用的是 推 模式,由服務端主動將數據推送給客戶端,這種方式是真正的實時更新。

二、什麼是 WebSocket

WebSocket是一種在單個TCP連接上進行全雙工通信的協議。它使得客戶端和伺服器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。


WebSocket 優點

較少的控制開銷:只需要進行一次握手,攜帶一次請求頭信息即可,後續只傳輸數據即可,相比 HTTP 每次請求都攜帶請求頭,WebSocket 非常省資源。

更強的實時性:由於伺服器可以主動推送消息,這使得延遲變得可以忽略不計,相比 HTTP 輪詢的時間間隔,WebSocket 可以在相同的時間內進行多次傳輸。

二進位支持:WebSocket 支持二進位幀,這意味著傳輸更節省。

……


爬蟲面對 HTTP 和 WebSocket

Python 中的網路請求庫非常多,Requests 是最常用的請求庫之一,它可以模擬發送網路請求。但是這些請求都是基於 HTTP 協議的。在面對 WebSocket 的時候 Requests 就發揮不料作用了,必須使用能夠連接 WebSocket 的庫。


三、爬取思路

在開發者工具中提供了篩選功能,其中 WS 選項代表只顯示 WebSocket 連接的網路請求。

這時候可以看到請求記錄列表中有一條名為 realTime 的記錄,滑鼠左鍵點擊它後,開發者工具會分為左右兩欄,右側列出本條請求記錄的詳細信息:

與 HTTP 請求不同的是,WebSocket 連接地址以 ws 或 wss 開頭。連接成功的狀態碼不是 200,而是 101。

Headers 標籤頁記錄的是 Request 和 Response 信息,而 Frames 標籤頁中記錄的則是雙方互傳的數據,也是我們需要爬取的數據內容:

Frames 圖中綠色箭頭向上的數據是客戶端發送給服務端的數據,橙色箭頭向下的數據是服務端推送給客戶端的數據。

從數據順序中可以看到,客戶端先發送:

然後服務端才會推送信息(一直推送):

所以,從發起握手到獲得數據的整個流程為:

那麼,現在問題來了:

握手怎麼弄?

連接保持怎麼弄?

消息發送和接收怎麼弄?

有什麼庫可以輕鬆實現嗎?


四、aiowebsocket

Python 庫中用於連接 WebSocket 的有很多,但是易用、穩定的有 websocket-client(非非同步)、websockets(非同步)、aiowebsocket(非同步)。

可以根據項目需求選擇三者之一,今天介紹的是非同步 WebSocket 連接客戶端 aiowebsocket。

Github 地址為:https://github.com/asyncins/aiowebsocket

ReadMe中介紹到:

AioWebSocket是一個遵循 WebSocket 規範的 非同步 WebSocket 客戶端,相對於其他庫它更輕、更快。

它的安裝和其他庫一樣簡單,使用 pip install aiowebsocket 即可。安裝好後,我們可以根據 ReadMe 中提供的示例代碼來測試:

運行後的結果輸出為:

send 表示客戶端向服務端發送的消息

recive 表示服務端向客戶端推送的消息


五、編碼獲取數據

回到這一次的爬取需求,目標網站是萊特幣官網:

從剛才的網路請求記錄中,我們得知目標網站的 WebSocket 地址為:wss://api.bbxapp.vip/v1/ifcontract/realTime,從地址中可以看出目標網站使用的是 wss,也就是 ws 的安全版,它們的關係跟 HTTP/HTTPS 一樣。aiowebsocket 會自動處理並識別 ssl,所以我們並不需要作額外的操作,只需要將目標地址賦值給連接 uri 即可:

運行代碼後觀察輸出,你會發現什麼都沒有發生。既沒有內容輸出,也沒有斷開連接,程序一直在運行,但是什麼都沒有:

這是為什麼呢?

是對方不接受我方的請求嗎?

還是有什麼反爬蟲限制呢?

實際上,剛才的流程圖可以解釋這個問題:

整個流程中有一步是需要客戶端給服務端發送指定的消息,服務端驗證後才會不停推送數據。所以,應該在消息讀取前、握手連接後加上消息發送的代碼:

保存後運行,就會看到數據源源不斷的推送過來:

到這裡,爬蟲就能夠獲取到想要的數據了。


aiowebsocket 做了什麼

代碼不長,使用的時候只需要將目標網站 WebSocket 地址填入,然後按照流程發送數據即可,那麼 aiowebsocket 在這個過程中做了什麼呢?

首先,aiowebsocket 根據 WebSocket 地址,向指定的服務端發送握手請求,並校驗握手結果。

然後,在確認握手成功後,將數據發送給服務端。

整個過程中為了保持連接不斷開,aiowebsocket 會自動與服務端響應 ping pong。

最後,aiowebsocket 讀取服務端推送的消息

(本文為 AI科技大本營轉載文章,轉載請聯繫作者)

4 月13日-4 月14日,CSDN 將在北京主辦「Python 開發者日( 2019 )」,匯聚十餘位來自阿里巴巴IBM英偉達等國內外一線科技公司的Python技術專家,還有數百位來自各行業領域的Python開發者。目前購票通道已開啟,早鳥票限量發售中,3 月15日之前可享受優惠價299(售完即止)。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI科技大本營 的精彩文章:

深度解析機器學習系統的八大坑
75道常見AI面試題,看看你的知識盲點在哪?

TAG:AI科技大本營 |