结构化数据文件 (SDF) 是采用特殊格式的逗号分隔值 (CSV) 文件,用于批量检索和更新 Display & Video 360 资源的相关数据。通过 Display & Video 360 API,您可以生成和下载自定义 SDF,从而检索经过整理的 Display & Video 360 资源上经过过滤的数据。
本指南介绍了如何创建 SDF 下载操作、跟踪该操作,以及如何下载生成的 SDF。
如需关于 SDF 格式和版本控制的信息,请参阅 SDF 参考文档。
创建任务
SDF 由称为 sdfdownloadtask
的异步操作生成。创建此任务时,您可以定义与所需 SDF 相关的参数。这是通过 sdfdownloadtasks.create
方法完成的。以下小节介绍了您可以设置的参数。
指定版本
结构化数据文件格式会独立于 Display & Video 360 API 定期更新,并会定期弃用新版本和旧版本。因此,始终建议用户使用最新版本的 SDF。
您可以使用请求正文中的 version
字段设置所需 SDF 的 SDF 版本。如果此政策未设置或设为 SDF_VERSION_UNSPECIFIED
,任务将使用广告主或合作伙伴资源的默认 SDF 版本(用作 SDF 内容上下文)。
设定背景
您可以生成包含任何可用资源相关数据的 SDF,但任何单个 SDF 都只能在单个合作伙伴或广告主环境中返回内容。此上下文由 partnerId
或 advertiserId
字段在请求正文中定义。这两个字段中必须设置且只能设置一个。
生成的 SDF 中只会包含给定上下文中的资源。如果您尝试按不归指定合作伙伴或广告主所有的资源进行过滤,结果将不包含该资源及其下的内容。如果仅按这些未包含的资源进行过滤,则生成的文件将为空。如果尝试按给定上下文之外的资源进行过滤,系统不会返回错误,因此请务必检查您的上下文是否正确。
选择合适的过滤条件
除了上面设置的上下文之外,您还可以指定要生成的文件类型以及要包含的特定资源或资源系列,从而进一步过滤所生成结构化数据文件的范围。
sdfdownloadtask
有三个可用的过滤器,每个过滤器可满足特定的规范类型。您只能为一个 sdfdownloadtask
分配一个。
ParentEntityFilter
ParentEntityFilter
是可用过滤器中范围最广的。
使用 fileType
字段,您可以列出希望在任务中生成的所有需要的文件类型。这是必填字段,如果留空或设置为 FILE_TYPE_UNSPECIFIED
,您的 sdfdownloadtask
将错误地完成。
使用 filterType
和 filterIds
字段,您可以进一步优化结果。filterType
指定要过滤的资源类型,filterIds
按资源的唯一 ID 识别这些资源。生成的 SDF 将包含由 fileType
标识的资源,这些资源可以是通过 filterType
和 filterIds
标识的资源的资源或子项。
IdFilter
IdFilter
过滤您的请求,以便仅包含识别出的资源。
在 IdFilter
中,每种 SDF 类型(不包括广告资源来源)都有一个对应的字段。其中每个字段都是一个唯一 ID 列表,用于标识您希望包含在生成的 SDF 中的特定资源。提供的 ID 必须在上下文集中,但它们不必直接相关。您无需请求特定的广告系列即可请求其中包含的订单项,反之亦然。仅生成与 IdFilter
中标识的资源对应的文件类型。
InventorySourceFilter
InventorySourceFilter
仅允许过滤和下载包含广告资源来源资源的 SDF。您只能使用该过滤条件来获取广告资源来源资源的相关信息。
InventorySourceFilter
具有单个 inventorySourceIds
字段,您可在其中标识要添加到 SDF 中的广告资源来源资源的唯一 ID。如果提供给 inventorySourceIds
的列表为空,则设置的上下文下的所有商品目录来源都将包含在生成的 SDF 中。
发出请求
知道所需 SDF 的参数后,您可以构建请求并创建 sdfdownloadtask
。
以下示例展示了如何使用 ParentEntityFilter
创建 sdfdownloadtask
:
Java
// Create the filter structure ParentEntityFilter parentEntityFilter = new ParentEntityFilter(); parentEntityFilter.setFileType(sdf-file-type-list); parentEntityFilter.setFilterType(sdfFilterType); parentEntityFilter.setFilterIds(filter-id-list); // Configure the sdfdownloadtasks.create request Sdfdownloadtasks.Create request = service .sdfdownloadtasks() .create( new CreateSdfDownloadTaskRequest() .setVersion(sdfVersion) .setAdvertiserId(advertiserId) .setParentEntityFilter(parentEntityFilter) ); // Create the sdfdownloadtask Operation operationResponse = request.execute(); System.out.printf("Operation %s was created.\n", operationResponse.getName());
Python
# Configure the sdfdownloadtasks.create request createSdfDownloadTaskRequest = { 'version': sdf-version, 'advertiserId': advertiser-id, 'parentEntityFilter': { 'fileType': sdf-file-type-list, 'filterType': sdf-filter-type, 'filterIds': filter-id-list } } # Create the sdfdownloadtask operation = service.sdfdownloadtasks().create( body=createSdfDownloadTaskRequest).execute(); print("Operation %s was created." % operation["name"])
PHP
// Create the sdfdownloadtasks.create request structure $createSdfDownloadTaskRequest = new Google_Service_DisplayVideo_CreateSdfDownloadTaskRequest(); $createSdfDownloadTaskRequest->setAdvertiserId(advertiser-id); $createSdfDownloadTaskRequest->setVersion(sdf-version); // Create and set the parent entity filter $parentEntityFilter = new Google_Service_DisplayVideo_ParentEntityFilter(); $parentEntityFilter->setFileType(sdf-file-type-list); $parentEntityFilter->setFilterType(sdf-filter-type); if (!empty(filter-id-list)) { $parentEntityFilter->setFilterIds(filter-id-list); } $createSdfDownloadTaskRequest->setParentEntityFilter($parentEntityFilter); // Call the API, creating the SDF Download Task. $operation = $this->service->sdfdownloadtasks->create( $createSdfDownloadTaskRequest ); printf('Operation %s was created.\n', $operation->getName());
检查您的请求并获取下载路径
当您创建 sdfdownloadtask
时,会返回一个 operation 对象。此操作表示异步 SDF 生成操作在创建时的状态。您可以使用 sdfdownloadtasks.operations.get
方法检查操作,确认其是否已完成并可供下载,或是否已抛出错误。
完成后,返回的操作将具有非 null done
字段。完成的操作将包含 response
或 error
字段。如果存在,则 error
字段将包含一个 Status
对象,该对象包含错误代码和提供所发生错误的详细信息消息。如果存在 response
字段,则该字段将包含一个具有 resourceName
值的对象,用于标识生成的可供下载的文件。
以下示例展示了如何使用指数退避算法检查您的请求:
Java
String operationName = operationResponse.getName(); // Configure the Operations.get request Sdfdownloadtasks.Operations.Get operationRequest = service .sdfdownloadtasks() .operations() .get(operationName); // Configure exponential backoff for checking the status of our operation ExponentialBackOff backOff = new ExponentialBackOff.Builder() .setInitialIntervalMillis(5000) // setting initial interval to five seconds .setMaxIntervalMillis(300000) // setting max interval to five minutes .setMaxElapsedTimeMillis(18000000) // setting max elapsed time to five hours .build(); while (operationResponse.getDone() == null) { long backoffMillis = backOff.nextBackOffMillis(); if (backoffMillis == ExponentialBackOff.STOP) { System.out.printf("The operation has taken more than five hours to complete.\n"); return; } Thread.sleep(backoffMillis); // Get current status of operation operationResponse = operationRequest.execute(); } // Check if the operation finished with an error and return if (operationResponse.getError() != null) { System.out.printf("The operation finished in error with code %s: %s\n", operationResponse.getError().getCode(), operationResponse.getError() .getMessage()); return; } System.out.printf( "The operation completed successfully. Resource %s was created.\n", operationResponse.getResponse().get("resourceName").toString());
Python
# The following values control retry behavior while # the report is processing. # Minimum amount of time between polling requests. Defaults to 5 seconds. min_retry_interval = 5 # Maximum amount of time between polling requests. Defaults to 5 minutes. max_retry_interval = 5 * 60 # Maximum amount of time to spend polling. Defaults to 5 hours. max_retry_elapsed_time = 5 * 60 * 60 # Configure the Operations.get request get_request = service.sdfdownloadtasks().operations().get( name=operation["name"] ) sleep = 0 start_time = time.time() while True: # Get current status of operation operation = get_request.execute() if "done" in operation: if "error" in operation: print("The operation finished in error with code %s: %s" % ( operation["error"]["code"], operation["error"]["message"])) else: print("The operation completed successfully. Resource %s was created." % operation["response"]["resourceName"]) break elif time.time() - start_time > max_retry_elapsed_time: print("Generation deadline exceeded.") sleep = next_sleep_interval(sleep) print("Operation still running, sleeping for %d seconds." % sleep) time.sleep(sleep) def next_sleep_interval(previous_sleep_interval): """Calculates the next sleep interval based on the previous.""" min_interval = previous_sleep_interval or min_retry_interval max_interval = previous_sleep_interval * 3 or min_retry_interval return min(max_retry_interval, random.randint(min_interval, max_interval))
PHP
// The following values control retry behavior // while the task is processing. // Minimum amount of time between polling requests. Defaults to 5 seconds. $minRetryInterval = 5; // Maximum amount of time between polling requests. Defaults to 5 minutes. $maxRetryInterval = 300; // Maximum amount of time to spend polling. Defaults to 5 hours. $maxRetryElapsedTime = 18000; $operationName = $operation->getName(); $sleepInterval = 0; $startTime = time(); while (!$operation->getDone()) { if ($sleepInterval != 0) { printf( 'The operation is still running, sleeping for %d seconds\n', $sleepInterval ); } // Sleep before retrieving the SDF Download Task again. sleep($sleepInterval); // Call the API, retrieving the SDF Download Task. $operation = $this->service->sdfdownloadtasks_operations->get( $operation->getName() ); // If the operation has exceeded the set deadline, throw an exception. if (time() - $startTime > $maxRetryElapsedTime) { printf('SDF download task processing deadline exceeded\n'); throw new Exception( 'Long-running operation processing deadline exceeded' ); } // Generate the next sleep interval using exponential backoff logic. $sleepInterval = min( $maxRetryInterval, rand( max($minRetryInterval, $previousSleepInterval), max($minRetryInterval, $previousSleepInterval * 3) ) ); } // If the operation finished with an error, throw an exception. if($operation->getError() !== null) { $error = $operation->getError(); printf( 'The operation finished in error with code %s: %s\n', $error->getCode(), $error->getMessage() ); throw new Exception($error->getMessage()); } // Print successfully generated resource. $response = $operation->getResponse(); printf( 'The operation completed successfully. Resource %s was ' . 'created. Ready to download.\n', $response['resourceName'] );