Facebookボタンに表示されるいいね!数をプログラムから取得する方法

世間はRubyKaigiで真っ只中の中,全力でリリース案件のサポートをしていました.
・・・・・・うらやましくなんかないんだからねっ!!

さて,今やどんなサイトにもついているFacebookのいいね!ボタンですが,ここに表示される数値をブラウザ以外のバッチなどのプログラムから取得したいという場合に,一筋縄ではいかなかったのでやり方をメモしておきます.
具体的には以下の部分の数値ですね.

Screen Shot 2013-06-02 at 2.01.19

Facebookのデータ取得といえばFacebook APIですが,実はこのいいね!数は一つのAPIだけではうまく取れず,FQLとGraph APIの二つのAPIを使って値を合算してやる必要があります.具体的には,Graph APIだけで取れるケースとFQLも交えないと正しい値が取れないケースがあるようです.
ここではそれぞれの方法と,サンプルコードを紹介します.

FQL(Facebook Query Language)

FQLはSQLライクな言語で問い合わせのできるAPIです.Facebookのaccess tokenを持っていると複数のFQL文を一度のリクエストでまとめて投げることができますが,access tokenが無くても1文ずつであれば取得可能です.
実行結果はXMLで帰ってきますので,後は好きなparserにかければデータが取り出せます.

FQLの使い方は非常に簡単で,「https://api.facebook.com/method/fql.query?query=」の後ろに実行したいFQL文をURL encodeしてくっつければ良いです.例えばTechRachoのこの記事のlike_count, share_count, comment_countを取得するFQLは

SELECT like_count, share_count, comment_count FROM link_stat WHERE url=”//techracho.bpsinc.jp/morimorihoge/2013_05_16/8664″

となるので,アクセスURLは「https://api.facebook.com/method/fql.query?query=SELECT%20%20like_count,%20share_count,%20comment_count%20FROM%20link_stat%20WHERE%20url=%22//techracho.bpsinc.jp/morimorihoge/2013_05_16/8664%22

となります.単純ですね.
参考までに,実行結果のXMLは以下の通りです.

<?xml version="1.0" encoding="UTF-8"?>
<fql_query_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" list="true">
  <link_stat>
    <like_count>24</like_count>
    <share_count>13</share_count>
    <comment_count>3</comment_count>
  </link_stat>
</fql_query_response>

いっぱいいいね!されてる.わーい:)

これをプログラム化する場合ですが,Rubyだとfqlというgemがありますので,それを使えばXMLのparseをするまでも無くhashで取得できます.
FQL単体のサンプルコードはGithubにある通りなので単体のサンプルはそちらを参照して下さい.本記事の最後にまとめたサンプルコードを載せておきます.

Graph API

Graph APIは非常に多機能なAPIで,色々できますが詳細はFacebook Developersのページを参照して下さい.
ここでは単純にページの情報を取得するだけですので「http://graph.facebook.com/#{ページのURL}」を取得すれば良いです.データ形式はJSONで返ってくるので,RubyであればJSON.parse()にでもかければ良いでしょう.

このGraph APIがどうも曲者で,取得するページのURLによって結果が違います.多くのページでは,idとしてページのURL,sharesとして前述のFQLで取得できるlike_count, share_count, comment_countの合計値が返ってきます.
例えば前述の例のページであれば,「http://graph.facebook.com///techracho.bpsinc.jp/morimorihoge/2013_05_16/8664」にアクセスして返ってくるJSONは

{
   "id": "//techracho.bpsinc.jp/morimorihoge/2013_05_16/8664",
   "shares": 40
}

となります.
しかし,今回扱ったページでは,以下の様な形式のJSONが返ってきました.特定できそうなIDや文字列部分はぼかしています.

{
   "id": "#{数値}",
   "about": "#{文字列}",
   "app_id": "#{数値}",
   "can_post": false,
   "category": "Website",
   "checkins": 0,
   "description": "#{文字列}",
   "has_added_app": false,
   "is_community_page": false,
   "is_published": true,
   "likes": 5,
   "link": "#{サイトのURL}",
   "name": "#{文字列}",
   "talking_about_count": 0,
   "were_here_count": 0
}

この形式で返ってきた場合,この中のlikesの値が重要で,FQLで取得できる3つの数値の合計+Graph APIのlikesの値がいいね!ボタンに表示される数になります
属性を見ていると,app_idなどがあるのでFacebookアプリなどに関連しているのかもしれませんが,今一つ条件を特定できませんでした.
誰か知ってたらコメントあたりで教えて下さい.

サンプルコード

というわけで,ページのいいね!ボタンに表示されるいいね!数を取得するには,「FQLのlike_count, share_count, comment_count,及びGraph APIのlikes数(あれば)」を合算すれば良いことになります.

実行環境は案の定Rubyですので,事前にfql, active_supportをインストールしておきます.

$ gem install fql active_support

後は以下のコードでいけます.urlの値は取得したいURLに置き換えて下さい.
※注意:以下のコードを数千件とかのデータに対して繰り返しを使ってno waitで回すと数百件取ったところでAPI limitに達して蹴られます.適切にsleep()を入れましょう.某図書館システムと違って警察に訴えられるようなことは無いとは思いますが,ご利用はいつも通りat your own riskでお願いします.

require 'net/http'
require 'fql'
require 'active_support/all'

url = "//techracho.bpsinc.jp/morimorihoge/2013_05_16/8664"

# get facebook like/share/comment count from FQL
result   = Fql.execute(
  "SELECT like_count, share_count, comment_count FROM link_stat WHERE url=\"#{url}\""
)
json     = { url: url }
json[:like_count] = result[0]['fql_result_set'][0]['like_count'].to_i
json[:share_count] = result[0]['fql_result_set'][0]['share_count'].to_i
json[:comment_count] = result[0]['fql_result_set'][0]['comment_count'].to_i

# get facebook Graph likes from Graph API
response = Net::HTTP.get_response("graph.facebook.com", "/#{url}")
hash = JSON.parse(response.body)
json[:graph_likes] = (hash['likes'].present? ? hash['likes'].to_i : 0)
json[:total_likes] = json[:like_count] + json[:share_count] +
                       json[:comment_count] + json[:graph_likes]

puts json.to_json

実行結果のJSONは以下の通りです(JSON Formatterでlintしてます).

{
  "url":"//techracho.bpsinc.jp/morimorihoge/2013_05_16/8664",
  "like_count":24,
  "share_count":13,
  "comment_count":3,
  "graph_likes":0,
  "total_likes":40
}

以上,もしいいね!ボタンに表示される数とFQLで取得できる数が合わなかった場合にはこちらのケースを疑ってみるのが良いと思います.

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

morimorihoge

高校卒業後,学生をやりながらずっとWebアプリ開発に携わってきました.2010くらいまではPHP/Symfonyプログラマでしたが,それ以降のWeb開発はRailsほぼ一本に宗旨替えしました.開発とは別にサーバ構築・運用も10年以上やってきているので,要件定義から設計・実装・環境構築・運用まで一通り何でもこなせます.開発以外では季節により大学でWebサービス開発やプログラミング関連の非常勤講師もしており,技術の啓蒙・教育にも積極的に関わっています.最近はPM的な仕事が増えていますが,現役開発者としていつでも動ける程度にはコードもサーバも弄る日々を送っています.AWS 認定ソリューションアーキテクト – アソシエイトレベル取りました

morimorihogeの書いた記事

開発
RubyのArray(配列)の使い方

2017年03月15日

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ