web-dev-qa-db-ja.com

Facebook Graph APIページングは​​どのように機能し、Facebookユーザーフィードを反復する方法は?

Facebookユーザーフィードを取得するためのFacebookGraphAPI呼び出しがあります。

dynamic myFeed = await fb.GetTaskAsync(
                    ("me/feed?fields=id,from {{id, name, picture{{url}} }},story,picture,link,name,description," +
                    "message,type,created_time,likes,comments")
                    .GraphAPICall(appsecret_proof));

上記は、しばらくの間、21または22の投稿など、最新のユーザー投稿の数を返しますが、ユーザー投稿の完全なリストではありません。 Facebookのページングを使用してユーザーフィードを反復処理する方法を探しましたが、Facebookのオフセットページングで機能するこのソリューションを見つけることになりました。

dynamic myFeed = await fb.GetTaskAsync(
                    ("me/feed?fields=id,from {{id, name, picture{{url}} }},story,picture,link,name,description," +
                    "message,type,created_time,likes,comments")
                    .GraphAPICall(appsecret_proof), new {limit = "1000", offset = "21" });

これにより、達成したいことに一歩近づきましたが、これは理想的な方法ではなく、すべてのユーザーの投稿が返されるわけではないと思います。回避策はありますか?助けてください。

追伸:Facebook C#SDKを使用しています。

PDATE1:ジェレミーの答えによる。 Facebookのカーソルページ付けが私の要件に対する唯一の正しいオプションのようです。 C#facebooksdkがNextEdgesを反復処理する機能を提供して、すべてのフィード投稿を1回の呼び出しで取得できるかどうかを知りたいのですが、これに対する可能な解決策はありますか? PS:私はFacebook APIドキュメントを何度も読んだことがあり、ノード、エッジ、フィールドが正確に何であるかを知っています。唯一の不幸なことは、FacebookがまだC#SDKをサポートしておらず、適切なドキュメントを見つけることができなかったことです。 Facebook C#SDKも。

9
Coding Freak

最後に、いくつかの調査を行い、いくつかのブログを読んだ後、Facebookからすべてのユーザーフィーダーの投稿を一度に取得する直接のAPI CAllsがないことがわかりました。その機能を実現するには、Jeremy Thomsonが提案するように無限スクロールを実行するか、Edgeでサポートされているfacebook paginationタイプに関係なくさまざまなFacebookデータページを反復処理する必要があります。ユーザーの干渉やアクションのないプロセスが必要な限り、Facebookのデータページをwhileループで反復する2番目のオプションを使用します。そのためには、まず、以下に説明する2つの最も重要なパラメーター(facebook access_token +(facebook appsecret_proof)が必要です。

var appsecret_proof = access_token.GenerateAppSecretProof();
var fb = new FacebookClient(access_token);

覚えておくべきポイント:facebook access_tokenHttpContextクラスによって生成されます。

FacebookのAPI呼び出しは、以下のようにユーザーに最初の25フィーダー投稿を取得します。

dynamic myFeed = await fb.GetTaskAsync(
                    ("me/feed?fields=id,from {{id, name, picture{{url}} }},story,picture,link,name,description," +
                    "message,type,created_time,likes,comments")
                    .GraphAPICall(appsecret_proof));

上記のAPI呼び出しは、Json配列になり、次に示すようにModel Viewプロパティを介してハイドレイトする必要があります。

var postList = new List<FacebookPostViewModel>();
    foreach (dynamic post in myFeed.data)
       {
         postList.Add(DynamicExtension.ToStatic<FacebookPostViewModel>(post));
       }

ここまですべてが明確になるまで、Facebookユーザーの投稿を確実に取得するという最も重要な部分が実行されています。そのためには、次のようにstringNextPageUriを空に設定する必要があります。

string NextPageURI = string.Empty;

すべての最後の部分は、データの別のページがあるかどうかを確認することです。ある場合は、次に示すように、ページリフトがなくなるまでデータを繰り返してView Modelに追加する必要があります。

while (myFeed.paging != null && myFeed.paging.next != null)
                {
                    NextPageURI = myFeed.paging.next;
                    var nextURL = GetNextPageQuery(NextPageURI, access_token);
                    dynamic nextPagedResult = await fb.GetTaskAsync(nextURL.GraphAPICall(appsecret_proof));
                    foreach (dynamic post in nextPagedResult.data)
                    {
                        postList.Add(DynamicExtension.ToStatic<FacebookPostViewModel>(post));
                    }
                }

これは私が直面している問題を取り除くのに役立ちました。しかし、それでも私には別の課題があります。投稿が30kを超える場合、10分かかるのは投稿の取得速度であり、少なくとも私にとっては理想的ではありません。

1
Coding Freak

最初に少し用語を説明します。

nodes-基本的に、ユーザー、写真、ページ、コメントなどの「もの」
edges-ページの写真や写真のコメントなどの「モノ」間の接続
fields-人の誕生日やページの名前など、これらの「もの」に関する情報

ノードまたはエッジに対してAPIリクエストを行う場合、通常、そのリクエストのすべての結果を1つのレスポンスで受け取るわけではありません。これは、一部の応答には数千のオブジェクトが含まれる可能性があるため、ほとんどの応答はデフォルトでページ付けされているためです。

ユーザーによるすべての投稿を取得するには、次の3つのオプションがあります。


カーソルベースのページ付け

カーソルベースのページングは​​、ページングの最も効率的な方法であり、可能な場合は常に使用する必要があります。カーソルは、データのリスト内の特定の項目をマークする文字のランダムな文字列を参照します。このアイテムが削除されない限り、カーソルは常にリストの同じ部分を指しますが、アイテムが削除されると無効になります。したがって、アプリは古いカーソルを保存したり、それらがまだ有効であると想定したりしないでください。

カーソルのページ付けをサポートするEdgeを読み取ると、次のJSON応答が表示されます。

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}

ユーザーによるすべての投稿を取得するには、「次の」エッジをサーフィンし続けます(新しいアイテムをアップサーティングします)。これは、統計分析のためにグループ全体をRDBMSにダンプするときに行う方法です。多くの場合、すでに遭遇したノードのエッジが表示されます。そのため、UPSERTに言及します(存在する場合は更新し、そうでない場合は挿入します)。

時間ベースのページ付け

時間のページ付けは、データのリスト内の特定の時間を指すUnixタイムスタンプを使用して結果データをナビゲートするために使用されます。

時間ベースのページ付けを使用するエンドポイントを使用すると、次のJSON応答が表示されます。

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "previous": "https://graph.facebook.com/me/feed?limit=25&since=1364849754",
    "next": "https://graph.facebook.com/me/feed?limit=25&until=1364587774"
  }
}

すべてのユーザーの投稿を取得するには、時間を遡って繰り返します。このメソッドは投稿を順番に取得しますが、FaceBooksEdgeアルゴリズムによって順番に返されるようにしたい場合があります。

オフセットベースのページ付け

オフセットページネーションは、時系列を気にせず、特定の数のオブジェクトを返すだけの場合に使用できます。これは、Edgeがカーソルまたは時間ベースのページ付けをサポートしていない場合にのみ使用する必要があります。

したがって、Offsetで見つけたものは、希望する標準のページ付けに最も近いものです。しかしながら:

オフセットベースのページ付けは、すべてのAPI呼び出しでサポートされているわけではありません。一貫した結果を得るには、応答で返される前/次のリンクを使用してページ付けすることをお勧めします。

これはすべて、FBAPIドキュメントで読むことができます。

https://developers.facebook.com/docs/graph-api/overview/
https://developers.facebook.com/docs/graph-api/using-graph-api/

9
Jeremy Thompson