一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python如何爬取實時變化的WebSocket數據的方法

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

2021-06-05 00:42AsyncIns Python

這篇文章主要介紹了Python如何爬取實時變化的WebSocket數據的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、前言

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

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

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 的庫。

三、爬取思路

這里以萊特幣官網 http://www.laiteb.com/ 實時數據為例。websocket 的握手只發生一次,所以如果需要通過瀏覽器開發者工具觀察網絡請求,則需要在打開頁面的情況下,打開瀏覽器開發者工具,定位到 newwork 選項卡,并輸入或刷新當前頁面,才能觀察到 websocket 的握手請求和數據傳輸情況。這里以 chrome 瀏覽器為例:

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

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

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

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

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

headers 標簽頁記錄的是 request 和 response 信息,而 frames 標簽頁中記錄的則是雙方互傳的數據,也是我們需要爬取的數據內容:

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

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

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

?
1
{"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"}]}

 

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

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

那么,現在問題來了:

  • 握手怎么弄?
  • 連接保持怎么弄?
  • 消息發送和接收怎么弄?
  • 有什么庫可以輕松實現嗎?

四、aiowebsocket

python 庫中用于連接 websocket 的有很多,但是易用、穩定的有 websocket-client(非異步)、websockets(異步)、aiowebsocket(異步)。

可以根據項目需求選擇三者之一,今天介紹的是異步 websocket 連接客戶端 aiowebsocket。其 github 地址為: https://github.com/asyncins/aiowebsocket

readme中介紹到: aiowebsocket是一個遵循 websocket 規范的 異步 websocket 客戶端,相對于其他庫它更輕、更快。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 表示服務端向客戶端推送的消息

五、編碼獲取數據

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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.')

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

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

這是為什么呢?

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
  # 客戶端給服務端發送消息
  await converse.send('{"action":"subscribe","args":["quotebin5m:14"]}')
  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.')

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

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

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

aiowebsocket 做了什么

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

  • 首先,aiowebsocket 根據 websocket 地址,向指定的服務端發送握手請求,并校驗握手結果。
  • 然后,在確認握手成功后,將數據發送給服務端。
  • 整個過程中為了保持連接不斷開,aiowebsocket 會自動與服務端響應 ping pong。
  • 最后,aiowebsocket 讀取服務端推送的消息

【奎因:】如果你認為 aiowebsocket 幫助了你,那么請你到 github https://github.com/asyncins/aiowebsocket 上給一個 star。如果在使用當中發現問題或者希望給 aiowebsocket 提建議,那么也可以到 github 上提出。只要你提出建議,就一定能夠幫助 aiowebsocket 變的更好,而 aiowebsocket 也能夠繼續為你服務。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://juejin.im/post/5c80b768f265da2dae514d4f

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久青草国产在线观看视频 | 国产精自产拍久久久久久 | 欧美一二区视频 | 日韩亚洲欧美综合一区二区三区 | 亚洲精品一二三四区 | 精品亚洲视频在线观看 | 欧美国产日本高清不卡 | 免费91麻豆精品国产自产在线观看 | 99爱在线观看精品视频 | www.俺去啦| 无码中文字幕热热久久 | 2022国产麻豆剧传媒剧情 | 好涨好大我快受不了了视频网 | 九九精品免视看国产成人 | 啊哈用力cao我 | 91麻豆精品激情在线观看最新 | 欧美三茎同入 | 深夜日韩 | 国产精品欧美在线观看 | 午夜理论片日本中文在线 | 欧美日韩国产一区二区三区在线观看 | 四虎永久免费地址ww417 | 精品国产福利在线 | 美女张开腿黄网站免费精品动漫 | 国产精品一区二区在线观看完整版 | 色综合伊人色综合网亚洲欧洲 | 国产99热 | 肉肉小说在线阅读 | 国产成人亚洲精品91专区手机 | 国产日韩欧美在线播放 | 日本高清中文 | 国产亚洲欧美成人久久片 | 精品无码国产AV一区二区三区 | 日本大尺度动漫在线观看缘之空 | 国产日韩高清一区二区三区 | 五月一区二区久久综合天堂 | bdsm中国精品调教 | 草草草视频在线观看 | 成人在线一区二区 | 色琪琪久久草在线视频 | 久久理论片迅播影院一级 |