Python如何爬取實時變化的WebSocket資料
作者 | 韋世東
來源 | 進擊的Coder(公眾號id:FightingCode)
一、前言
作為一名爬蟲工程師,在工作中常常會遇到爬取實時資料的需求,比如體育賽事實時資料、股市實時資料或幣圈實時變化的資料。如下圖:
Web 領域中,用於實現資料'實時'更新的手段有輪詢和 WebSocket 這兩種。輪詢指的是客戶端按照一定時間間隔(如 1 秒)訪問服務端介面,從而達到 '實時' 的效果,雖然看起來資料像是實時更新的,但實際上它有一定的時間間隔,並不是真正的實時更新。輪詢通常採用 拉 模式,由客戶端主動從服務端拉取資料。
WebSocket 採用的是 推 模式,由服務端主動將資料推送給客戶端,這種方式是真正的實時更新。
二、什麼是 WebSocket
WebSocket是一種在單個TCP連線上進行全雙工通訊的協議。它使得客戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向客戶端推送資料。在WebSocket API中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以建立永續性的連線,並進行雙向資料傳輸。
WebSocket 優點
較少的控制開銷:只需要進行一次握手,攜帶一次請求頭資訊即可,後續只傳輸資料即可,相比 HTTP 每次請求都攜帶請求頭,WebSocket 非常省資源。
更強的實時性:由於伺服器可以主動推送訊息,這使得延遲變得可以忽略不計,相比 HTTP 輪詢的時間間隔,WebSocket 可以在相同的時間內進行多次傳輸。
二進位制支援:WebSocket 支援二進位制幀,這意味著傳輸更節省。
……
爬蟲面對 HTTP 和 WebSocket
Python 中的網路請求庫非常多,Requests 是最常用的請求庫之一,它可以模擬傳送網路請求。但是這些請求都是基於 HTTP 協議的。在面對 WebSocket 的時候 Requests 就發揮不料作用了,必須使用能夠連線 WebSocket 的庫。
三、爬取思路
這裡以萊特幣官網 http://www.laiteb.com/ 實時資料為例。WebSocket 的握手只發生一次,所以如果需要通過瀏覽器開發者工具觀察網路請求,則需要在開啟頁面的情況下,開啟瀏覽器開發者工具,定位到 NewWork 選項卡,並輸入或重新整理當前頁面,才能觀察到 WebSocket 的握手請求和資料傳輸情況。這裡以 Chrome 瀏覽器為例:
在開發者工具中提供了篩選功能,其中 WS 選項代表只顯示 WebSocket 連線的網路請求。
這時候可以看到請求記錄列表中有一條名為 realTime 的記錄,滑鼠左鍵點選它後,開發者工具會分為左右兩欄,右側列出本條請求記錄的詳細資訊:
與 HTTP 請求不同的是,WebSocket 連線地址以 ws 或 wss 開頭。連線成功的狀態碼不是 200,而是 101。
Headers 標籤頁記錄的是 Request 和 Response 資訊,而 Frames 標籤頁中記錄的則是雙方互傳的資料,也是我們需要爬取的資料內容:
Frames 圖中綠色箭頭向上的資料是客戶端傳送給服務端的資料,橙色箭頭向下的資料是服務端推送給客戶端的資料。
從資料順序中可以看到,客戶端先傳送:
{"action":"subscribe","args":["QuoteBin5m:14"]}
然後服務端才會推送資訊(一直推送):
{"group":"QuoteBin5m:14","data":[{"low":"55.42","high":"55.63","open":"55.42","close":"55.59","last_price":"55.59","avg_price":"55.5111587372932781077","volume":"40078","timestamp":1551941701,"rise_fall_rate":"0.0030674846625766871","rise_fall_value":"0.17","base_coin_volume":"400.78","quote_coin_volume":"22247.7621987324"}]}
所以,從發起握手到獲得資料的整個流程為:
那麼,現在問題來了:
握手怎麼弄?
連線保持怎麼弄?
訊息傳送和接收怎麼弄?
有什麼庫可以輕鬆實現嗎?
四、aiowebsocket
Python 庫中用於連線 WebSocket 的有很多,但是易用、穩定的有 websocket-client(非非同步)、websockets(非同步)、aiowebsocket(非同步)。
可以根據專案需求選擇三者之一,今天介紹的是非同步 WebSocket 連線客戶端 aiowebsocket。
Github 地址為:https://github.com/asyncins/aiowebsocket
ReadMe中介紹到:
AioWebSocket是一個遵循 WebSocket 規範的 非同步 WebSocket 客戶端,相對於其他庫它更輕、更快。
它的安裝和其他庫一樣簡單,使用 pip install aiowebsocket 即可。安裝好後,我們可以根據 ReadMe 中提供的示例程式碼來測試:
import asyncio
import logging
from datetime import datetime
from aiowebsocket.converses import AioWebSocket
async def startup(uri):
async with AioWebSocket(uri) as aws:
converse = aws.manipulator
message = b'AioWebSocket - Async WebSocket Client'
while True:
await converse.send(message)
print('{time}-Client send: {message}'
.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), message=message))
mes = await converse.receive()
print('{time}-Client receive: {rec}'
.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rec=mes))
if __name__ == '__main__':
remote = 'ws://echo.websocket.org'
try:
asyncio.get_event_loop().run_until_complete(startup(remote))
except KeyboardInterrupt as exc:
logging.info('Quit.')
執行後的結果輸出為:
2019-03-07 15:43:55-Client send: b'AioWebSocket - Async WebSocket Client'
2019-03-07 15:43:55-Client receive: b'AioWebSocket - Async WebSocket Client'
2019-03-07 15:43:55-Client send: b'AioWebSocket - Async WebSocket Client'
2019-03-07 15:43:56-Client receive: b'AioWebSocket - Async WebSocket Client'
2019-03-07 15:43:56-Client send: b'AioWebSocket - Async WebSocket Client'
……
send 表示客戶端向服務端傳送的訊息
recive 表示服務端向客戶端推送的訊息
五、編碼獲取資料
回到這一次的爬取需求,目標網站是萊特幣官網:
從剛才的網路請求記錄中,我們得知目標網站的 WebSocket 地址為:wss://api.bbxapp.vip/v1/ifcontract/realTime,從地址中可以看出目標網站使用的是 wss,也就是 ws 的安全版,它們的關係跟 HTTP/HTTPS 一樣。aiowebsocket 會自動處理並識別 ssl,所以我們並不需要作額外的操作,只需要將目標地址賦值給連線 uri 即可:
import asyncio
import logging
from datetime import datetime
from aiowebsocket.converses import AioWebSocket
async def startup(uri):
async with AioWebSocket(uri) as aws:
converse = aws.manipulator
while True:
mes = await converse.receive()
print('{time}-Client receive: {rec}'
.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rec=mes))
if __name__ == '__main__':
remote = 'wss://api.bbxapp.vip/v1/ifcontract/realTime'
try:
asyncio.get_event_loop().run_until_complete(startup(remote))
except KeyboardInterrupt as exc:
logging.info('Quit.')
執行程式碼後觀察輸出,你會發現什麼都沒有發生。既沒有內容輸出,也沒有斷開連線,程式一直在執行,但是什麼都沒有:
這是為什麼呢?
是對方不接受我方的請求嗎?
還是有什麼反爬蟲限制呢?
實際上,剛才的流程圖可以解釋這個問題:
整個流程中有一步是需要客戶端給服務端傳送指定的訊息,服務端驗證後才會不停推送資料。所以,應該在訊息讀取前、握手連線後加上訊息傳送的程式碼:
import asyncio
import logging
from datetime import datetime
from aiowebsocket.converses import AioWebSocket
async def startup(uri):
async with AioWebSocket(uri) as aws:
converse = aws.manipulator
while True:
mes = await converse.receive()
print('{time}-Client receive: {rec}'
.format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rec=mes))
if __name__ == '__main__':
remote = 'wss://api.bbxapp.vip/v1/ifcontract/realTime'
try:
asyncio.get_event_loop().run_until_complete(startup(remote))
except KeyboardInterrupt as exc:
logging.info('Quit.')
儲存後執行,就會看到資料來源源不斷的推送過來:
到這裡,爬蟲就能夠獲取到想要的資料了。
aiowebsocket 做了什麼
程式碼不長,使用的時候只需要將目標網站 WebSocket 地址填入,然後按照流程傳送資料即可,那麼 aiowebsocket 在這個過程中做了什麼呢?
首先,aiowebsocket 根據 WebSocket 地址,向指定的服務端傳送握手請求,並校驗握手結果。
然後,在確認握手成功後,將資料傳送給服務端。
整個過程中為了保持連線不斷開,aiowebsocket 會自動與服務端響應 ping pong。
最後,aiowebsocket 讀取服務端推送的訊息
(本文為 AI科技大本營轉載文章,轉載請聯絡作者)
4 月13日-4 月14日,CSDN 將在北京主辦“Python 開發者日( 2019 )”,匯聚十餘位來自阿里巴巴、IBM、英偉達等國內外一線科技公司的Python技術專家,還有數百位來自各行業領域的Python開發者。目前購票通道已開啟,早鳥票限量發售中,3 月15日之前可享受優惠價 299 元(售完即止)。
推薦閱讀:
讓數百萬臺手機訓練同一個模型?Google把這套框架開源了
她們,在”圖形“科研的征途裡灑下堅定信仰
楊超越杯程式設計大賽上熱搜:不懂技術真不敢追星女子偷師男子學校,變身區塊鏈開發工程師,卻說: “這次女人不會再缺席了!”
❤點選“閱讀原文”,檢視歷史精彩文章。
相關文章
- python爬蟲獲取天氣網實時資料Python爬蟲
- Python爬取股票資訊,並實現視覺化資料Python視覺化
- 實時獲取股票資料,免費!——Python爬蟲Sina Stock實戰Python爬蟲
- 房產資料爬取、智慧財產權資料爬取、企業工商資料爬取、抖音直播間資料python爬蟲爬取Python爬蟲
- python爬蟲抓取資料時失敗_python爬蟲 大佬 請教下 為什麼爬取的資料有時能爬到 有時有爬不到, 程式碼如下:...Python爬蟲
- Python:爬取疫情每日資料Python
- 【python】爬取疫情資料並進行視覺化Python視覺化
- Python實時爬取鬥魚彈幕Python
- 使用 Python 爬取網站資料Python網站
- Python爬取噹噹網APP資料PythonAPP
- Python 爬取 baidu 股票市值資料PythonAI
- Python爬取CSDN部落格資料Python
- Python爬蟲實戰:爬取淘寶的商品資訊Python爬蟲
- 如何提升scrapy爬取資料的效率
- 輕鬆利用Python爬蟲爬取你想要的資料Python爬蟲
- kafka和websocket實時資料推送KafkaWeb
- JavaScript爬蟲程式實現自動化爬取tiktok資料教程JavaScript爬蟲
- python爬取股票資料並存到資料庫Python資料庫
- 爬蟲爬取資料如何繞開限制?爬蟲
- Python爬取免費IP代理時,無法解析到資料Python
- 如何使用python多執行緒有效爬取大量資料?Python執行緒
- 爬取資料時防止爬蟲被限制的四種方法爬蟲
- Python 爬取網頁資料的兩種方法Python網頁
- 利用python爬取某殼的房產資料Python
- python爬取58同城一頁資料Python
- 如何保障爬蟲高效穩定爬取資料?爬蟲
- 如何爬取 python 進行多執行緒跑資料的內容Python執行緒
- 爬蟲實戰——58同城租房資料爬取爬蟲
- 一小時入門Python爬蟲,連我都會了!Python爬取租房資料例項Python爬蟲
- python3 使用 Selenium 自動化測試或爬取資料Python
- python 爬蟲 實現增量去重和定時爬取例項Python爬蟲
- Python爬蟲框架:scrapy爬取高考派大學資料Python爬蟲框架
- Python爬蟲入門【3】:美空網資料爬取Python爬蟲
- python爬取不到資料的可能原因之一Python
- 利用Python爬取新冠肺炎疫情實時資料,Pyecharts畫2019-nCoV疫情地圖PythonEcharts地圖
- 如何利用 Selenium 爬取評論資料?
- 爬取百度貼吧實戰,python教你如何獲取Python
- Python 如何實現資料視覺化Python視覺化