苦于websocket的能跑的案例太少了,还没开始就要什么逆向,一来就是拦路虎,太折磨人了,无意间看了一个类似的文章并学习更新了,感谢大佬,对websocket有了一个新的认识。
python版本:
目标网站:http://m.611.com/
1、打开开发者工具(Ctrl+Shift+I)启用浏览器仿真器
2、触摸启用仿真
将鼠标移到设备上可查看圆形“触摸”光标。这将对基于触摸的 JavaScript 事件( 如touchstart,touchmove和touchend)做出反应。鼠标特定的事件和 CSS 效果不会 做出反应。
按住Shift键,然后单击并移动鼠标以模拟双指缩放操作。
通过观察数据一段时间会变~
没发现比分是怎么和球队怎么拼接而成,疑惑~
通过查看发现是基于websockt实时更新数据,接下来开始分析:
3、参数分析:
{“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]}
通过多次刷新页面/更换浏览器得出结论:
第一条内容是连接服务器用的,action、ids、Url都是不变的,只有UserInfo里面内容是变化的,其中Version中括号里面是一个时间戳+000,后面加浏览器参数,那么只需要更改时间戳就可以了,浏览器参数直接复制就行。
第二、三条内容是加入群组用的,参数都是固定的,不需要改。
4、分析完发送的内容,后面就容易了,只需要再得到url就可以尝试连接了,返回headers界面,发现url后面加了一段字符串参数,字符串每次刷新后都不同,应该是js加密生成的,找js文件逆向太麻烦,先看看前面的请求有没有这个参数;
直接复制f3fa2472b9db40f89bcf82c32e2357e6
ctrl+f搜索:
发现这样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):
# 向服务器发送连接信息
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):
# 向服务器发送入组信息
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):
# 输出服务器推送过来的内容
print(message)
def on_error(self, ws, error):
# 报错
print('报错:', error)
def on_close(self, ws, *args):
# 关闭连接
print("####### on_close #######")
def on_open(self, *args):
# 连接服务器
self.login()
print('连接成功!')
self.join_group()
def run(self):
# 运行循环
self.socket.run_forever()
if __name__ == '__main__':
ly = Leyu()
ly.run()
运行:其学习的过程中踩了不少的坑,能真正跑起的案例可唯是凤毛麟角。不知道是因为大佬们用的版本不一样,还是什么问题。
通过推测试一个列表字典里的分别为A队和B队的比分,分成了三个列表,然后实时更新数据。
另扩展:
连接websocket还有一个异步库可以用,aiowebsocket
import time
import websocket
import asyncio
import requests
import logging
import time
from aiowebsocket.converses import AioWebSocket
# 爬虫网址 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
# 向服务器发送消息
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.')
总结:
整个过程其实就是分析,分析数据获取方式,分析链接,分析参数,代码写起来就比较容易了。这个网站貌似没什么反爬措施,作为一个练手的项目还是不错的。