Python爬蟲:Python+WebSocket獲取體育實時賽事數(shù)據(jù)
苦于websocket的能跑的案例太少了,還沒開始就要什么逆向,一來就是攔路虎,太折磨人了,無意間看了一個類似的文章并學習更新了,感謝大佬,對websocket有了一個新的認識。
python版本:
目標網(wǎng)站:http://m.611.com/
1、打開開發(fā)者工具(Ctrl+Shift+I)啟用瀏覽器仿真器
2、觸摸啟用仿真
將鼠標移到設備上可查看圓形“觸摸”光標。這將對基于觸摸的 JavaScript 事件( 如touchstart,touchmove和touchend)做出反應。鼠標特定的事件和 CSS 效果不會 做出反應。
按住Shift鍵,然后單擊并移動鼠標以模擬雙指縮放操作。
通過觀察數(shù)據(jù)一段時間會變~
沒發(fā)現(xiàn)比分是怎么和球隊怎么拼接而成,疑惑~
通過查看發(fā)現(xiàn)是基于websockt實時更新數(shù)據(jù),接下來開始分析:
3、參數(shù)分析:
{“command”:“RegisterInfo”,“action”:“Web”,“ids”:[],“UserInfo”:{“Version”:“[1667099935000]{“webkit”:true,“version”:“605.1.15”,“safari”:true}”,“Url”:“http://m.611.com/”}}
{“command”:“JoinGroup”,“action”:“SoccerLive”,“ids”:[303794138,303747120,303794153,303748872,303747117,303749323,303755706,303747122,303755264,303794150,303794144,303747115]}
{“command”:“JoinGroup”,“action”:“BasketSoccerLive”,“ids”:[303683091,303683092,303674542,303674543,303674544,303674545,303674546,303683093,303683094,303683096,303683097,303683098]}
通過多次刷新頁面/更換瀏覽器得出結(jié)論:
第一條內(nèi)容是連接服務器用的,action、ids、Url都是不變的,只有UserInfo里面內(nèi)容是變化的,其中Version中括號里面是一個時間戳+000,后面加瀏覽器參數(shù),那么只需要更改時間戳就可以了,瀏覽器參數(shù)直接復制就行。
第二、三條內(nèi)容是加入群組用的,參數(shù)都是固定的,不需要改。
4、分析完發(fā)送的內(nèi)容,后面就容易了,只需要再得到url就可以嘗試連接了,返回headers界面,發(fā)現(xiàn)url后面加了一段字符串參數(shù),字符串每次刷新后都不同,應該是js加密生成的,找js文件逆向太麻煩,先看看前面的請求有沒有這個參數(shù);
直接復制f3fa2472b9db40f89bcf82c32e2357e6
ctrl+f搜索:
發(fā)現(xiàn)這樣GET不就可以了,太喜歡這樣了,對剛開始學爬蟲的小白我才能學的起走……
pip install websocket-client
開始寫代碼:
import requests
def get_token():
# 獲取token
token_url = 'http://m.611.com/Live/GetToken'
headers = {
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Referer': 'http://m.611.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'
}
return requests.get(token_url, headers=headers, verify=False).json()['Data']
接著定義一個類,初始化url、websocket,具體代碼如下:
import time
import websocket
class Leyu:
def __init__(self):
# 獲取token
self.token = get_token()
# 初始化服務器地址
self.ws_url = 'ws://push.611.com:6118/{}'.format(self.token)
# 初始化websocket
self.socket = websocket.WebSocketApp(
self.ws_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
def login(self):
# 向服務器發(fā)送連接信息
msg = '{"command":"RegisterInfo","action":"Web","ids":[],"UserInfo":{"Version":"[' + str(int(time.time())) + '000' + ']\
{\\"chrome\\":true,\\"version\\":\\"106.0.0.0\\",\\"webkit\\":true}","Url":"https://live.611.com/"}}'
self.socket.send(msg)
def join_group(self):
# 向服務器發(fā)送入組信息
msg1 = '{"command":"JoinGroup","action":"SoccerLive","ids":[]}'
msg2 = '{"command":"JoinGroup","action":"BasketSoccerLive","ids":[]}'
self.socket.send(msg1)
self.socket.send(msg2)
def on_message(self, ws, message):
# 輸出服務器推送過來的內(nèi)容
print(message)
def on_error(self, ws, error):
# 報錯
print('報錯:', error)
def on_close(self, ws, *args):
# 關(guān)閉連接
print("####### on_close #######")
def on_open(self, *args):
# 連接服務器
self.login()
print('連接成功!')
self.join_group()
def run(self):
# 運行循環(huán)
self.socket.run_forever()
if __name__ == '__main__':
ly = Leyu()
ly.run()
運行:其學習的過程中踩了不少的坑,能真正跑起的案例可唯是鳳毛麟角。不知道是因為大佬們用的版本不一樣,還是什么問題。
通過推測試一個列表字典里的分別為A隊和B隊的比分,分成了三個列表,然后實時更新數(shù)據(jù)。
另擴展:
連接websocket還有一個異步庫可以用,aiowebsocket文章來源:http://www.zghlxwxcb.cn/news/detail-412225.html
import time
import websocket
import asyncio
import requests
import logging
import time
from aiowebsocket.converses import AioWebSocket
# 爬蟲網(wǎng)址 http://m.611.com/
def get_token():
# 獲取token
token_url = 'http://m.611.com/Live/GetToken'
headers = {
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Referer': 'http://m.611.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'
}
return requests.get(token_url, headers=headers, verify=False).json()['Data']
async def startup(uri):
async with AioWebSocket(uri) as aws:
converse = aws.manipulator
# 向服務器發(fā)送消息
await converse.send('{"command":"RegisterInfo","action":"Web","ids":[],"UserInfo":{"Version":"[' + str(int(time.time())) + '000' + ']\
{\\"chrome\\":true,\\"version\\":\\"106.0.0.0\\",\\"webkit\\":true}","Url":"https://live.611.com/"}}')
await converse.send('{"command":"JoinGroup","action":"SoccerLive","ids":[]}')
await converse.send('{"command":"JoinGroup","action":"BasketSoccerLive","ids":[]}')
while True:
mes = await converse.receive()
print(mes)
print("================*================")
if __name__ == '__main__':
token = get_token()
remote = 'ws://push.611.com:6118/{}'.format(token)
try:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(startup(remote))
# asyncio.get_event_loop().run_until_complete(startup(remote))
except KeyboardInterrupt as exc:
logging.info('Quit.')
總結(jié):
整個過程其實就是分析,分析數(shù)據(jù)獲取方式,分析鏈接,分析參數(shù),代碼寫起來就比較容易了。這個網(wǎng)站貌似沒什么反爬措施,作為一個練手的項目還是不錯的。文章來源地址http://www.zghlxwxcb.cn/news/detail-412225.html
到了這里,關(guān)于Python爬蟲:Python+WebSocket獲取體育實時賽事數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!