Coding4Fun 過程產生一個統計 FB 按讚數的小需求,手上有一份 URL 清單,我想統計各網頁臉書分享區塊的按讚數。(即下圖中的 239)

thumbnail

之前我用過一個笨方法,用 WebClient 抓該區塊的 IFrame 網址抓回 HTML 再從中解析,這回試試更有效率的正統做法。

Facebook Graph API 由有個 URL API 可在 ID 參數傳入 URL 取得該網址的按讚數。FB Graph API 有各種語言的 SDK 可用,但我選擇最簡單的做法,直接組出 URL 下載 JSON 解析。不管用 SDK 或組 URL, 都需先取得 Access Token。最簡單做法是先註冊 Facebook 應用程式 APP ID,接著連上圖形 API 測試工具,在右側選取應用程式名稱、應用程式權杖,下方的存取權杖欄位的一串英數字即為 Access Token,這個介面還可以直接測試 URL API。(註:記得在 URL 加上 &fields=engagement 參數才會傳回按讚統計)

如上圖,傳回結果的 engagement 為用戶與網址不同互動方式的計數,共有四個數字:

  • comment_count - 網址的留言次數。
  • comment_plugin_count - 使用網站的留言外掛程式收集的外掛程式留言次數。
  • reaction_count - 對網址表達心情的次數。
  • share_count - 分享網址的次數。

網頁上看到的按讚數為以上四個數字的加總,在這個案例:213 + 6 + 20 + 0 = 239。

下一步我們將動作搬到 Postman,URL 參數傳入 id=網址(記得做 encodeURIComponent()/UrlEncode() 編碼)&fields=engagement,Access Token 可使用 &access_token=... 傳入,但我選擇藏在 Request Header "Authorization: Bearer ..."更安全。

Postman 實測 OK 後,我們把邏輯改寫成 C#。

var fbLikes = new Dictionary<string, int>();
var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Bearer", accessToken);
urls.ForEach(url => 
{
    var json = http.GetStringAsync(
        new Uri($"https://graph.facebook.com/v3.1/?id={Uri.EscapeDataString(url)}&fields=engagement"))
        .Result;
    dynamic jo = JsonConvert.DeserializeObject<JObject>(json) as dynamic;
    var likes = (int)jo.engagement.reaction_count +
                (int)jo.engagement.comment_count +
                (int)jo.engagement.share_count +
                (int)jo.engagement.comment_plugin_count;
    fbLikes.Add(url, likes);
    Thread.Sleep(1200);
});

.NET 4.5+ 及 .NET Core 已建議改用 HttpClient 取代 WebClient 參考,故以上範例使用 HttpClient 示範,JSON 解析部分則順便展示 Json.NET 搭配 Dynamic 的極簡風

另外有一點很重要,FB Graph API 有流量管控,發送請求勿貪多求快,別手癢把程式改成多執行緒併行,否則很快 Access Token 就會被封鎖得到以下結果,需等待一段時間才能再使用:

{
    "error": {
        "message": "(#4) Application request limit reached",
        "type": "OAuthException",
        "is_transient": true,
        "code": 4,
        "fbtrace_id": "Awsh7b8pVrC"
    }
}

Facebook 官方文件並未註明呼叫流量上限,但依據網路討論約略數字為每個 Token 每個 IP 在 600 秒內不可超過 600 次,基本上使用單執行緒每次呼叫間隔大於一秒即可永保安康,最簡單的做法是每次呼叫後加一行 Thread.Sleep(1200) 即可。

Sample code of querying FB likes count of specific URL via FB Graph API


Comments

# by Cloud

目前已限縮為每小時200次, 請參考下方連結 https://developers.facebook.com/docs/graph-api/overview/rate-limiting/ Calls within one hour = 200 * Number of Users

Post a comment