Bing Ads API PHP报告请求无需下载

时间:2015-08-05 21:41:24

标签: php api bing bing-api

有没有办法在不下载文件的情况下从报告请求中获取数据? google adwords api允许api以制表符分隔的字符串返回报告,然后我可以自己解析报告而无需制作文件。

我目前正在使用Bing API通过CampaignPerformancReportRequest类获取广告系列效果报告。我想获取数据并将其放入我们的SQL数据库中。该文件是不必要的。现在是的,我知道一旦创建了文件,我总是可以使用php来打开文件并从中获取数据,但老实说,这很乏味,并且无缘无故地需要额外的处理能力。有人可以帮忙吗?

这是代码的副本,以防有人需要使用PHP运行的广告系列效果报告来下载报告。

<?php

// Include the Bing Ads namespaced class file available
// for download at http://go.microsoft.com/fwlink/?LinkId=322147
include '..\..\includes\bing\ReportingClasses.php';
include '..\..\includes\bing\ClientProxy.php';

// Specify the BingAds\Reporting objects that will be used.
use BingAds\Reporting\SubmitGenerateReportRequest;
use BingAds\Reporting\CampaignPerformanceReportRequest;
use BingAds\Reporting\ReportFormat;
use BingAds\Reporting\ReportAggregation;
use BingAds\Reporting\AccountThroughAdGroupReportScope;
use BingAds\Reporting\CampaignReportScope;
use BingAds\Reporting\ReportTime;
use BingAds\Reporting\ReportTimePeriod;
use BingAds\Reporting\Date;
use BingAds\Reporting\CampaignPerformanceReportFilter;
use BingAds\Reporting\DeviceTypeReportFilter;
use BingAds\Reporting\CampaignPerformanceReportColumn;
use BingAds\Reporting\PollGenerateReportRequest;
use BingAds\Reporting\ReportRequestStatusType;
// use BingAds\Reporting\CampaignPerformanceReportSort;
use BingAds\Reporting\SortOrder;

// Specify the BingAds\Proxy object that will be used.
use BingAds\Proxy\ClientProxy;

// Disable WSDL caching.

ini_set("soap.wsdl_cache_enabled", "0");
ini_set("soap.wsdl_cache_ttl", "0");

// Specify your credentials.

$UserName = "XXX";          
$Password = "XXX";          
$DeveloperToken = "XXX"; 
$AccountId = XXX;
$CampaignId = XXX;


// Reporting WSDL.

$wsdl = "https://api.bingads.microsoft.com/Api/Advertiser/Reporting/V9/ReportingService.svc?singleWsdl";


// Specify the file to download the report to. Because the file is
// compressed use the .zip file extension.

$DownloadPath = "c:\\keywordperf.zip";

// Confirm that the download folder exist; otherwise, exit.

$length = strrpos($DownloadPath, '\\');
$folder = substr($DownloadPath, 0, $length);

if (!is_dir($folder))
{
    printf("The output folder, %s, does not exist.\nEnsure that the " .
        "folder exists and try again.", $folder);
    return;
}

try
{
    $proxy = ClientProxy::ConstructWithAccountId($wsdl, $UserName, $Password, $DeveloperToken, $AccountId, null);

    // Build a keyword performance report request, including Format, ReportName, Aggregation,
    // Scope, Time, Filter, and Columns.

    $report = new CampaignPerformanceReportRequest();

    $report->Format = ReportFormat::Tsv;
    $report->ReportName = 'My Keyword Performance Report';
    $report->ReturnOnlyCompleteData = false;
    $report->Aggregation = ReportAggregation::Daily;

    $report->Scope = new AccountThroughAdGroupReportScope();
    $report->Scope->AccountIds = null;
    $report->Scope->AdGroups = null;
    $report->Scope->Campaigns = null;
    // $campaignReportScope = new CampaignReportScope();
    // $campaignReportScope->CampaignId = $CampaignId;
    // $campaignReportScope->AccountId = $AccountId;
    // $report->Scope->Campaigns[] = $campaignReportScope;

    $report->Time = new ReportTime();
    $report->Time->PredefinedTime = ReportTimePeriod::Yesterday;

    //  You may either use a custom date range or predefined time.
    //    $report->Time->CustomDateRangeStart = new Date();
    //    $report->Time->CustomDateRangeStart->Month = 2;
    //    $report->Time->CustomDateRangeStart->Day = 1;
    //    $report->Time->CustomDateRangeStart->Year = 2012;
    //    $report->Time->CustomDateRangeEnd = new Date();
    //    $report->Time->CustomDateRangeEnd->Month = 2;
    //    $report->Time->CustomDateRangeEnd->Day = 15;
    //    $report->Time->CustomDateRangeEnd->Year = 2012;

    // $report->Filter = new CampaignPerformanceReportFilter();
    // $report->Filter->DeviceType = array (
            // DeviceTypeReportFilter::Computer,
            // DeviceTypeReportFilter::SmartPhone
    // );

    $report->Columns = array (
            CampaignPerformanceReportColumn::TimePeriod,
            CampaignPerformanceReportColumn::AccountId,
            CampaignPerformanceReportColumn::CampaignName,
            CampaignPerformanceReportColumn::CampaignId,

            CampaignPerformanceReportColumn::Clicks,
            CampaignPerformanceReportColumn::Impressions,
            CampaignPerformanceReportColumn::Ctr,
            CampaignPerformanceReportColumn::AverageCpc,
            CampaignPerformanceReportColumn::Spend,
            CampaignPerformanceReportColumn::QualityScore
    );

    // You may optionally sort by any CampaignPerformanceReportColumn, and optionally
    // specify the maximum number of rows to return in the sorted report.

    // $report->Sort = array ();
    // $CampaignPerformanceReportSort = new CampaignPerformanceReportSort();
    // $CampaignPerformanceReportSort->SortColumn = CampaignPerformanceReportColumn::Clicks;
    // $CampaignPerformanceReportSort->SortOrder = SortOrder::Ascending;
    // $report->Sort[] = $CampaignPerformanceReportSort;

    $report->MaxRows = 10;

    $encodedReport = new SoapVar($report, SOAP_ENC_OBJECT, 'CampaignPerformanceReportRequest', $proxy->GetNamespace());

    // SubmitGenerateReport helper method calls the corresponding Bing Ads service operation
    // to request the report identifier. The identifier is used to check report generation status
    // before downloading the report.

    $reportRequestId = SubmitGenerateReport(
            $proxy, 
            $encodedReport
            );

    printf("Report Request ID: %s\n\n", $reportRequestId);

    $waitTime = 30 * 1; 
    $reportRequestStatus = null;

    // This sample polls every 30 seconds up to 5 minutes.
    // In production you may poll the status every 1 to 2 minutes for up to one hour.
    // If the call succeeds, stop polling. If the call or 
    // download fails, the call throws a fault.

    for ($i = 0; $i < 10; $i++)
    {
        sleep($waitTime);

        // PollGenerateReport helper method calls the corresponding Bing Ads service operation
        // to get the report request status.

        $reportRequestStatus = PollGenerateReport(
                $proxy, 
                $reportRequestId
                );

        if ($reportRequestStatus->Status == ReportRequestStatusType::Success ||
            $reportRequestStatus->Status == ReportRequestStatusType::Error)
        {
            break;
        }
    }

    if ($reportRequestStatus != null)
    {
        if ($reportRequestStatus->Status == ReportRequestStatusType::Success)
        {
            $reportDownloadUrl = $reportRequestStatus->ReportDownloadUrl;
            printf("Downloading from %s.\n\n", $reportDownloadUrl);
            DownloadFile($reportDownloadUrl, $DownloadPath);
            printf("The report was written to %s.\n", $DownloadPath);
        }
        else if ($reportRequestStatus->Status == ReportRequestStatusType::Error)
        {
            printf("The request failed. Try requesting the report " .
                    "later.\nIf the request continues to fail, contact support.\n");
        }
        else  // Pending
        {
            printf("The request is taking longer than expected.\n " .
                    "Save the report ID (%s) and try again later.\n",
                    $reportRequestId);
        }
    }

}
catch (SoapFault $e)
{
    // Output the last request/response.

    print "\nLast SOAP request/response:\n";
    print $proxy->GetWsdl() . "\n";
    print $proxy->GetService()->__getLastRequest()."\n";
    print $proxy->GetService()->__getLastResponse()."\n";

    // Reporting service operations can throw AdApiFaultDetail.
    if (isset($e->detail->AdApiFaultDetail))
    {
        // Log this fault.

        print "The operation failed with the following faults:\n";

        $errors = is_array($e->detail->AdApiFaultDetail->Errors->AdApiError)
        ? $e->detail->AdApiFaultDetail->Errors->AdApiError
        : array('AdApiError' => $e->detail->AdApiFaultDetail->Errors->AdApiError);

        // If the AdApiError array is not null, the following are examples of error codes that may be found.
        foreach ($errors as $error)
        {
            print "AdApiError\n";
            printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

            switch ($error->Code)
            {
                case 0:    // InternalError
                    break;
                case 105:  // InvalidCredentials
                    break;
                default:
                    print "Please see MSDN documentation for more details about the error code output above.\n";
                    break;
            }
        }
    }

    // Reporting service operations can throw ApiFaultDetail.
    elseif (isset($e->detail->ApiFaultDetail))
    {
        // Log this fault.

        print "The operation failed with the following faults:\n";

        // If the BatchError array is not null, the following are examples of error codes that may be found.
        if (!empty($e->detail->ApiFaultDetail->BatchErrors))
        {
            $errors = is_array($e->detail->ApiFaultDetail->BatchErrors->BatchError)
            ? $e->detail->ApiFaultDetail->BatchErrors->BatchError
            : array('BatchError' => $e->detail->ApiFaultDetail->BatchErrors->BatchError);

            foreach ($errors as $error)
            {
                printf("BatchError at Index: %d\n", $error->Index);
                printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

                switch ($error->Code)
                {
                    case 0:     // InternalError
                        break;
                    default:
                        print "Please see MSDN documentation for more details about the error code output above.\n";
                        break;
                }
            }
        }

        // If the OperationError array is not null, the following are examples of error codes that may be found.
        if (!empty($e->detail->ApiFaultDetail->OperationErrors))
        {
            $errors = is_array($e->detail->ApiFaultDetail->OperationErrors->OperationError)
            ? $e->detail->ApiFaultDetail->OperationErrors->OperationError
            : array('OperationError' => $e->detail->ApiFaultDetail->OperationErrors->OperationError);

            foreach ($errors as $error)
            {
                print "OperationError\n";
                printf("Code: %d\nError Code: %s\nMessage: %s\n", $error->Code, $error->ErrorCode, $error->Message);

                switch ($error->Code)
                {
                    case 0:     // InternalError
                        break;
                    case 106:   // UserIsNotAuthorized
                        break;
                    case 2100:  // ReportingServiceInvalidReportId
                        break;
                    default:
                        print "Please see MSDN documentation for more details about the error code output above.\n";
                        break;
                }
            }
        }
    }
}
catch (Exception $e)
{
    if ($e->getPrevious())
    {
        ; // Ignore fault exceptions that we already caught.
    }
    else
    {
        print $e->getCode()." ".$e->getMessage()."\n\n";
        print $e->getTraceAsString()."\n\n";
    }
}


// Request the report. Use the ID that the request returns to
// check for the completion of the report.

function SubmitGenerateReport($proxy, $report)
{
    // Set the request information.

    $request = new SubmitGenerateReportRequest();
    $request->ReportRequest = $report;

    return $proxy->GetService()->SubmitGenerateReport($request)->ReportRequestId;
}

// Check the status of the report request. The guidance of how often to poll
// for status is from every five to 15 minutes depending on the amount
// of data being requested. For smaller reports, you can poll every couple
// of minutes. You should stop polling and try again later if the request
// is taking longer than an hour.

function PollGenerateReport($proxy, $reportRequestId)
{
    // Set the request information.

    $request = new PollGenerateReportRequest();
    $request->ReportRequestId = $reportRequestId;

    return $proxy->GetService()->PollGenerateReport($request)->ReportRequestStatus;
}

// Using the URL that the PollGenerateReport operation returned,
// send an HTTP request to get the report and write it to the specified
// ZIP file.

function DownloadFile($reportDownloadUrl, $downloadPath)
{
    if (!$reader = fopen($reportDownloadUrl, 'rb'))
    {
        throw new Exception("Failed to open URL " . $reportDownloadUrl . ".");
    }

    if (!$writer = fopen($downloadPath, 'wb'))
    {
        fclose($reader);
        throw new Exception("Failed to create ZIP file " . $downloadPath . ".");
    }

    $bufferSize = 100 * 1024;

    while (!feof($reader))
    {
        if (false === ($buffer = fread($reader, $bufferSize)))
        {
             fclose($reader);
             fclose($writer);
             throw new Exception("Read operation from URL failed.");
        }

        if (fwrite($writer, $buffer) === false)
        {
             fclose($reader);
             fclose($writer);
             $exception = new Exception("Write operation to ZIP file failed.");
        }
    }

    fclose($reader);
    fflush($writer);
    fclose($writer);
}


?>

如果此代码可以帮助您,请投票;)

1 个答案:

答案 0 :(得分:3)

我遇到了这个寻找与Bing Ads API相关的其他内容。

您可以尝试将整个文件读入字符串(使用OS内存映射),然后从字符串中提取文件。 在类似情况下,hack为我工作了:

$data = file_get_contents($reportDownloadUrl);
$head = unpack("Vsig/vver/vflag/vmeth/vmodt/vmodd/Vcrc/Vcsize/Vsize/vnamelen/vexlen", substr($data, 0, 30));
$report = gzinflate(substr($data, 30 + $head['namelen'] + $head['exlen'], $head['csize']));

希望它有所帮助...