時間過得飛快,轉眼間本公眾號文章已經連續更新了四個月。感恩這三個月里結交了很多志同道合的朋友;我也會持之以恆,繼續創造更好的文章給各位讀者朋友。廢話不多說,今天給大家帶來B站彈幕protobuf協議分析,全程高能,在閱讀的同時不要忘記點讚+關注哦⛽️
特別聲明:本公眾號文章只作為學術研究,不用於其它用途。
二、網站調試分析
三、protobuf協議還原
四、完整代碼實現
五、心得分享及總結
趣味模塊
小紅是一名數據分析工程師,自從上次小紅解決了字體反爬的問題後,小紅還未遇到過有難度的問題。但是天有不測風雲,今天小紅在分析彈幕君的時候,遇到了新的問題。數據亂碼無規律,據說是protobuf,那麼今天我們去分析下小紅同學遇到的新問題吧!
一、什麼是protobuf協議?
前言:Protobuf (Protocol Buffers) 是谷歌開發的一款無關平台,無關語言,可擴展,輕量級高效的序列化結構的數據格式,用於將自定義數據結構序列化成字節流,和將字節流反序列化為數據結構。所以很適合做數據存儲和為不同語言,不同應用之間互相通信的數據交換格式,只要實現相同的協議格式,即後綴為proto文件被編譯成不同的語言版本,加入各自的項目中,這樣不同的語言可以解析其它語言通過Protobuf序列化的數據。目前官方提供c++,java,go等語言支持。
二、網站調試分析
1、首先打開我們本次分析的網站,搜索指定彈幕內容,截圖如下所示:

說明:由於彈幕內容使用了protobuf協議,所以無法直接搜索定位,我們需要分析數據包請求,去定位具體的url鏈接。
2、分析數據包請求,定位到彈幕鏈接,截圖如下所示:

說明:從截圖中我們可以清楚看出,這就是彈幕的內容。但是畢竟使用了protobuf協議編碼,我們如果想還原出明文信息,接下來需要去進行JS斷點調試分析了。
3、使用xhr/fetch對該請求打斷點調試,截圖如下所示:

說明:因為該請求是對response進行了protobuf協議編碼,所以我們在定位到該請求發包位置後,只需要關注後面的解碼邏輯即可。
4、執行斷點操作按鈕後,截圖如下所示:

說明:此刻r變量即為我們要訪問的彈幕url地址;接下來繼續執行斷點。
5、繼續執行斷點,持續更近,截圖如下所示:

此刻我們打印變量r的值,截圖如下所示:

說明:這不就是我們想要的明文信息麼?接下來,我們只需要找到protobuf協議初始化參數id定義就可以還原明文了。
6、經過JS斷點調試,最終定位到protobuf協議初始化參數如下:

7、將Console中的數據複製後進行JSON在線格式化解析,截圖如下:

總結:知道response明文及protobuf協議定義的參數及id後,接下來我們只需要構建proto文件即可完成對整個明文信息的還原。
三、protobuf協議還原
1、還原protobuf協議,編輯代碼結構如下:

2、執行如下命令,編譯為python protobuf可執行文件:
protoc --python_out=. *.proto3、運行命令後,生成protobuf文件,截圖如下所示:

總結:走到這裡protobuf協議就完全還原了,接下來讓我們進入完整代碼實現環節吧。
四、完整代碼實現
1、整個項目完整代碼如下
# -*- coding: utf-8 -*-# --------------------------------------# @author : 公眾號:逆向與爬蟲的故事# --------------------------------------import requestsfrom feed_pb2 import Feedfrom google.protobuf.json_format import MessageToDictdef start_requests(): cookies = { 'rpdid': '|(J~RkYYY|k|0J\'uYulYRlJl)', 'buvid3': '794669E2-CEBC-4737-AB8F-73CB9D9C0088184988infoc','buvid4':'046D34538-767A-526A-8625-7D1F04E0183673538-022021413-+yHNrXw7i70NUnsrLeJd2Q%3D%3D', 'DedeUserID': '481849275', 'DedeUserID__ckMd5': '04771b27fae39420','sid':'ij1go1j8', 'i-wanna-go-back': '-1', 'b_ut': '5', 'CURRENT_BLACKGAP': '0', 'buvid_fp_plain': 'undefined', 'blackside_state': '0', 'nostalgia_conf': '-1', 'PVID': '2', 'b_lsid': '55BA153F_18190A78A34', 'bsource': 'search_baidu', 'innersign': '1', 'CURRENT_FNVAL': '4048','b_timer':'%7B%22ffp%22%3A%7B%22333.1007.fp.risk_794669E2%22%3A%2218190A78B5F%22%2C%22333.788.fp.risk_794669E2%22%3A%2218190A797FF%22%2C%22333.42.fp.risk_794669E2%22%3A%2218190A7A6C5%22%7D%7D', } headers = { 'authority': 'xxxxxx', 'accept': '*/*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'origin': 'https://www.xxxxx.com', 'pragma': 'no-cache', 'referer': 'https://www.xxxxxx.li.com/video/BV1434y1L7rb?spm_id_from=333.851.b_7265636f6d6d656e64.1&vd_source=8d45ec9ed78652f966b3625afe95e904', 'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"macOS"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36', } params = { 'type': '1', 'oid': '729126061', 'pid': '896926231', 'segment_index': '1', }response=requests.get('https://xxxx.xxxx.com/x/v2/dm/web/seg.so',params=params,cookies=cookies, headers=headers) info = Feed() info.ParseFromString(response.content) _data = MessageToDict(info, preserving_proto_field_name=True) messages = _data.get("message") or [] for message in messages: print(message.get("content"))if __name__ == '__main__':start_requests()2、運行代碼後,截圖如下所示:

五、心得分享及總結
回顧整個分析流程,本次難點主要概括為以下幾點:
能夠通過源碼還原proto文件
如何在python中使用protobuf
今天分享到這裡就結束了,歡迎大家關注下期文章,我們不見不散⛽️