這篇文章首發(fā)于公號《貓瑪尼》
大家好,我是“貓瑪尼”,一名程序員。
昨天有位讀者留言,說起“有人用爬蟲統(tǒng)計元衛(wèi)男 收到的打賞金額”。我之前也逛過雪球,所以知道他說的那個人,叫元衛(wèi)南,他的留言里面是寫錯字了。所以最終這個事情叫做:統(tǒng)計雪球大V元衛(wèi)南收到的打賞金額。
我喜歡技術(shù)也喜歡錢,覺得這個事情蠻有意思的,所以我也來嘗試一下。聲明一下,沒有對元衛(wèi)南大V不敬,也不想引起什么誤會,純粹是學(xué)術(shù)+愛好的結(jié)合,如侵則刪。

對技術(shù)不感興趣的直接拉到文末看結(jié)論就行。
雖然使用Python的Scrapy框架會很方便,不過有些不了解它的人可能會有點懵,所以我決定不使用爬蟲框架,直接用Python的requests類庫來完成這個任務(wù)。
雪球,是一個投資理財論壇,可以發(fā)帖,看到帖子的人可以根據(jù)個人喜好,對樓主點贊、評論和打賞。
雪球,有登錄功能,因為登錄會增加整個任務(wù)的復(fù)雜度,所以我先考慮簡單的不登錄的方式能不能拿到數(shù)據(jù),能拿到則最好,不能則繼續(xù)走登錄的方式。
第一次講解爬蟲的具體案例,我會講的細(xì)致一點。
打開Chrome瀏覽器,打開“開發(fā)者工具”,并切換到“Network”Tab頁面。使用“開發(fā)者工具”可以很方面的調(diào)試網(wǎng)頁,獲取更多的信息。我是直接使用快捷鍵“option+command+J”打開的。Mac Pro筆記本怎么打開,見下圖:

然后,在頂部的網(wǎng)址輸入欄,輸入網(wǎng)址“https://xueqiu.com/”,由于我們的目標(biāo)非常的明確:統(tǒng)計雪球大V元衛(wèi)南收到的打賞金額。那么我們直接在雪球網(wǎng)的搜索框輸入“元衛(wèi)南”,然后找到他的原創(chuàng)帖子列表(這個就是我們常說的爬蟲入口),并觀察“開發(fā)者工具欄”中的“Network”Tab頁面的請求數(shù)據(jù)。具體如下:

可以很清楚的看到,里面只有一個正常的請求“https://xueqiu.com/statuses/original/timeline.json?user_id=2227798650&page=1”,這里其實可以做一些額外的分析,比如我們可以猜測2227798650這個user_id代表的就是元衛(wèi)南,page=1表示的是們目前處在分頁列表的第一頁。這個請求返回的是一個Json格式的數(shù)據(jù)。以我的經(jīng)驗,Json數(shù)據(jù),是最友好的,對后續(xù)的數(shù)據(jù)處理很方便,而且據(jù)我觀察,Json數(shù)據(jù)的格式,一般不會變化,比較穩(wěn)定,有效的縮減了我們以后的維護(hù)精力。
直接觀察列表,發(fā)現(xiàn)只有標(biāo)題、摘要、發(fā)布時間、閱讀量,并沒有文章的打賞數(shù)據(jù)。那么我們再看看剛才發(fā)現(xiàn)的那個請求的Json數(shù)據(jù),里面有沒有打賞相關(guān)的數(shù)據(jù)。Json數(shù)據(jù)的最小單元,截圖如下:

不需要太強的英語能力,就能分析紅圈里面的各個字段。再觀察里面有沒有類似打賞信息的字段,發(fā)現(xiàn)并沒有。看來打賞數(shù)據(jù)并不在列表里面,那么我們可以得出初步的結(jié)論,打賞數(shù)據(jù)基本就在列表點進(jìn)去的帖子詳情里面。
為了提高我們的效率,我們需要多看幾個帖子,找到那種有打賞的,且最好打賞還比較多的那種帖子。
怎么找這種帖子也是一門學(xué)問,我是這么想的,閱讀量大,說明基數(shù)大,那么一般來說打賞的可能性也就大,那么打賞的數(shù)據(jù)也就多了。這是一種提高做事效率的合理推測,雖然存在反例來打我臉,但這并不影響,我們?nèi)绱巳ニ伎紗栴}。
我向后翻閱他的原創(chuàng)列表,發(fā)現(xiàn)在第二頁就有閱讀量很高,且標(biāo)題也比較引人注意的一片文章。直接點進(jìn)去,運氣不錯,有20個人點贊。截圖如下:

我發(fā)現(xiàn),雪球基本都是Ajax動態(tài)請求服務(wù)端API加載數(shù)據(jù)的,這就讓我比較方便了,哈哈哈……
我們繼續(xù)分析這些請求,找一下到底是哪個請求返回了打賞數(shù)據(jù)。
很巧,第一個接口“https://xueqiu.com/statuses/reward/list_by_user.json?status_id=116503994&page=1&size=20”里面就有,而且讓我高興的是,他居然有一個打賞總額的字段,不過經(jīng)我測算,打賞總額字段的值,跟每個人打賞金額加起來的總和,總是相差1%,我猜測可能是雪球平臺拿走了這1%,剩下99%是給原創(chuàng)坐著的(這個1%的說明,后來我在雪球的公告里面找到了)。這個接口跟分頁相關(guān)的兩個字段page、size,經(jīng)過分析我們知道是打賞的分頁列表,所以如果要用一個一個對打賞相加的方式來計算這個帖子的打賞總額的話,還要考慮分頁的問題,不是不可以做,只是會比較麻煩。不過這里顯然不需要這樣繁瑣,因為我前面說了,已經(jīng)有了一個總金額字段,只是相差1%,這個最后我們計算的時候考慮進(jìn)去就行。
這里面還有個關(guān)鍵字段“status_id”,這個值其實就是列表數(shù)據(jù)API里面的ID值。所以這個接口我們就很好仿照了,“https://xueqiu.com/statuses/reward/list_by_user.json”這部分不用變,后面的參數(shù)status_id的值取自列表數(shù)據(jù)API的ID,由于我們不需要做分頁撈取數(shù)據(jù),是直接使用“reward_amount”的值,那么page就固定為1,size固定為20,就行。


雪球上面這幾個接口的金額數(shù)據(jù),都是乘上了100,所以在最后的時候我們要除以100,這個要記住。
到這里,思路就清晰了,我們只要遍歷元衛(wèi)南的所有帖子,把每個帖子的打賞金額加起來,就是元衛(wèi)南收到的打賞總額。
理清楚了思路,接下來就是寫代碼了啊。
先寫個列表API數(shù)據(jù)的模擬請求代碼,運行了下,直接報錯了啊……

看報錯信息,是在25行Json解析返回數(shù)據(jù)的時候出錯了,我拿URL直接去從來沒有登錄過雪球網(wǎng)的火狐里面請求,也是直接是報錯:

直覺告訴我,我前面以為的不需要登錄是錯的,實際是需要用到登錄后的cookies信息,才能正常訪問API的。那么為什么我開始的時候,在Chrome就可以直接訪問呢?原來之前我是一直都用Chrome登錄雪球網(wǎng),查看我的自選股什么的,瀏覽器幫我保存了相關(guān)cookies在我的電腦上,如果我清除瀏覽器數(shù)據(jù),效果就會和在從來沒登錄過的火狐一樣。既然如此,那我就在Chrome拿到我的cookies數(shù)據(jù),繼續(xù)編寫我的代碼。模擬請求帶上cookies就成功獲取到了數(shù)據(jù)。
其他的,就是具體的代碼實現(xiàn)了,比如列表分頁、每一頁列表的每一項數(shù)據(jù)獲取等。具體直接上代碼(今天比較臨時,后續(xù)我打算將整理后的代碼放到我的github上面):
代碼太亂了,下次看看怎么貼代碼。
最終統(tǒng)計到的信息如下(截止2018-12-10):
收到的打賞金額為:25317.10 元
球友打賞的總額是:25572.83 元
雪球收取的服務(wù)費:255.73 元
(最后一位有四舍五入)
“統(tǒng)計雪球大V元衛(wèi)南收到的打賞金額”,只是很多類似事情里面具有代表性的一件,還有其他比如:統(tǒng)計某個大V的每篇文章的閱讀數(shù),統(tǒng)計閱讀數(shù)最高的那些文章的標(biāo)題經(jīng)常出現(xiàn)的詞是什么,通過統(tǒng)計這些文章的點贊、轉(zhuǎn)發(fā)、收藏等情況,判斷一個帖子的熱度,還有行情相關(guān)的數(shù)據(jù),股票關(guān)注的熱度等等……只要有想法,數(shù)據(jù)在,一般都是可以去好好挖掘的。
本文涉及到了具體的一個大V——元衛(wèi)南,我沒有惡意,純屬技術(shù)交流,如侵則刪。