본문 바로가기

프로그래밍/Delphi

페이스북(Facebook) Feed 읽어들이기

1. 개요

  페이스북의 계정별 FEED를 별도의 개발자 인증 과정 없이 손쉽게 읽기 위한 방법을 델파이로 구현한다.


2. 알아야 할 것들.

   - 페이스북 Feed를 읽기 위한 AccessToken 얻기

     개인별 페이스북 계정에 로그인 한 후에 다음 URL로 접근한다.

https://developers.facebook.com/tools/explorer/145634995501895/?method=GET&path=feedname%2Ffeed%3Ffields%3Did%2Cname%2Cmessage%2Clink%2Ccaption%2Csource%2Cpermalink_url%26limit%3D100&version=v2.6 


* feedname에는 수집하고자 하는 feed명을 넣어 주면 된다.

* 예를 들어 삼성전자 페이스북 FEED명은 sumsung 이다.


   - AccessToken 확인과 Feed를 API를 이용해 호출한 결과를 Json data로 확인이 가능하다.



- 수집대상 필드 조정하기 : 좌측에 "Search for a field"를 클릭하여 feed json data에 추가될 필드를 지정한다.


  - 엑세스토큰(AccessToken) : 피드 API를 호출하려면 AccessToken을 얻어야 하는데 위 화면을 리프레시 하면 AccessToken을 새로 발급 받을 수 있으며 테스트로 호출된 Json 페이지를 호출하는 API는 하단 "코드받기"를 클릭하여 개발 어플리케이션별 활용 가능한 API를 확인 할 수 있다.


  - 그림에서는 http로 호출하기 위한 URL을 얻을 수 있다.



3. DB-테이블 스키마(MSSQL)

   - TABLE : facebook_data 

drop table facebook_data

create table facebook_data
(
	SN numeric primary key identity(1,1),
	[SID] int null,
	CONFIRM int,
	GDATE DateTime,
	SeasonID Int,
	FB_ID nvarchar(60),
	FB_NAME nvarchar(100),
	FB_FROM_NAME nvarchar(100),
	FB_FROM_ID nvarchar(100),
	FB_LINK nvarchar(1000),
	FB_PERMALINK_URL nvarchar(1000),
	FB_CREATED_TIME datetime,
	FB_UPDATED_TIME datetime,
	FB_FULL_PICTURE nvarchar(1000),
	FB_CONTENTS NVARCHAR(MAX),
	FB_DESCRIPTION NVARCHAR(MAX),
	FB_STORY NVARCHAR(MAX),
	FB_MESSAGE NVARCHAR(MAX),
)

create index IDX_SID on facebook_data ([SID])
create index IDX_FB_ID on facebook_data (FB_ID)

select * from facebook_data


   - StoredProcedure : usp_facebook_insert : feed 데이터 삽입

ALTER PROCEDURE [dbo].[usp_facebook_insert]
	@SN numeric output
	, @SID int
	, @CONFIRM int
	, @GDATE datetime
	, @SeasonID int
	, @FB_ID nvarchar(60)
	, @FB_NAME nvarchar(100)
	, @FB_FROM_NAME nvarchar(100)
	, @FB_FROM_ID nvarchar(100)
	, @FB_LINK nvarchar(1000)
	, @FB_PERMALINK_URL nvarchar(1000)
	, @FB_CREATED_TIME datetime
	, @FB_UPDATED_TIME datetime
	, @FB_FULL_PICTURE nvarchar(1000)
	, @FB_CONTENTS nvarchar(max)
	, @FB_DESCRIPTION nvarchar(2000)
	, @FB_STORY nvarchar(1000)
	, @FB_MESSAGE nvarchar(2000)
AS
BEGIN
	SET NOCOUNT ON;

	IF (@SN=0) 
		IF EXISTS(SELECT SN FROM facebook_data WHERE FB_ID=@FB_ID)	
			SELECT @SN=SN FROM facebook_data WHERE FB_ID=@FB_ID
			
	IF (@SN=0) -- INSERT MODE
	BEGIN
		INSERT INTO facebook_data
			([SID], CONFIRM, GDATE, SeasonID, FB_ID, FB_NAME, FB_FROM_NAME, FB_FROM_ID, FB_LINK, FB_PERMALINK_URL, 
			 FB_CREATED_TIME, FB_UPDATED_TIME, FB_FULL_PICTURE, FB_CONTENTS, FB_DESCRIPTION, FB_STORY, FB_MESSAGE)
		VALUES
			(@SID, @CONFIRM, @GDATE, @SeasonID, @FB_ID, @FB_NAME, @FB_FROM_NAME, @FB_FROM_ID, @FB_LINK, @FB_PERMALINK_URL, 
			 @FB_CREATED_TIME, @FB_UPDATED_TIME, @FB_FULL_PICTURE, @FB_CONTENTS, @FB_DESCRIPTION, @FB_STORY, @FB_MESSAGE)
			 
		SET @SN=@@IDENTITY
	END
	ELSE
		UPDATE facebook_data
		SET
			[SID]= @SID
			, CONFIRM=@CONFIRM
			, GDATE=@GDATE
			, SeasonID=@SeasonID
			, FB_ID=@FB_ID
			, FB_NAME=@FB_NAME
			, FB_FROM_NAME=@FB_FROM_NAME
			, FB_FROM_ID=@FB_FROM_ID
			, FB_LINK=@FB_LINK
			, FB_PERMALINK_URL=@FB_PERMALINK_URL
			, FB_CREATED_TIME=@FB_CREATED_TIME
			, FB_UPDATED_TIME=@FB_UPDATED_TIME
			, FB_FULL_PICTURE=@FB_FULL_PICTURE
			, FB_CONTENTS=@FB_CONTENTS
			, FB_DESCRIPTION=@FB_DESCRIPTION
			, FB_STORY=@FB_STORY
			, FB_MESSAGE=@FB_MESSAGE
		WHERE
			SN = @SN
			
END


   - StoredProcedure : usp_facebook_update : feeddata 갱신


ALTER PROCEDURE [dbo].[usp_facebook_update]
	@SN numeric
	, @SID int
	, @CONFIRM int
	, @GDATE datetime
	, @SEASONID int
	, @FB_ID nvarchar(60)
	, @FB_NAME nvarchar(100)
	, @FB_FROM_NAME nvarchar(100)
	, @FB_FROM_ID nvarchar(100)
	, @FB_LINK nvarchar(1000)
	, @FB_PERMALINK_URL nvarchar(1000)
	, @FB_CREATED_TIME datetime
	, @FB_UPDATED_TIME datetime
	, @FB_FULL_PICTURE nvarchar(1000)
	, @FB_CONTENTS nvarchar(max)
	, @FB_DESCRIPTION nvarchar(2000)
	, @FB_STORY nvarchar(1000)
	, @FB_MESSAGE nvarchar(2000)
AS
BEGIN
	SET NOCOUNT ON;

	UPDATE facebook_data
	SET
		[SID]= @SID
		, CONFIRM=@CONFIRM
		, GDATE=@GDATE
		, SeasonID=@SeasonID
		, FB_ID=@FB_ID
		, FB_NAME=@FB_NAME
		, FB_FROM_NAME=@FB_FROM_NAME
		, FB_FROM_ID=@FB_FROM_ID
		, FB_LINK=@FB_LINK
		, FB_PERMALINK_URL=@FB_PERMALINK_URL
		, FB_CREATED_TIME=@FB_CREATED_TIME
		, FB_UPDATED_TIME=@FB_UPDATED_TIME
		, FB_FULL_PICTURE=@FB_FULL_PICTURE
		, FB_CONTENTS=@FB_CONTENTS
		, FB_DESCRIPTION=@FB_DESCRIPTION
		, FB_STORY=@FB_STORY
		, FB_MESSAGE=@FB_MESSAGE
	WHERE
		SN = @SN
			
END


   - StoredProcedure : usp_facebook_getlist : feed data얻기



CREATE PROCEDURE [dbo].[usp_facebook_getlist]
	@SID int,
	@SeasonID int = -1,
	@Confirm int = -1,
	@Top int = 0
AS
BEGIN
	SET NOCOUNT ON;

	DECLARE @WHERE VARCHAR(100)
	DECLARE @SQL VARCHAR(200)
	
	
	SET @WHERE = 'SID=' + STR(@SID)
	IF (@SeasonID>-1)
		SET @WHERE = @WHERE + ' AND SeasonID=' + STR(@SeasonID)
		
	IF (@Confirm>-1)
		SET @WHERE = @WHERE + ' AND Confirm=' + STR(@Confirm)
		
	IF (@Top>0)
		SET @SQL = 'SELECT TOP '+STR(@Top) + ' * FROM facebook_data WHERE ' + @WHERE
	ELSE
		SET @SQL = 'SELECT * FROM facebook_data WHERE ' + @WHERE
	
	SET @SQL = @SQL + ' ORDER BY SN ASC'
		
	exec sp_executesql @SQL	
END



4. FEED 수집 프로세스

   가. Facebook에 사용자 계정으로 로그인 한다.

   나. https://developers.facebook.com/tools feed툴 페이지에 접근하여 AccessToken을 얻는다.

   다. Feed샘플을 확인하고 코드 얻기를 통해 Get방식의 URL 정보를 얻고 적당히 가공한다. (요청 필드 목록들 추가)

   라. 얻어진 URL에서 AccessToken만을 바꿔가며 매번 수집한다(AccessToken은 발급 받은지 1시간 경과하면 Expired된다)

   마. 얻어진 json 데이터를 파싱하여 각각의 레코드로 기록한다.

   바. 페이지 네비게이션을 위해서는 json 데이터 하단의 "next" value를 얻어서 다음페이지 네비게이션을 반복 한다.

   * 특정날짜 이후는 URL에 "since=2016-01-01"과 같은 형식으로 적어준다.

   * 한번에 얻을 수 있는 Acticle의 최대(limit) 갯수는 100개 까지이며 limit=100 처럼 적어준다.


5. FACEBOOK Feed 수집을 위한 델파이 소스

  - 참고로 데이터 객체의 부모클래스인 "TbnContent"는 JsonToObject / ObjectToJson 으로 json 데이터를 읽고 쓸 수 있는 기능이 구현되어 있다.

  - 웹 Request는 인디의 TIdHTTP 컴포넌트를 이용하였다.

  - 필드 : SID는 수집피드 정보원 ID쯤으로 생각하면 된다.

  - TFacebookArticled의 private 섹션의 중요 필드들은 실제 Json data내의 필드명과 일치 시켜야 객체의 JsonToObject를 통해 자동으로 객체화 시킬 수 있다.

  - 예약어 등으로 필드명을 일치시키지 못할 경우에는 수신한 json data의 소스를 "srcfield" --> "destfield"로 사전 변경처리하는 과정이 필요하다.


unit uFacebookData;

interface

uses
  Classes, SysUtils, uCommonData, Json, RTTI, uDebug, IdHTTP, DB, ADODB;

const
  URL_FACEBOOK_AUTH = 'https://developers.facebook.com/tools/explorer/145634995501895/?method=GET&path=gyeonkorea%2Ffeed%3Fsince%3D2016-01-01%26limit%3D100&version=v2.6';
  ERROR_CODE = 'OAuthException';
  FEED_DOMAIN = 'https://graph.facebook.com/v2.6/';
  DEFAULT_ACCESS_TOKEN = 'EAAN9hkawNL8BABZBjpVbUqtTbGe9PVllwipa0FCKTtWGdZBMIaMdNfdltZBSrihmJMY1Tyf1jHRXuFWYiRHvrUmllI7x5I6UDy4ZB9lyXAN5aoRG50kCZB4sXI5mpfkGZBp4b4i9M47UZACUImo9E2fNACW6ZBrQB61ESAdEbfLDigZDZD';
  DEFAULT_PARAMS = '/feed?since=@SINCE&fields=caption%2Cdescription%2Cfull_picture%2Cid%2Cfrom%2Clink%2Cmessage%2Cname%2Cpermalink_url%2Cstory%2Ccreated_time%2Cupdated_time&limit=100&access_token=';

type
  TFacebookUser = class(TbnContent)
  private
    //페북 글쓴 아이디
    fbname: String;
    //페북 글쓴 이름
    id: String;
  public
  end;

  TFacebookArticle = class(TbnContent)
  private
    //JSONData에 의해서 자동으로 읽히는 부분
    //페북 아티클 아이디
    id : String;
    //페북 아티클 작성자 정보
    from : TFacebookUser;
    //이름
    fbname : String;
    //페북 아티클 바로가기 링크
    link : String;
    //페북 아티클 바로가기 링크(영구적인)
    permalink_url : String;
    //페북 아티클 생성일시
    created_time : TDateTime;
    //페북 아티클 수정일시
    updated_time : TDateTime;
    //페북 이미지 풀경로
    full_picture : String;
    //페북 아티클 메시지(원본은 message 필드인데 델파이 예약어로 소스에서 contents로 변경 처리
    contents : string;
    //설명글
    description : String;
    //스로리
    story : String;
    //메시지
    fbmessage : String;

    //JSONDATA와 무관한 정보
    //페북단위 정보원 ID
    FSID: Integer;
    //수집일련번호
    FSn: Int64;
    //수집일시
    FGDate: TDateTime;
    //예약필드 - 검수확인
    FConfirm : Integer;
    //수집 회차번호 - 회차를 달리하여 새로 수집될 수 있다.
    FSeasonID: Integer;

    procedure Read(Asds: TDataSet); override;
    procedure Write(Asds: TDataSet); override;
  public
    property Sn : Int64 read FSn write FSn;
    property SID : Integer read FSID write FSID;
    property GDate : TDateTime read FGDate write FGDate;
    property Confirm : Integer read FConfirm write FConfirm;
    property SeasonID : Integer read FSeasonID write FSeasonID;

    function ToString : string; override;

    procedure Insert; override;
    procedure Delete; override;
    procedure Update; override;

    constructor Create(ASQLConn: TUnivConnection); override;
    destructor Destroy; override;

    procedure JSONToObject(AJSONString: String); override;
  end;

  TFacebookData = class(TbnContentList)
  private
    FSID: Integer;
    function _GetFacebookArticle(nIdx: Integer): TFacebookArticle;
    procedure _SetSID(const Value: Integer);
  public
    property SID : Integer read FSID write _SetSID;
    property Items[nIdx : Integer] : TFacebookArticle read _GetFacebookArticle;

    procedure LoadData(ASID : Integer; ATop : Integer = 0; ASeasonID : Integer = -1; AConfirm : Integer = -1);
    procedure Save;
  end;


  TFacebookCollector = class(TIdHTTP)
  private
    FFeed: String;
    FFacebookData: TFacebookData;
    FSID: Integer;
    function _GetURL: String;
  public
    property Feed : String read FFeed write FFeed;
    property FacebookData : TFacebookData read FFacebookData write FFacebookData;
    property URL : String read _GetURL;

    constructor Create(AOwner : TComponent; AFacebookData : TFaceBookData; AFeed : String); overload;

    procedure GetFacebookData(ASID : Integer; ABeginDate : TDateTime; AAccessToken : String);
  end;

  procedure ParseJsonForFacebook(AJsonData : String; AFaceBookData : TFacebookData);
  procedure ParseJsonFileForFacebook(AJsonFile : String; AFaceBookData : TFacebookData);


implementation
uses
  uStringManager;

procedure ParseJsonFileForFacebook(AJsonFile : String; AFaceBookData : TFacebookData);
var
  sl : TStringList;
begin
  try
    sl := TStringList.Create;
    sl.LoadFromFile(AJsonFile);
    ParseJsonForFacebook(sl.Text, AFaceBookData);
  finally
    sl.Free;
  end;
end;

procedure ParseJsonForFacebook(AJsonData : String; AFaceBookData : TFacebookData);
var
  jsonString : String;
begin
  try
    jsonString :=  StringReplace(AJsonData, '"name"', '"fbname"', [rfReplaceAll]);
    jsonString := StringReplace(jsonString, '"message"', '"fbmessage"', [rfReplaceAll]);
    AFaceBookData.JSONToObject(jsonString, TFacebookArticle, 'data', false);
  finally

  end;
end;

{ TFacebookData }

procedure TFacebookData._SetSID(const Value: Integer);
var
  i : integer;
begin
  FSID := Value;

  for i := 0 to count-1 do
    Items[i].SID := SID;
end;


procedure TFacebookData.LoadData(ASID, ATop, ASeasonID, AConfirm: Integer);
var
  objFB : TFacebookArticle;
  ads : TUnivStoredProc;
begin
  ClearAll;

  ads := TBaseContent.CreateStoredProc(self.SQLCon);
  try
    ads.ProcedureName := 'usp_facebook_getlist';
    ads.ClearParams;
    ads.CreateParameter('@SID', ftInteger, pdInput, SizeOf(integer), ASID);
    ads.CreateParameter('@SeasonID', ftInteger, pdInput, SizeOf(integer), ASeasonID);
    ads.CreateParameter('@Confirm', ftInteger, pdInput, SizeOf(integer), AConfirm);
    ads.CreateParameter('@Top', ftInteger, pdInput, SizeOf(integer), ATop);
    ads.Open;

    while not ads.Eof do
    begin
      objFB := TFacebookArticle.Create(SQLCon);
      objFB.Read(ads);

      Add(objFB);

      ads.Next;
    end;

  finally
    ads.Free;
  end;
end;

procedure TFacebookData.Save;
var
  i : integer;
  objFB : TFacebookArticle;
begin
  for i := 0 to count-1 do
  begin
    objFB := Items[i];
    objFB.Insert; // AutoUpdate
  end;
end;

function TFacebookData._GetFacebookArticle(nIdx: Integer): TFacebookArticle;
begin
  result := TFacebookArticle(Get(nIdx));
end;

{ TFacebookArticle }

constructor TFacebookArticle.Create(ASQLConn: TUnivConnection);
begin
  inherited;
  from := TFacebookUser.Create(SQLConn);
  GDate := now;
end;

procedure TFacebookArticle.Delete;
begin
  inherited;

end;

destructor TFacebookArticle.Destroy;
begin
  from.Free;

  inherited;
end;

procedure TFacebookArticle.Insert;
var
  ads : TUnivStoredProc;
begin
  if sn>0 then
    Update
  else
  begin
  ads := TBaseContent.CreateStoredProc(SQLConn);
    try
      ads.ProcedureName := 'usp_facebook_insert';
      Write(ads);
      ads.ExecProc;
      sn := ads.Parameters.ParamByName('@SN').Value;
    finally
      ads.Free;
    end;
  end;
end;

function TFacebookArticle.ToString: string;
var
  sl : TStringList;
begin
  sl := TStringList.Create;
  sl.Add('SN = ' + intToStr(SN));
  sl.Add('SID = ' + intToStr(SID));
  sl.Add('CONFIRM = ' + intToStr(Confirm));
  sl.Add('GDATE = ' + formatDateTime('yyyy-mm-dd', GDate));
  sl.Add('id = ' + id);
  sl.Add('link = ' + link);
  sl.Add('fbname = ' + fbname);
  sl.Add('from.id = ' + from.id);
  sl.Add('from.fbname = ' + from.fbname);
  sl.Add('created_time = ' + formatDateTime('yyyy-mm-dd hh:nn:ss', created_time));
  sl.Add('updated_time = ' + formatDateTime('yyyy-mm-dd hh:nn:ss', updated_time));
  sl.Add('permalink = ' + permalink_url);
  sl.Add('contents = ' + contents);
  sl.Add('description = ' + description);
  sl.Add('story = ' + story);
  sl.Add('message = ' + fbmessage);
  result := sl.Text;
  sl.free;
end;

procedure TFacebookArticle.Update;
var
  ads : TUnivStoredProc;
begin
  if sn=0 then
    Insert
  else
  begin
    ads := TBaseContent.CreateStoredProc(SQLConn);
    try
      ads.ProcedureName := 'usp_facebook_update';
      Write(ads);
      ads.ExecProc;
    finally
      ads.Free;
    end;
  end;
end;

procedure TFacebookArticle.Write(Asds: TDataSet);
var
  univAds : TUnivStoredProc;
begin
  univAds := TUnivStoredProc(Asds);
  univAds.ClearParams;
  univAds.CreateParameter('@SN', ftInteger, pdInputOutput, SizeOf(int64), Sn);
  univAds.CreateParameter('@SID', ftInteger, pdInput, SizeOf(integer), SID);
  univAds.CreateParameter('@CONFIRM', ftInteger, pdInput, SizeOf(integer), Confirm);
  univAds.CreateParameter('@GDATE', ftDateTime, pdInput, SizeOf(TDateTime), GDate);
  univAds.CreateParameter('@SEASONID', ftInteger, pdInput, SizeOf(integer), SeasonID);
  univAds.CreateParameter('@FB_ID', ftWideString, pdInput, 60, id);
  univAds.CreateParameter('@FB_NAME', ftWideString, pdInput, 100, fbName);
  univAds.CreateParameter('@FB_FROM_NAME', ftWideString, pdInput, 100, from.fbname);
  univAds.CreateParameter('@FB_FROM_ID', ftWideString, pdInput, 100, from.id);
  univAds.CreateParameter('@FB_LINK', ftWideString, pdInput, 1000, link);
  univAds.CreateParameter('@FB_PERMALLINK_URL', ftWideString, pdInput, 1000, permalink_url);
  univAds.CreateParameter('@FB_CREATED_TIME', ftDateTime, pdInput, SizeOf(TDateTime), created_time);
  univAds.CreateParameter('@FB_UPDATED_TIME', ftDateTime, pdInput, SizeOf(TDateTime), updated_time);
  univAds.CreateParameter('@FB_FULL_PICTURE', ftWideString, pdInput, 1000, full_picture);
  univAds.CreateParameter('@FB_CONTENTS', ftWideMemo, pdInput, 16, '');
  univAds.CreateParameter('@FB_DESCRIPTION', ftWideMemo, pdInput, 16, '');
  univAds.CreateParameter('@FB_STORY', ftWideMemo, pdInput, 16, '');
  univAds.CreateParameter('@FB_MESSAGE', ftWideMemo, pdInput, 16, '');
  univAds.Parameters.ParamByName('@FB_CONTENTS').Value := contents;
  univAds.Parameters.ParamByName('@FB_DESCRIPTION').Value := description;
  univAds.Parameters.ParamByName('@FB_STORY').Value := story;
  univAds.Parameters.ParamByName('@FB_MESSAGE').Value := fbmessage;
end;

procedure TFacebookArticle.JSONToObject(AJSONString: String);
var
  RttiContext: TRttiContext;
  RttiType: TRttiType;
  FieldCount : Integer;
  RttiField : TRttiField;

  JsonObject : TJsonObject;
  JsonValue : TJsonValue;
  JsonArray : TJsonArray;
  JsonPair : TJsonPair;
  PairCount : Integer;
begin
  if AJSONString='' then
    exit;

  TRACE('ClassType : ' + self.ClassName);
  //현재 객체의 런타임 클래스 타입 정보를 얻는다.
  RttiType := RttiContext.GetType(self.ClassType);
  //전달받은 JSON문자열을 JSON객체로 파싱한다.
  JsonObject := TJSONObject.ParseJSONValue(AJSONString) as TJsonObject;
  try
    //클래스의 필드를 순회 하면서 각 필드를 처리한다.
    for RttiField in RttiType.GetFields do
    begin
      try
        JsonValue := JsonObject.GetValue(RttiField.Name) as TJSONValue;
        if RttiField.Name='from' then
          from.JSONToObject(JsonValue.ToString)
        else
        begin
          if JsonValue<>nil then
            SetRttiFieldValue(RttiField, JsonValue);
        end;
      except
        on e:Exception do
        begin
          TRACE('Error : RttiField.Name=' + RttiField.Name + ', JsonValue.Value=' + JsonValue.Value + #13+
            e.Message);
        end;
      end;
    end;
  finally
    JsonObject.Free;
  end;
end;

procedure TFacebookArticle.Read(Asds: TDataSet);
var
  univAds : TUnivStoredProc;
begin
  univAds := TUnivStoredProc(Asds);
  Sn := univAds.FieldByName('SN').AsInteger;
  SID := univAds.FieldByName('SID').AsInteger;
  Confirm := univAds.FieldByName('Confirm').AsInteger;
  SeasonID := univAds.FieldByName('SeasonID').AsInteger;
  id := univAds.FieldByName('FB_ID').AsString;
  fbname := univAds.FieldByName('FB_NAME').AsString;
  from.fbname := univAds.FieldByName('FB_FROM_NAME').AsString;
  from.id := univAds.FieldByName('FB_FROM_ID').AsString;
  link := univAds.FieldByName('FB_LINK').AsString;
  permalink_url := univAds.FieldByName('FB_PERMALINK_URL').AsString;
  created_time := univAds.FieldByName('FB_CREATED_TIME').AsDateTime;
  updated_time := univAds.FieldByName('FB_UPDATED_TIME').AsDateTime;
  full_picture := univAds.FieldByName('FB_FULL_PICTURE').AsString;
  contents := univAds.FieldByName('FB_CONTENTS').AsString;
  description := univAds.FieldByName('FB_DESCRIPTION').AsString;
  story := univAds.FieldByName('FB_STORY').AsString;
  fbmessage := univAds.FieldByName('FB_MESSAGE').AsString;
end;

{ TFacebookCollector }

constructor TFacebookCollector.Create(AOwner: TComponent;
  AFacebookData: TFaceBookData; AFeed : String);
begin
  inherited Create(AOwner);

  FacebookData := AFacebookData;
  Feed := AFeed;
end;

procedure TFacebookCollector.GetFacebookData(ASID : Integer; ABeginDate: TDateTime;
  AAccessToken: String);
var
  runURL : String;
  responseStream : TStringStream;
  i : integer;
begin
  runURL := StringReplace(URL + AAccessToken, '@SINCE', formatDateTime('yyyy-mm-dd', ABeginDate), []);

  FacebookData.ClearAll;

  responseStream := TStringStream.Create;
  try
    i := 0;
    while runURL<>'' do
    begin
      inc(i);
      responseStream.Clear;
      Get(runURL, responseStream);
      ParseJsonForFacebook(responseStream.DataString, FacebookData);
      runURL := sm.mid('"next":"', '"', responseStream.DataString);
      runURL := StringReplace(runURL, '\/', '/', [rfReplaceAll]);
      FacebookData.SID := ASID; //해주어야만 모든 객체에 SID 값이 전파 된다.
      FacebookData.Save;
    end;
  finally
    responseStream.free;
  end;
end;

function TFacebookCollector._GetURL: String;
begin
  result := FEED_DOMAIN + Feed + DEFAULT_PARAMS;
end;

end.

- 샘플소스


procedure TfrmMainFacebook.Button1Click(Sender: TObject);
var
  fc : TFacebookCollector;
begin
  fc := TFacebookCollector.Create(self, FacebookData, 'gyeonkorea');
  fc.GetFacebookData(1, cl.StrToDateTime('2016-01-01'), AccessToken);
  FacebookData.LoadData(1);
  Memo2.Lines.Text := FacebookData.ToString;
  fc.Free;
end;


6. FACEBOOK Feed 수집테스트 결과(총 수집건수 212건)