结构化数据文件 (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
时,系统会返回一个操作对象。此操作表示创建时异步 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'] );