Facebook Graph API 分页如何工作以及如何使用它来迭代 facebook 用户提要?

Posted

技术标签:

【中文标题】Facebook Graph API 分页如何工作以及如何使用它来迭代 facebook 用户提要?【英文标题】:How does Facebook Graph API Pagination works and how to iterate facebook user feed with it? 【发布时间】:2017-05-16 01:53:50 【问题描述】:

我有一个 facebook Graph API 调用来获取 facebook 用户供稿:

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

上面返回了一段时间内的一些最新用户帖子,比如 21 或 22 个帖子,但不是用户帖子的完整列表。 我搜索了一种使用 facebook 分页遍历用户提要的方法,最终找到了适用于 facebook Offset 分页的解决方案。

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

这使我离我想要实现的目标更近了一步,但我认为这不是理想的方法,而且它也不会返回所有用户的帖子。 有什么解决方法吗?请帮忙。

P.S:我正在使用 Facebook C# SDK。

更新1: 根据杰里米的回答。似乎 facebook 光标分页是满足我要求的唯一正确选择。我想知道 C# facebook sdk 是否提供任何功能来迭代 Next Edges,以便我可以在一次调用中获取所有提要帖子,是否有任何可能的解决方案? PS:我已经多次阅读 facebook API 文档,我知道节点、边缘和字段到底是什么,唯一不幸的是 facebook 还不支持 C# SDK,我无法找到合适的文档Facebook C# SDK 也是如此。

【问题讨论】:

除非 Graph API 在最近的几个版本中发生了变化,否则它实际上不会那样工作。 Facebook 帖子处于边缘,如果您想获得用户的所有帖子,您必须保持浏览边缘(更新新项目)。你用 Offset 找到的是最接近的。您可以在 FB API 文档中阅读此内容。 【参考方案1】:

最后在做了一些研究并阅读了一些博客之后,我发现没有直接来自 facebook 的API CAlls 可以一次获取所有用户馈线帖子。 要实现该功能,要么按照 Jeremy Thomson 的建议进行无限滚动,要么遍历不同的 facebook 数据页面,无论 edge 支持哪种 facebook pagination 类型。至于我想要一个没有用户干预/操作的过程,我肯定会选择第二个选项,即使用while 循环遍历 facebook 数据页面。 为此,我们首先需要两个最重要的参数(facebook access_token + (facebook appsecret_proof),如下所述:

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

要记住的要点: facebook access_tokenHttpContext 类生成。

facebook API 调用将获得用户的前 25 个 feeder 帖子,如下所示:

dynamic myFeed = await fb.GetTaskAsync(
                    ("me/feed?fields=id,from id, name, pictureurl ,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 用户帖子。为此,我们需要将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));
                    
                

这帮助我摆脱了面临的问题。但我还有另一项任务要处理。如果帖子超过 30k,则获取帖子的速度需要 10 分钟,这至少对我来说并不理想。

【讨论】:

什么是GetNextPageQuery 看来您使用的 API 与我不同 :)【参考方案2】:

首先介绍一些术语:

nodes - 基本上是“事物”,例如用户、照片、页面、评论edges - “事物”之间的连接,例如主页的照片或照片的评论字段 - 有关这些“事物”的信息,例如某人的生日或主页的名称

当您向节点或边缘发出 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="
  

要获取用户的所有帖子,您需要继续浏览“下一个”边缘(更新插入新项目)。当我将整个组转储到 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"
  

要获取所有用户的帖子,您需要及时迭代。此方法将按顺序获取帖子,但可能希望它们按 FaceBooks 边缘算法的顺序返回。

基于偏移的分页

当您不关心年表并且只希望返回特定数量的对象时,可以使用偏移分页。仅当边缘不支持光标或基于时间的分页时才应使用此选项。

因此,您使用 Offset 找到的是最接近您想要的股票标准分页的内容。然而:

并非所有 API 调用都支持基于偏移的分页。为了获得一致的结果,我们建议您使用我们在响应中返回的上一个/下一个链接进行分页。

您可以在 FB API 文档中阅读所有这些内容。

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

【讨论】:

我已经更新了问题,请看一下,如果我能得到中肯的答案,我将不胜感激。 底层 Facebook Graph API 不支持一次调用获取所有用户帖子,因此 C# SDK 无法提供该功能。我唯一能想到的是使用 WebClient 和/或 html Agility 包并滚动到用户页面的底部并将整个页面转储出去。不理想。 我做到了,看看我下面的答案

以上是关于Facebook Graph API 分页如何工作以及如何使用它来迭代 facebook 用户提要?的主要内容,如果未能解决你的问题,请参考以下文章

Facebook Open Graph API:获取分页用户新闻提要时参数限制的奇怪行为

iOS Facebook Graph API 使用“下一个”或“上一个”Url 使用 SDK 进行分页

Facebook Graph API:工作历史

facebook javascript API 中的分页如何工作?

Facebook Graph API:用户性别

如何使用 Facebook GRAPH API 删除 Facebook 评论帖子?