因為我過年的時候蠻無聊的,雖然有研究上的正事要做,但是我還是想做一點自己的事情。正好最近 Dcard,這個專門為大學生開設的交友網站非常熱門,裡面有著各式各樣的文章,所以我就一時興起把上面的文章抓下來看看能做什麼樣的研究。

Dcard 簡介

傳送門:http://www.dcard.tw/

Dcard 成立於 2011 年,是一個以大學生為客群的交友網站。其最大的特色在於其每天午夜的抽卡機制。

抽卡機制

其抽卡機制的運作方式為,每當到午夜時,每一位註冊的會員會收到一張卡片。卡片上包含著另一位會員的自我介紹,以及該會員的照片。如果想要認識對方,就必須要送出邀請信。但是唯有當兩方都有送出邀請時,才會看到對方的邀請信的內容,並成為朋友。如果有其中一方直至下次午夜前尚未送出邀請,那張卡片就會消失,以後不會再抽到同一個人。

匿名討論區

除了抽卡之外,Dcard 也提供了一個匿名討論區。討論區上有十幾種討論版,依據不同的討論議題分類,像是:時事、男女關係、音樂、電影…等等。在上面無論發文或回文,只會顯示學校與系名,甚至某些狀況下能夠完全隱藏上述資訊,只留下性別供人判斷。若在文中流露太多辨別身份的資訊,則會被直接刪除。因此他人幾乎無法辨別每一則文章或留言是由誰所撰寫。

因為 Dcard 的註冊流程繁雜,加上註冊者必須要具備經過 Dcard 認證的學校電子信箱。因此幾乎可以確定註冊者就是大學生。並且在特殊抽卡機制的驅使下,使得使用者更喜歡在 Dcard 上活動。這也造就了 Dcard 匿名討論區熱絡討論的狀況。

研究方向

這次主要是要研究其匿名討論區的部分。因為討論區是公開給任何人觀賞,所以資料取得就沒有隱私的問題。雖然我有想過要取得抽卡的資料,不過這並非是短時間內就可以收集起來的,因而作罷。看看有沒有辦法從文章中挖出什麼有趣的訊息。

爬文章

既然是要研究文章,那我勢必是要把 Dcard 上所有文都先抓下來。

身為一個 Programmer,我們當然不會一篇一篇地用瀏覽器打開文章,然後一篇一篇地存起來。因此這邊我們就要寫一個爬蟲來自動幫我們把所有文章都抓下來,以方便我們做研究。

網路監測

那要怎麼樣讓程式能夠自動找出文章,然後存下來呢?

我們可以先瞭解一下,到底 Dcard 是怎麼從伺服器上取得文章的?

幸虧現在的瀏覽器都有很強大的 debug 功能,我們可以很簡單地知道當我們進入 Dcard 網站時,瀏覽器到底跟伺服器送了哪些請求,得到了哪些回覆。

當在使用 Firefox 或者 Google Chrome 時,你可以按下 F12 (Mac 是按 fn + F12) 呼叫出 debug 視窗。此時只要選擇其中一個頁籤「網路」,就可以監測有哪些請求與回覆。

當你打開畫面後,此時點選一個 Dcard 上的文章,就會顯示像是下圖的資訊:

因為在下曾經有參與過寫網站與 App 的經驗,此時我就發現其中有幾個請求很可疑。我們先看「類型」那一行,該行所代表的就是伺服器回應時所傳遞的資料格式。其中第一個與第三個請求都是收到 JSON 的回覆,這代表我們很有可能中大獎了!

JSON 是一種常用於傳遞小型資料的格式,現在廣泛使用於 App 與伺服器之間的溝通。因為 Dcard 除了網站之外,還有開發 App 版本,因此使用 JSON 搭配 RESTful API 來傳遞資料也是很合理的做法。

分析 API

當我們點選上圖中的第一個請求之後,馬上就會跳出另一個視窗。此時我們點選「回應」,就可以看見伺服器回覆的內容:

大致看下來之後,就知道這鐵定是文章的資料沒錯!內容大約是文章的一些資料,像是 fourm_alias 就是代表這個文章屬於哪個版,updatedAt 就是最近一次更新時間,likeCount 就是點讚數等等。

若進一步點開 version 這個 object,就可以發現裡面放的就是文章的內文。comment 點開則可以看到文章下面的留言與留言者的學校與系名。

看到這邊,就知道這一個 JSON object 裡面所包含的資料就是這整份文章的資料了!因此我們只要能夠找到所有文章的 JSON object,就可以把所有文章都存在自己電腦裡。

這時我們再點選「檔頭」,可以看到這些資料:

最重要的是上面「URL」的部分。我們可以看到這個網址是:

1
http://www.dcard.tw/api/post/all/85846

www.dcard.tw 當然是伺服器的網址,而剩下 api/post/all/85846 就是可以取得這篇文章 JSON object 的位址。

這邊大致可以猜到文章的 API 八成是這樣:

1
http://www.dcard.tw/api/post/all/[post-id]

如果我們將 85846 換成別的數字,像是 84840:

1
http://www.dcard.tw/api/post/all/85840

然後把這個網址輸入瀏覽器的網址列,按下 enter,就會出現:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"forum_alias": "bg",
"pinned": false,
"anonymousDepartment": true,
"anonymousSchool": true,
"reply": -1,
"updatedAt": "2015-02-18T18:38:15.890Z",
"createdAt": "2015-02-18T18:04:07.135Z",
"follow": false,
"comment": [...],

...
}

大致看下來應該可以發現這是另一個文章的 JSON object。

那麼毫無疑問,那個數字就是文章的 id(編號),而那段網址就是能夠取得文章 JSON object 的 API。並且幸運的是,文章編號看起來是從依序給定的。也就是說,假設最新的文章編號是 85846,那我們只需要從 0 掃到 85846,應該就可以取得 Dcard 上所有文章的 JSON object。

下次再來說該怎麼抓下來,怎麼處理吧~