世間はRubyKaigiで真っ只中の中,全力でリリース案件のサポートをしていました.
・・・・・・うらやましくなんかないんだからねっ!!
さて,今やどんなサイトにもついているFacebookのいいね!ボタンですが,ここに表示される数値をブラウザ以外のバッチなどのプログラムから取得したいという場合に,一筋縄ではいかなかったのでやり方をメモしておきます.
具体的には以下の部分の数値ですね.
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"
となります.単純ですね.
参考までに,実行結果の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で取得できる数が合わなかった場合にはこちらのケースを疑ってみるのが良いと思います.
