List [CTL]
前几天在爬虫单中看见一个wss://xxxxxx.com
的爬取,借机学习了Websocket
协议
P.s 这个博彩网站是我见过的最难的单,wss
数据被协议帧层面加密,定时发送options
请求刷新cookie
Websocket
是Html5
提供的一种基于TCP
的全双工式通讯协议,它复用了Http
连接的握手通道,它使得B/S
之间完全平等。
由于Http
协议是一种无状态,无连接(keep-alive
除外),不持久的通讯协议,且服务器的Response
是绝对被动的,浏览器不请求,它就没法响应。
但在现实场景中很多时候都需要进行推送,例如我们的手机上,各个App
都会定时推送消息给客户端,原理是App
后台驻留,由事先建立的TCP
长连接定时请求服务器,也就是轮询,这就引出了polling
和long polling
polling
就是轮询,定时向服务器询问是否有新信息,这样的方式对于资源的消耗可想而知
long polling
阻塞查询,当请求服务器后,没有接到新消息就会阻塞,直到服务器返回消息,这对于服务器的并发有很大考验
Websocket
而Websocket
协议则是用了回调
的形式,与传统的异步相同
它允许服务器主动向浏览器发送消息,这样就解决了上诉两种方案的弊端
它与Http
相同,也是先建立Tcp
连接,再发送协议标准的数据帧。且它复用Http
的握手通道,即客户端借用Http
协议与服务器升级Websocket
协议,后续进行WS
通讯
且ws
也有ssl
层加密,加密后为wss
,类似http/https
这里我们发起一个ws
请求,网址为:Websocket在线测试
请求头:
Accept: text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Cache-Control: no-cache
Connection: keep-alive, Upgrade
DNT: 1
Host: 121.40.165.18:8800
Origin: http://www.blue-zero.com
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: W/kolcgVmU5mUVJi3i4tpA==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/59.0
响应头:
Connection: Upgrade
Sec-WebSocket-Accept: yjko/QGDLpz4adhGrf0jHwrlnG0=
Upgrade: websocket
可以看到请求头中有upgrage/connection
的变化,为升级http
为ws
,加上sec-*
的三个字段,key
为浏览器随机生成的base64
编码字符串
当使用Firefox
F12或BurpSuite
抓包时,URL
会显示http://
,但在使用脚本请求时需更正协议名为ws://
抓包过程中火狐的数据响应会显示在JS
控制台,Burp
会有Websocket History
标签显示,但它俩几乎都看不到最初的握手数据。所以在分析ws
这点上,还是用Chrome
比较省心,可以直接在Frame
查看所有的数据帧
接下来爬取一个网站快讯通,里面的新闻数据全是由ws
传输的
写脚本请求,函数库websocket:
import requests
import websocket
def get_token():
token_url = "http://viewapi.yn.com/index/kxauth"
r = requests.get(token_url)
token = r.json()["data"]["token"]
return token
def ws_post():
headers = {
'Origin': 'http://viewapi.yn.com',
'Pragma': 'no-cache',
'Sec-WebSocket-Extensions': 'permessage-deflate',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0'
}
url = f"ws://118.31.236.175:9502/?token={get_token()}"
ws = websocket.create_connection(url, header=headers)
ws.send('{"cmd":"login", "number":100, "codes":["CJRL","KUAIXUN"]}')
print(ws.recv())
ws.close()
def main():
ws_post()
main()
正常获取到数据