Facebook Graph API 分页如何工作以及如何使用它迭代 facebook 用户提要?
How does Facebook Graph API Pagination works and how to iterate facebook user feed with it?
我有一个 facebook Graph API 调用来获取 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));
上面 return 是一些最新的用户帖子,说是 21 或 22 个帖子,但不是完整的用户帖子列表。
我搜索了一种使用 facebook 分页遍历用户提要的方法,最终找到了适用于 facebook Offset 分页的解决方案。
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" });
这让我离我想要实现的目标又近了一步,但我认为这不是实现它的理想方式,而且它并不是 return 所有用户的帖子。
有什么解决方法吗?请帮忙。
P.S: 我正在使用 Facebook C# SDK。
更新 1:
根据杰里米的回答。看来 facebook 光标分页是满足我的要求的唯一正确选择。我想知道 C# facebook sdk 是否提供任何功能来迭代 Next Edges 以便我可以在一次调用中获取所有提要帖子,是否有任何可能的解决方案?
P.S:我看过 facebook API 文档很多次,我知道节点、边和字段到底是什么,唯一不幸的是 facebook 还不支持 C# SDK,我也无法在 Facebook C# SDK 上找到合适的文档。
首先介绍一些术语:
节点 - 基本上"things" 例如用户、照片、页面、评论
edges - "things" 之间的联系,例如主页的照片或照片的评论
字段 - 有关这些 "things" 的信息,例如个人生日或主页名称
当您向节点或边缘发出 API 请求时,您通常不会在单个响应中收到该请求的所有结果。这是因为某些响应可能包含数千个对象,因此默认情况下大多数响应都是分页的。
要获取用户的所有帖子,您有 3 个选项:
基于光标的分页
基于光标的分页是最有效的分页方法,应尽可能使用。游标是指随机字符串,它标记数据列表中的特定项目。除非删除此项,否则光标将始终指向列表的同一部分,但如果删除了一项,则光标将失效。因此,您的应用不应存储任何旧游标或假设它们仍然有效。
读取支持游标分页的边缘时,您将看到以下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="
}
}
To get all posts by a user you keep surfing the "next" edges (upserting new items). This is how I do it when I dump entire groups into RDBMS's for statistical analysis. Often you will see edges with nodes you have already encountered, that's why I mention to UPSERT (update if it exists otherwise insert).
基于时间的分页
时间分页用于使用指向数据列表中特定时间的 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"
}
}
要获取所有用户的帖子,您需要及时迭代。此方法将使您按顺序获得帖子,尽管可能希望它们 return 按 FaceBooks 边缘算法的顺序排列。
基于偏移的分页
当您不关心时间顺序而只想要特定数量的对象时,可以使用偏移分页 returned。仅当边缘不支持光标或基于时间的分页时才应使用此方法。
因此,您发现 Offset 最接近您想要的标准分页。然而:
并非所有 API 调用都支持基于偏移量的分页。为了获得一致的结果,我们建议您使用我们在响应中 return 的 previous/next 链接进行分页。
您可以在 FB API 文档中阅读所有这些内容。
https://developers.facebook.com/docs/graph-api/overview/
https://developers.facebook.com/docs/graph-api/using-graph-api/
最后,在做了一些研究并阅读了一些博客之后,我发现没有直接从 facebook API CAlls
一次获取所有用户供稿器 post 的方法。
要实现该功能,要么必须按照 Jeremy Thomson 的建议进行无限滚动,要么遍历不同的 facebook 数据页面,而不管 edge
支持哪种 facebook pagination
类型。就我想要一个没有用户 interference/actions 的进程而言,我肯定会选择第二个选项,即使用 while
循环遍历 facebook 数据页面。
为此,我们首先需要两个最重要的参数 (facebook access_token
+ (facebook appsecret_proof
),如下所述:
var appsecret_proof = access_token.GenerateAppSecretProof();
var fb = new FacebookClient(access_token);
Point to be remembered:
facebook access_token
is generated by HttpContext
class.
facebook API
呼叫将获得用户前 25 个馈线 post 如下:
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
调用 return 产生了一个 Json
数组,应该通过 Model View
属性对其进行水化,如下所示:
var postList = new List<FacebookPostViewModel>();
foreach (dynamic post in myFeed.data)
{
postList.Add(DynamicExtension.ToStatic<FacebookPostViewModel>(post));
}
到这里之前一切都很清楚,最重要的部分肯定是获取所有 facebook 用户 post 现在正在运行。为此,我们需要将 string
NextPageUri
设置为空,如下所示:
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));
}
}
这帮助我摆脱了面临的问题。但我还有另一项任务要处理。这是获取 posts 的速度,如果 posts 超过 30k,则需要 10 分钟,这至少对我来说并不理想。
我有一个 facebook Graph API 调用来获取 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));
上面 return 是一些最新的用户帖子,说是 21 或 22 个帖子,但不是完整的用户帖子列表。 我搜索了一种使用 facebook 分页遍历用户提要的方法,最终找到了适用于 facebook Offset 分页的解决方案。
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" });
这让我离我想要实现的目标又近了一步,但我认为这不是实现它的理想方式,而且它并不是 return 所有用户的帖子。 有什么解决方法吗?请帮忙。
P.S: 我正在使用 Facebook C# SDK。
更新 1: 根据杰里米的回答。看来 facebook 光标分页是满足我的要求的唯一正确选择。我想知道 C# facebook sdk 是否提供任何功能来迭代 Next Edges 以便我可以在一次调用中获取所有提要帖子,是否有任何可能的解决方案? P.S:我看过 facebook API 文档很多次,我知道节点、边和字段到底是什么,唯一不幸的是 facebook 还不支持 C# SDK,我也无法在 Facebook C# SDK 上找到合适的文档。
首先介绍一些术语:
节点 - 基本上"things" 例如用户、照片、页面、评论
edges - "things" 之间的联系,例如主页的照片或照片的评论
字段 - 有关这些 "things" 的信息,例如个人生日或主页名称
当您向节点或边缘发出 API 请求时,您通常不会在单个响应中收到该请求的所有结果。这是因为某些响应可能包含数千个对象,因此默认情况下大多数响应都是分页的。
要获取用户的所有帖子,您有 3 个选项:
基于光标的分页
基于光标的分页是最有效的分页方法,应尽可能使用。游标是指随机字符串,它标记数据列表中的特定项目。除非删除此项,否则光标将始终指向列表的同一部分,但如果删除了一项,则光标将失效。因此,您的应用不应存储任何旧游标或假设它们仍然有效。
读取支持游标分页的边缘时,您将看到以下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="
}
}
To get all posts by a user you keep surfing the "next" edges (upserting new items). This is how I do it when I dump entire groups into RDBMS's for statistical analysis. Often you will see edges with nodes you have already encountered, that's why I mention to UPSERT (update if it exists otherwise insert).
基于时间的分页
时间分页用于使用指向数据列表中特定时间的 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"
}
}
要获取所有用户的帖子,您需要及时迭代。此方法将使您按顺序获得帖子,尽管可能希望它们 return 按 FaceBooks 边缘算法的顺序排列。
基于偏移的分页
当您不关心时间顺序而只想要特定数量的对象时,可以使用偏移分页 returned。仅当边缘不支持光标或基于时间的分页时才应使用此方法。
因此,您发现 Offset 最接近您想要的标准分页。然而:
并非所有 API 调用都支持基于偏移量的分页。为了获得一致的结果,我们建议您使用我们在响应中 return 的 previous/next 链接进行分页。
您可以在 FB API 文档中阅读所有这些内容。
https://developers.facebook.com/docs/graph-api/overview/
https://developers.facebook.com/docs/graph-api/using-graph-api/
最后,在做了一些研究并阅读了一些博客之后,我发现没有直接从 facebook API CAlls
一次获取所有用户供稿器 post 的方法。
要实现该功能,要么必须按照 Jeremy Thomson 的建议进行无限滚动,要么遍历不同的 facebook 数据页面,而不管 edge
支持哪种 facebook pagination
类型。就我想要一个没有用户 interference/actions 的进程而言,我肯定会选择第二个选项,即使用 while
循环遍历 facebook 数据页面。
为此,我们首先需要两个最重要的参数 (facebook access_token
+ (facebook appsecret_proof
),如下所述:
var appsecret_proof = access_token.GenerateAppSecretProof();
var fb = new FacebookClient(access_token);
Point to be remembered: facebook
access_token
is generated byHttpContext
class.
facebook API
呼叫将获得用户前 25 个馈线 post 如下:
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
调用 return 产生了一个 Json
数组,应该通过 Model View
属性对其进行水化,如下所示:
var postList = new List<FacebookPostViewModel>();
foreach (dynamic post in myFeed.data)
{
postList.Add(DynamicExtension.ToStatic<FacebookPostViewModel>(post));
}
到这里之前一切都很清楚,最重要的部分肯定是获取所有 facebook 用户 post 现在正在运行。为此,我们需要将 string
NextPageUri
设置为空,如下所示:
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));
}
}
这帮助我摆脱了面临的问题。但我还有另一项任务要处理。这是获取 posts 的速度,如果 posts 超过 30k,则需要 10 分钟,这至少对我来说并不理想。