To learn the use of basic Facebook graph API, Graph API Explorer (https://developers.facebook.com/tools/explorer/) is the best starting point.

Now we move to R programming and first install or load the required libraries.

if (!require("RCurl")) install.packages("RCurl", repos="https://cran.cnr.berkeley.edu/", dependencies = TRUE)
if (!require("RJSONIO")) install.packages("RJSONIO", repos="https://cran.cnr.berkeley.edu/", dependencies = TRUE)
if (!require("httr")) install.packages("httr", repos="https://cran.cnr.berkeley.edu/", dependencies = TRUE)

library(RCurl)
library(RJSONIO)
library(httr)

Follow the below instruction to setup the token.

###
### Setup your client_id and client_secret
### Read this
### 1) https://developers.facebook.com/docs/apps/register
### 2) http://stackoverflow.com/questions/3203649/where-can-i-find-my-facebook-application-id-and-secret-key
###
### Fill in your App ID (client_id) and Secret ID (client_secret). Grant_type is fixed.
###

token_fb <- function(){  ### randomly select one token from the list
  token <- httr::GET("https://graph.facebook.com/oauth/access_token", 
    query = list(client_id="",   # say client_id="sjdkksrekerke"
    client_secret="",            # say client_secret="ldsldsldlsdlsldsl"
    grant_type = "client_credentials"))
  return(httr::content(token))
}

We define a function to obtain basic meta data of a Facebook Page, i.e. name, about, id, and category. Take Page ID as input. Three IDs are then sent to the Function for output.

If you want to know how to find the id of a Facebook Page, just google “find facebook page id”.

read_fbpprofile <- function(pid){
  url <- paste0("https://graph.facebook.com/v2.12/",pid,"?fields=name,fan_count,about,category&access_token=",token_fb())
  out <- fromJSON(getURL(url))
  return(data.frame(out,stringsAsFactors = FALSE))
}

read_fbpprofile("5550296508")  ## CNN
##   name fan_count
## 1  CNN  29590125
##                                                             about
## 1 Instant breaking news alerts and the most talked about stories.
##             category         id
## 1 Media/News Company 5550296508
read_fbpprofile("355665009819") ## SCMP
##                       name fan_count
## 1 South China Morning Post    789133
##                                                                  about
## 1 The best news and analysis on Hong Kong, China and the rest of Asia.
##             category           id
## 1 Media/News Company 355665009819
read_fbpprofile("800660560021071") ## Hong Kong Free Press
##                        name fan_count
## 1 Hong Kong Free Press HKFP     76786
##                                                                                                       about
## 1 An English-language news source for Hong Kong. Not-for-profit, free-of-charge and completely independent.
##    category              id
## 1 Newspaper 800660560021071

Let’s try more IDs (25) and use lapply to generate a list of outputs to a variable whole_idlist. Display the first, the tenth item, and all the Page names.

id <- c("18468761129","5281959998","15779440092","219367258105115","86680728811","889307941125736","924244934290700","153080620724","184096565021911","15704546335","124955570892789","273864989376427","21516776437","13652355666","29259828486","10643211755","223649167822693","346937065399354","6250307292","95475020353","114050161948682","62317591679","18793419640","8304333127","260212261199")

whole_idlist <- lapply(id,read_fbpprofile)
length(whole_idlist)
## [1] 25
whole_idlist[[1]]
##       name fan_count             about           category          id
## 1 HuffPost   9846839 Know what's real. Media/News Company 18468761129
whole_idlist[[10]]
##       name fan_count
## 1 Fox News  16184065
##                                                                                                                                    about
## 1 Welcome to the official Fox News facebook page.  Get breaking news, must see videos and exclusive interviews from the #1 name in news.
##             category          id
## 1 Media/News Company 15704546335
sapply(whole_idlist,"[",1)  # "[" is a function that extracts part of an object. 1 means the first element.
## $name
## [1] "HuffPost"
## 
## $name
## [1] "The New York Times"
## 
## $name
## [1] "National Review"
## 
## $name
## [1] "CNN Politics"
## 
## $name
## [1] "ABC News"
## 
## $name
## [1] "Hillary Clinton"
## 
## $name
## [1] "Speaker Paul Ryan"
## 
## $name
## [1] "Donald J. Trump"
## 
## $name
## [1] "ABC News Politics"
## 
## $name
## [1] "Fox News"
## 
## $name
## [1] "Bernie Sanders"
## 
## $name
## [1] "MSNBC"
## 
## $name
## [1] "Slate.com"
## 
## $name
## [1] "USA TODAY"
## 
## $name
## [1] "The Atlantic"
## 
## $name
## [1] "NPR"
## 
## $name
## [1] "Vox"
## 
## $name
## [1] "Occupy Democrats"
## 
## $name
## [1] "Washington Post"
## 
## $name
## [1] "Breitbart"
## 
## $name
## [1] "Reuters"
## 
## $name
## [1] "POLITICO"
## 
## $name
## [1] "CNN International"
## 
## $name
## [1] "The Wall Street Journal"
## 
## $name
## [1] "BBC Newsnight"

We then define a function to read the 100 latest posts of a Facebook Page and show the first one. The last step is to check if next page of data is available to access.

#
# Read all messages posts on a Facebook Page 
# - pid : Facebook Page id
# - limit: limit of each api call, default and max is 100.
#
read_fbpgposts <- function(pid,limit=100){
  url <- paste0("https://graph.facebook.com/v2.12/",pid,"/posts?fields=id,parent_id,updated_time,created_time,link,message,comments.summary(true),likes.summary(true),shares&limit=",limit,"&access_token=",token_fb())
  out <- fromJSON(getURL(url))
  return(out)
}

hkfp_posts <- read_fbpgposts("800660560021071") ## Read 100 posts from Hong Kong Free Press
print(hkfp_posts$data[[1]])   ## Read the latest post
## $id
## [1] "800660560021071_1634512236635895"
## 
## $updated_time
## [1] "2018-02-05T09:00:01+0000"
## 
## $created_time
## [1] "2018-02-05T09:00:00+0000"
## 
## $link
## [1] "https://www.hongkongfp.com/2018/02/05/pictures-hong-kong-students-uk-protest-banning-pro-democracy-candidates-election/"
## 
## $message
## [1] "Students in London have condemned \"the heavy-handed response of Beijing to the demand for universal suffrage in Hong Kong.\""
## 
## $comments
## $comments$data
## $comments$data[[1]]
##                                                                                                                                      created_time 
##                                                                                                                        "2018-02-05T05:13:52+0000" 
##                                                                                                                                           message 
## "Should start this in all countries where there are Hong Kong students. D4HK should have a chapter in all major cities. I am happy to back them." 
##                                                                                                                                                id 
##                                                                                                               "1410333499093679_1410340929092936" 
## 
## 
## $comments$paging
## $comments$paging$cursors
##   before    after 
## "MQZDZD" "MQZDZD" 
## 
## 
## $comments$summary
## $comments$summary$order
## [1] "ranked"
## 
## $comments$summary$total_count
## [1] 1
## 
## $comments$summary$can_comment
## [1] FALSE
## 
## 
## 
## $likes
## $likes$data
## list()
## 
## $likes$paging
## $likes$paging$cursors
##                      before                       after 
## "MTAxNTk4NTc2ODE1MTU3MDUZD" "MTAxNTUyNDc4NTI1NTEyMjAZD" 
## 
## $likes$paging$`next`
## [1] "https://graph.facebook.com/v2.12/800660560021071_1634512236635895/likes?access_token=546646765498714%7CJEVSf7lnJbUOhi1wJrSQ17pHa7E&summary=true&limit=25&after=MTAxNTUyNDc4NTI1NTEyMjAZD"
## 
## 
## $likes$summary
## $likes$summary$total_count
## [1] 29
## 
## $likes$summary$can_like
## [1] FALSE
## 
## $likes$summary$has_liked
## [1] FALSE
## 
## 
## 
## $shares
## count 
##     4
is.null(hkfp_posts$paging$`next`)  ## Check if next page exists
## [1] FALSE

Last, we create a function to read all pages. Use a while loop to check until no next page is available.

#
# Read all messages posts on a Facebook Page 
# - pid : Facebook Page id
# - limit: limit of each api call, default and max is 100.
#
read_fbpgposts_ALL <- function(pid,limit=100){
  result <- list()
  url <- paste0("https://graph.facebook.com/v2.12/",pid,"/posts?fields=id,parent_id,updated_time,created_time,link,message,comments.summary(true),likes.summary(true),shares&limit=",limit,"&access_token=",token_fb())
  while (!is.null(url)){  # The while loop and check if the url is null.
    fbposts <- getURL(url)  # if not null, read the url
    if (!is.null(fbposts)){ # if at least one post
      out <- fromJSON(fbposts)
      result <- c(result,out$data) # Append the data to the list
      print(length(result)) # Show number of posts in each loop
    }
    url <- out$paging$`next`
  }
  return(result)
}

jmsc_posts_ALL <- read_fbpgposts_ALL("213429288008") ## Read all posts of JMSC FB page
## [1] 100
## [1] 200
## [1] 300
## [1] 400
## [1] 500
## [1] 600
## [1] 700
## [1] 800
## [1] 900
## [1] 1000
## [1] 1100
## [1] 1200
## [1] 1300
## [1] 1400
## [1] 1500
## [1] 1600
## [1] 1700
## [1] 1800
## [1] 1900
## [1] 2000
## [1] 2100
## [1] 2200
## [1] 2231
length(jmsc_posts_ALL) # Total number of posts
## [1] 2231
jmsc_posts_ALL[[1]]   ## Show the latest post
## $id
## [1] "213429288008_10157192203048009"
## 
## $parent_id
## [1] "1496684587325000_1977902512536536"
## 
## $updated_time
## [1] "2018-02-03T10:27:47+0000"
## 
## $created_time
## [1] "2018-02-03T10:27:47+0000"
## 
## $link
## [1] "https://www.facebook.com/hkdocumentary/photos/a.1532525097074282.1073741828.1496684587325000/1977900622536725/?type=3"
## 
## $comments
## $comments$data
## list()
## 
## $comments$summary
## $comments$summary$order
## [1] "ranked"
## 
## $comments$summary$total_count
## [1] 0
## 
## $comments$summary$can_comment
## [1] FALSE
## 
## 
## 
## $likes
## $likes$data
## list()
## 
## $likes$paging
## $likes$paging$cursors
##                       before                        after 
##       "NzY5NTg4MDI2NTYzNTg3" "MTYzNTE5NzMyNjUxNjIzOAZDZD" 
## 
## 
## $likes$summary
## $likes$summary$total_count
## [1] 2
## 
## $likes$summary$can_like
## [1] FALSE
## 
## $likes$summary$has_liked
## [1] FALSE
## 
## 
## 
## $shares
## count 
##     1