Facebook Marketing API - 如何处理通过广告系列 ID 检索*所有*广告集的速率限制?

问题描述

我最近开始使用 Facebook Marketing API,使用适用于 Python 的 facebook_business SDK(在 Ubuntu 20.04 上运行 v3.9)。我想我大部分时间都在思考它是如何工作的,但是,对于如何处理 API 速率限制的任意方式,我仍然有点茫然。

具体来说,我试图做的是从曾经在我的广告帐户上运行的所有广告系列中检索所有广告集,无论它们的 effective_status 是否为 {{ 1}}、ACTIVEPAUSEDDELETED

因此,我为我的广告帐户提取了所有广告系列。它们存储在字典中,其中键表示 ARCHIVED,就像这样,称为 effective_status:

output

然后,我正在尝试提取广告集 ID,如下所示:

{'ACTIVE': ['******************','******************','******************'],'PAUSED': ['******************','******************'}

现在,每当我运行它时,它都会在不同的时间崩溃,并出现以下错误

import pandas as pd
import json
import re
import time
from random import *

from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.adaccount import AdAccount # account-level info
from facebook_business.adobjects.campaign import Campaign # campaign-level info
from facebook_business.adobjects.adset import AdSet # ad-set level info
from facebook_business.adobjects.ad import Ad # ad-level info

# auth init
app_id = open(APP_ID_PATH,'r').read().splitlines()[0]
app_secret = open(APP_SECRET_PATH,'r').read().splitlines()[0]
token = open(APP_ACCESS_TOKEN,'r').read().splitlines()[0]

# init the connection
FacebookAdsApi.init(app_id,app_secret,token)

campaign_types = list(output.keys())

ad_sets = {}

for status in campaign_types:
    ad_sets_for_status = []
    for campaign_id in output[status]:
        # sleep and wait for a random time
        sleepy_time = uniform(1,3)
        time.sleep(sleepy_time)
        # pull the ad_sets for this particular campaign
        campaign_ad_sets = Campaign(campaign_id).get_ad_sets()
        for entry in campaign_ad_sets:
            ad_sets_for_status.append(entry['id'])
    ad_sets[status] = ad_sets_for_status

我无法重现它崩溃的时间,但是,它肯定不需要大约 600 次调用(请参阅此处:https://stackoverflow.com/a/29690316/5080858),而且正如您所看到的,我在每个API 调用。您可能会建议我只在 AdAccount 端点上调用 FacebookRequestError: Message: Call was not successful Method: GET Path: https://graph.facebook.com/v11.0/23846914220310083/adsets Params: {'summary': 'true'} Status: 400 Response: { "error": { "message": "(#17) User request limit reached","type": "OAuthException","is_transient": true,"code": 17,"error_subcode": 2446079,"fbtrace_id": "***************" } } 方法,但是,即使在崩溃之前,这也比上述代码提取的广告集少。就我的用例而言,重要的是拉取已结束的广告和正在进行的广告,因此获取尽可能多的数据很重要。

我对此有点恼火——看到我们为这些广告的运行付费,你会认为 FB 会尽可能轻松地通过 API 检索它们的信息,而不是引入 API 速率限制类似于那些不一定拥有的有价值数据。

无论如何,我很感激任何形式的建议或见解 - 也许还有一种我没有考虑过的更好的方法来做到这一点。

非常感谢!

解决方法

'code': 17 的错误意味着您达到了调用限制,为了获得更多节点,您必须等待。

首先我会以这种方式处理错误:

from facebook_business.exceptions import FacebookRequestError

...

for status in campaign_types:
    ad_sets_for_status = []
    for campaign_id in output[status]:

        # keep trying until the request is ok
        while True:
            try:
                campaign_ad_sets = Campaign(campaign_id).get_ad_sets()
                break
            except FacebookRequestError as error:
                if error.api_error_code() in [17,80000]:
                    time.sleep(sleepy_time) # sleep for a period of time
           
        for entry in campaign_ad_sets:
            ad_sets_for_status.append(entry['id'])
    ad_sets[status] = ad_sets_for_status

此外,我还建议您从帐户中获取节点列表(通过使用 'level': node 中的 params 参数)并使用批处理调用:我可以向您保证会帮助你很多,它会减少程序运行时间。

希望对您有所帮助。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...