【问题标题】:FB Ads API (#17) User request limit reachedFB Ads API (#17) 达到用户请求限制
【发布时间】:2019-12-28 22:56:04
【问题描述】:

我正在使用 Facebook 广告 api 来获取帐户广告系列数据。我在这里做的是获取所有广告系列的列表并为每个广告系列执行 forloop 获取广告系列统计数据

$campaignSets = $account->getCampaigns(array(
      CampaignFields::ID,
      CampaignFields::NAME
));

foreach ($campaignSets as $campaign) {
      $campaign = new Campaign($campaign->id);
      $fields = array(
        InsightsFields::CAMPAIGN_NAME,
        InsightsFields::IMPRESSIONS,
        InsightsFields::UNIQUE_CLICKS,
        InsightsFields::REACH,
        InsightsFields::SPEND,
        InsightsFields::TOTAL_ACTIONS,
        InsightsFields::TOTAL_ACTION_VALUE
      );
      $params = array(
        'date_preset' => InsightsPresets::TODAY
      );
                $insights = $campaign->getInsights($fields, $params);
}

执行上述代码时,我收到错误,因为 (#17) 达到用户请求限制。

谁能帮我解决这种错误?

谢谢, 罗纳克·沙阿

【问题讨论】:

  • 你可以通过限制 api 调用的数量来解决它,并等待一段时间直到限制错误消息消失。
  • 是的!但我认为无论如何都必须在一次调用中获取所有数据,或者就像以任何方式下载 xls 或 csv 中的统计数据或报告一样,所以我可以处理报告并在数据库中添加数据
  • 可以实现调用之间的延迟,例如
  • 坏主意!!在通话之间添加延迟
  • 为什么这是个坏主意?我已经用过很多次了。查看我的答案以获得更具体的解决方案。

标签: php facebook facebook-ads-api


【解决方案1】:

您应该考虑针对广告帐户生成一份报告,该报告会返回您所有广告系列的见解,这应该会显着减少所需的请求数量。

Cursor::setDefaultUseImplicitFetch(true);

$account = new AdAccount($account_id);
$fields = array(
  InsightsFields::CAMPAIGN_NAME,
  InsightsFields::CAMPAIGN_ID,
  InsightsFields::IMPRESSIONS,
  InsightsFields::UNIQUE_CLICKS,
  InsightsFields::REACH,
  InsightsFields::SPEND,
  InsightsFields::TOTAL_ACTIONS,
  InsightsFields::TOTAL_ACTION_VALUE,
);
$params = array(
  'date_preset' => InsightsPresets::TODAY,
  'level' => 'ad',
  'limit' => 1000,
);

$insights = $account->getInsights($fields, $params);
foreach($insights as $i) {
  echo $i->campaign_id.PHP_EOL;
}

【讨论】:

  • 嘿,非常感谢,是的,这就是我想要的 +1 投票,但这里有一个问题,我无法获得活动名称
  • 广告系列名称将变为空白您知道吗?
  • 已更新以包含请求字段的正确方法。你一直是对的,因为 v2.5 发生了变化。
  • 嗨,Paul,感谢您回复我,我刚刚编辑了您的 answer.getInsights 函数接受第一个参数作为 $fields 数组
  • @PaulBain 你能在 python 中建议相同的代码吗?面临同样的问题,但在 Python 中编写脚本。
【解决方案2】:

如果您遇到 API 限制,您唯一的选择是减少调用。您可以通过延迟 API 调用轻松做到这一点。我假设您已经在使用 Cron 作业,因此请实施一个计数器来存储您请求数据的最后一个活动。当 Cron Job 再次运行时,请求下一个 1-x 活动数据的数据(您必须测试每个 Cron Job 调用可能有多少个)并再次存储最后一个。

此外,您应该批量处理 API 调用 - 它不会避免限制,但会快很多。与批处理中最慢的 API 调用一样快。

【讨论】:

  • 如果我有超过 100 个广告系列说我获得了前 10 个广告系列的数据,然后它停止并开始抛出错误。Facebook 块调用 30 分钟,我的要求是每小时获取所有广告系列数据,并且插入数据库。
  • 好吧,这很奇怪。你确定只有 10 个 api 调用达到 api 限制,还是“getInsights”函数中发生了其他事情?我有时一次最多可以调用 50 个 API,这不是问题。
  • 如果您在游标中使用隐式提取,例如Cursor::setDefaultUseImplicitFetch(true),您实际上在循环期间自动进行了许多调用,这就是为什么我们默认没有将其设置为 true,因为您永远不知道作为开发人员发出了多少请求。
【解决方案3】:

将此添加到您的代码中,您将永远不必担心 FB 的速率限制/达到用户限制。 当你接近极限时,你的脚本会自动休眠,然后在冷却后从它离开的地方继续。享受:)

import logging
import requests as rq

#Function to find the string between two strings or characters
def find_between( s, first, last ):
    try:
        start = s.index( first ) + len( first )
        end = s.index( last, start )
        return s[start:end]
    except ValueError:
        return ""

#Function to check how close you are to the FB Rate Limit
def check_limit():
    check=rq.get('https://graph.facebook.com/v3.3/act_'+account_number+'/insights?access_token='+my_access_token)
    call=float(find_between(check.headers['x-business-use-case-usage'],'call_count":','}'))
    cpu=float(find_between(check.headers['x-business-use-case-usage'],'total_cputime":','}'))
    total=float(find_between(check.headers['x-business-use-case-usage'],'total_time":',','))
    usage=max(call,cpu,total)
    return usage

#Check if you reached 75% of the limit, if yes then back-off for 5 minutes (put this chunk in your loop, every 200-500 iterations)
if (check_limit()>75):
    print('75% Rate Limit Reached. Cooling Time 5 Minutes.')
    logging.debug('75% Rate Limit Reached. Cooling Time 5 Minutes.')
    time.sleep(300)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2018-05-10
    • 2012-01-31
    • 2018-05-29
    • 1970-01-01
    • 2018-06-27
    • 2013-08-16
    相关资源
    最近更新 更多