原文來自websocket與爬蟲php
寫爬蟲的目的應該就是爲了拿到數據,或者說模擬某種操做 若是他使用的是http(s) 協議來傳輸數據的,那麼咱們就模擬http協議來發送數據 若是它使用的是websocket協議來傳輸數據的, 那麼咱們理所固然的就模擬websocket來發送數據~html
首先,咱們須要瞭解什麼是websocketpython
WebSocket是一種在單個TCP鏈接上進行全雙工通信的協議。WebSocket通訊協議於2011年被IETF定爲標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定爲標準。git
WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。github
上面是維基百科的介紹. 簡單的將,websocket 和http同樣,都是一種網絡傳輸協議web
WebSocket 是獨立的、建立在 TCP 上的協議。chrome
Websocket 經過 HTTP/1.1 協議的101狀態碼進行握手。json
爲了建立Websocket鏈接,須要經過瀏覽器發出請求,以後服務器進行迴應,這個過程一般稱爲「握手」瀏覽器
那麼websocket協議是如何握手的呢?服務器
下面是websocket一次握手的過程 客戶端請求
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
複製代碼
服務器響應
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/
複製代碼
和http字段不同的地方
能夠看到只是在http協議上增長了幾個硬性規定,http協議的user-agent,cookie均可以在websocket握手過程當中使用
抓包時候的注意事項:由於websocket只有一次握手,握手成功後就能夠雙方發送消息了,假如你打開網頁後沒有找到你要抓的數據,那麼你就須要從新刷新網頁,讓他從新握手一次
表示剛剛鏈接的時候
表示收到消息怎麼作
表示給服務器發送消息
表示關閉鏈接
那麼知道了這些對咱們有什麼好處麼? 找js的時候會很好找,這幾個關鍵詞基本上都是固定的 你能夠直接全局搜搜,而後很容易能找到發送的js代碼
模擬發送的時候也是同樣的.
前面介紹了一堆websocket協議相關的東西,估計不少人已經暈了. 不要緊,先看實例,有問題再回到上面看
咱們先使用chrome
本次要抓的網站的一個投票網站 你們能夠先隨便投一個票,抓抓包看看 會發現怎麼沒有找到他是如何提交數據的...
選擇ws,而後刷新下網頁,再點擊下投票,會發現有一個請求
能夠看到是在握手階段,請求頭裏面的參數和咱們上面講的是同樣的.
請求地址是ws://v5.10brandchina.com:8008/
這邊順帶說一下,有時候這邊會看到 wss://v5.10brandchina.com:8008/
那麼這兩個有啥區別的,簡單的講就是http與https協議的區別同樣...
看一下交互的內容(點擊Frames) 能夠看到已經有四條消息了,可是消息內容是二進制的,chrome這邊沒法預覽... 那麼咱們使用fiddle試一下
打開fiddle,刷新一下網頁 不刷新的話是看不到的,而後隨便投一下票.
怎麼找到請求呢,很簡單,看狀態碼爲101的就行,而後雙擊這一行
而後這邊仍是看到四條消息,咱們點擊第一條,而後用TextView
展現,能夠看到消息是這些 爲啥用TextView
呢?實際上是一個一個的試過來的,假如你發現都試過了,仍是亂碼,那應該是他使用了其餘的壓縮或者加密方法,須要查看js看看他是如何加密的
這個網站的數據是沒有加密過的. 帶向上的箭頭的是咱們向服務器發送的,向下的箭頭是服務器返回的(下面的數據,前面帶黑點?,是咱們發送的)
{"action":"auth","val":5}
{"action":"auth","msg":"eval(\"\\115\\141\\164\\150\\56\\163\\151\\156\\50\\61\\65\\61\\67\\67\\66\\62\\63\\61\\63\\51\")"}
{"action":"auth","val":-0.3241458910493796}
{"action":"wait","msg":95420}
{"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}
{"action":"vote","msg":"ok,231812,2018-02-04 22:32:55"}
能夠看出來 首先咱們發送{"action":"auth","val":5}
而後服務器返回一串信息給咱們, 而後咱們根據服務器返回的算出一個值,也就是 {"action":"auth","val":-0.3241458910493796}
再發送給服務器. 服務器返回{"action":"wait","msg":95420}
,表示驗證經過 而後咱們投票,發送了投票的一些信息給服務 服務器告訴咱們投票成功.
以上就是整個通信過程.
那若是咱們要模擬發送的話,須要知道哪些信息呢
{"action":"auth","val":5}
裏面的val:5
,這個5是固定的麼?若是不是,是如何生成的{"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}
itemid,catid,capthc,auth,rnd如何生成仍是使用chrome,直接用ctrl + shift +f
,而後輸入websocket(或者on_open,on_message,等等上面提到的事件去搜索)
運氣很好,輸入websocket
直接就搜到了js,仍是沒有混淆的
首先發現 websocket 地址是根據catId變的,若是catId能被2整除則地址爲xxx,不然爲xxx 那麼catId是什麼呢,調試發現就是url中的id,咱們當前url爲http://www.10brandchina.com/vote/startin.php?id=41867
則 catId爲41867
而後onmessage也看到了,大概意思是收到信息後,用json解析,若是action是auth的話,則調用sendData這個方法,若是action是vote的話,則使用vote_resule方法.
在看到onopen方法,是調用sendData,併發送('auth',authType)
,在這邊是否是聯想到前面,咱們第一次發送的數據?{"action":"auth","val":5}
,是否是感受如出一轍
close方法就不說了,反正咱們也用不上
再看看sendData這個方法,
用python實現的話是這樣再看vote_result方法,大概做用是判斷投票結果
全部的方法咱們都找到了,那麼咱們再和以前要找的參數走一遍.
{"action":"auth","val":5}
裏面的val:5
,這個5是固定的麼?若是不是,是如何生成的這個5也就是onopen裏面的authType,至於authType是否是固定的,搜索一下就知道了.
能夠經過onmessage方法知道他返回的json數據,json解析一下就行, 裏面的val是經過執行 eval(val)
獲得的 因此你也能夠直接執行這個.或者用python實現
{"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}
itemid,catid,capthc,auth,rnd如何生成itemid 就是你投票的公司的id,catid以前講過,captcha就是驗證碼, auth和上面的authtype同樣 rnd是經過搜索js發現了.
再看看驗證碼是如何生成的呢
檢查驗證碼是否正確
咱們已經拿到全部須要的東西了,只要用程序模擬發送就好了.
使用的包是websocket
官方demo
import websocket
try:
import thread
except ImportError:
import _thread as thread
import time
def on_message(ws, message):
print(message)
def on_error(ws, error):
print(error)
def on_close(ws):
print("### closed ###")
def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(1)
ws.close()
print("thread terminating...")
thread.start_new_thread(run, ())
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://echo.websocket.org/",
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()
複製代碼
能夠看到使用仍是很簡單的,也是onopen,onmessage,send
因此咱們只要用咱們上面獲得的信息就行模擬發送就能夠了
由於是投票網站,因此不提供代碼...有啥問題,請留言~