這篇文章首發于公號《貓瑪尼》
大家好,我是“貓瑪尼”,一名程序員。
昨天有位讀者留言,說起“有人用爬蟲統計元衛男 收到的打賞金額”。我之前也逛過雪球,所以知道他說的那個人,叫元衛南,他的留言里面是寫錯字了。所以最終這個事情叫做:統計雪球大V元衛南收到的打賞金額。
我喜歡技術也喜歡錢,覺得這個事情蠻有意思的,所以我也來嘗試一下。聲明一下,沒有對元衛南大V不敬,也不想引起什么誤會,純粹是學術+愛好的結合,如侵則刪。
對技術不感興趣的直接拉到文末看結論就行。
雖然使用Python的Scrapy框架會很方便,不過有些不了解它的人可能會有點懵,所以我決定不使用爬蟲框架,直接用Python的requests類庫來完成這個任務。
雪球,是一個投資理財論壇,可以發帖,看到帖子的人可以根據個人喜好,對樓主點贊、評論和打賞。
雪球,有登錄功能,因為登錄會增加整個任務的復雜度,所以我先考慮簡單的不登錄的方式能不能拿到數據,能拿到則最好,不能則繼續走登錄的方式。
第一次講解爬蟲的具體案例,我會講的細致一點。
打開Chrome瀏覽器,打開“開發者工具”,并切換到“Network”Tab頁面。使用“開發者工具”可以很方面的調試網頁,獲取更多的信息。我是直接使用快捷鍵“option+command+J”打開的。Mac Pro筆記本怎么打開,見下圖:
然后,在頂部的網址輸入欄,輸入網址“https://xueqiu.com/”,由于我們的目標非常的明確:統計雪球大V元衛南收到的打賞金額。那么我們直接在雪球網的搜索框輸入“元衛南”,然后找到他的原創帖子列表(這個就是我們常說的爬蟲入口),并觀察“開發者工具欄”中的“Network”Tab頁面的請求數據。具體如下:
可以很清楚的看到,里面只有一個正常的請求“https://xueqiu.com/statuses/original/timeline.json?user_id=2227798650&page=1”,這里其實可以做一些額外的分析,比如我們可以猜測2227798650這個user_id代表的就是元衛南,page=1表示的是們目前處在分頁列表的第一頁。這個請求返回的是一個Json格式的數據。以我的經驗,Json數據,是最友好的,對后續的數據處理很方便,而且據我觀察,Json數據的格式,一般不會變化,比較穩定,有效的縮減了我們以后的維護精力。
直接觀察列表,發現只有標題、摘要、發布時間、閱讀量,并沒有文章的打賞數據。那么我們再看看剛才發現的那個請求的Json數據,里面有沒有打賞相關的數據。Json數據的最小單元,截圖如下:
不需要太強的英語能力,就能分析紅圈里面的各個字段。再觀察里面有沒有類似打賞信息的字段,發現并沒有。看來打賞數據并不在列表里面,那么我們可以得出初步的結論,打賞數據基本就在列表點進去的帖子詳情里面。
為了提高我們的效率,我們需要多看幾個帖子,找到那種有打賞的,且最好打賞還比較多的那種帖子。
怎么找這種帖子也是一門學問,我是這么想的,閱讀量大,說明基數大,那么一般來說打賞的可能性也就大,那么打賞的數據也就多了。這是一種提高做事效率的合理推測,雖然存在反例來打我臉,但這并不影響,我們如此去思考問題。
我向后翻閱他的原創列表,發現在第二頁就有閱讀量很高,且標題也比較引人注意的一片文章。直接點進去,運氣不錯,有20個人點贊。截圖如下:
我發現,雪球基本都是Ajax動態請求服務端API加載數據的,這就讓我比較方便了,哈哈哈……
我們繼續分析這些請求,找一下到底是哪個請求返回了打賞數據。
很巧,第一個接口“https://xueqiu.com/statuses/reward/list_by_user.json?status_id=116503994&page=1&size=20”里面就有,而且讓我高興的是,他居然有一個打賞總額的字段,不過經我測算,打賞總額字段的值,跟每個人打賞金額加起來的總和,總是相差1%,我猜測可能是雪球平臺拿走了這1%,剩下99%是給原創坐著的(這個1%的說明,后來我在雪球的公告里面找到了)。這個接口跟分頁相關的兩個字段page、size,經過分析我們知道是打賞的分頁列表,所以如果要用一個一個對打賞相加的方式來計算這個帖子的打賞總額的話,還要考慮分頁的問題,不是不可以做,只是會比較麻煩。不過這里顯然不需要這樣繁瑣,因為我前面說了,已經有了一個總金額字段,只是相差1%,這個最后我們計算的時候考慮進去就行。
這里面還有個關鍵字段“status_id”,這個值其實就是列表數據API里面的ID值。所以這個接口我們就很好仿照了,“https://xueqiu.com/statuses/reward/list_by_user.json”這部分不用變,后面的參數status_id的值取自列表數據API的ID,由于我們不需要做分頁撈取數據,是直接使用“reward_amount”的值,那么page就固定為1,size固定為20,就行。
雪球上面這幾個接口的金額數據,都是乘上了100,所以在最后的時候我們要除以100,這個要記住。
到這里,思路就清晰了,我們只要遍歷元衛南的所有帖子,把每個帖子的打賞金額加起來,就是元衛南收到的打賞總額。
理清楚了思路,接下來就是寫代碼了啊。
先寫個列表API數據的模擬請求代碼,運行了下,直接報錯了啊……
看報錯信息,是在25行Json解析返回數據的時候出錯了,我拿URL直接去從來沒有登錄過雪球網的火狐里面請求,也是直接是報錯:
直覺告訴我,我前面以為的不需要登錄是錯的,實際是需要用到登錄后的cookies信息,才能正常訪問API的。那么為什么我開始的時候,在Chrome就可以直接訪問呢?原來之前我是一直都用Chrome登錄雪球網,查看我的自選股什么的,瀏覽器幫我保存了相關cookies在我的電腦上,如果我清除瀏覽器數據,效果就會和在從來沒登錄過的火狐一樣。既然如此,那我就在Chrome拿到我的cookies數據,繼續編寫我的代碼。模擬請求帶上cookies就成功獲取到了數據。
其他的,就是具體的代碼實現了,比如列表分頁、每一頁列表的每一項數據獲取等。具體直接上代碼(今天比較臨時,后續我打算將整理后的代碼放到我的github上面):
代碼太亂了,下次看看怎么貼代碼。
最終統計到的信息如下(截止2018-12-10):
收到的打賞金額為:25317.10 元
球友打賞的總額是:25572.83 元
雪球收取的服務費:255.73 元
(最后一位有四舍五入)
“統計雪球大V元衛南收到的打賞金額”,只是很多類似事情里面具有代表性的一件,還有其他比如:統計某個大V的每篇文章的閱讀數,統計閱讀數最高的那些文章的標題經常出現的詞是什么,通過統計這些文章的點贊、轉發、收藏等情況,判斷一個帖子的熱度,還有行情相關的數據,股票關注的熱度等等……只要有想法,數據在,一般都是可以去好好挖掘的。
本文涉及到了具體的一個大V——元衛南,我沒有惡意,純屬技術交流,如侵則刪。