原文來自 websocket與爬蟲php
寫爬蟲的目的應該就是爲了拿到數據,或者說模擬某種操做
若是他使用的是http(s) 協議來傳輸數據的,那麼咱們就模擬http協議來發送數據
若是它使用的是websocket協議來傳輸數據的,
那麼咱們理所固然的就模擬websocket來發送數據~html
首先,咱們須要瞭解什麼是websocketpython
WebSocket是一種在單個TCP鏈接上進行全雙工通信的協議。WebSocket通訊協議於2011年被IETF定爲標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定爲標準。WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。git
上面是維基百科的介紹.
簡單的將,websocket 和http同樣,都是一種網絡傳輸協議github
WebSocket 是獨立的、建立在 TCP 上的協議。web
Websocket 經過 HTTP/1.1 協議的101狀態碼進行握手。chrome
爲了建立Websocket鏈接,須要經過瀏覽器發出請求,以後服務器進行迴應,這個過程一般稱爲「握手」json
那麼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
因此咱們只要用咱們上面獲得的信息就行模擬發送就能夠了
由於是投票網站,因此不提供代碼...有啥問題,請留言~