5

我们正在尝试使用 Webmasters API .NET 客户端库下载网站的页面数据,方法是调用WebmastersService.SearchAnalytics.Query(). 为此,我们使用批处理和发送大约。一批 600 个请求。然而,其中大多数都因错误“配额超出”而失败。每次失败的数量都不同,但只有大约 600 个中的 10 个有效(并且它们在批次中的位置会有所不同)。我们可以让它工作的唯一方法是将批量大小减少到 3,并在每次调用之间等待 1 秒。

根据开发者控制台,我们的每日配额设置为 1,000,000(我们还有 99% 剩余),我们的每个用户限制设置为 10,000 个请求/秒/用户。

我们得到的错误是:

配额超出 [403] 错误 [消息 [配额超出] 位置 [-] 原因 [配额超出] 域 [usageLimits]]

是否有另一个配额被强制执行?“域[使用限制]”是什么意思 - 是我们查询页面数据的站点的域,还是我们的用户帐户?

如果我们分别运行每个请求,我们仍然会遇到问题,除非我们在每次调用之间等待 1 秒。由于网站的数量和页面的数量,我们需要为此下载数据并不是一个真正的选择。

我发现这篇文章指出,仅仅因为最大批处理大小为 1000 并不意味着您调用的 Google 服务支持这些大小的批处理。但我真的很想弄清楚配额限制到底是什么(因为它们与开发者控制台的数据无关)以及如何避免错误。

更新 1

这是一些示例代码。它专门编写只是为了证明问题,所以无需评论它的质量;o)

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using Google.Apis.Webmasters.v3;
using Google.Apis.Webmasters.v3.Data;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program().Run().Wait();
        }

        private async Task Run()
        {
            List<string> pageUrls = new List<string>();
            // Add your page urls to the list here

            await GetPageData("<your app name>", "2015-06-15", "2015-07-05", "web", "DESKTOP", "<your domain name>", pageUrls);
        }

        public static async Task<WebmastersService> GetService(string appName)
        {
            //if (_service != null)
            //    return _service;
            //TODO: - look at analytics code to see how to store JSON and refresh token and check runs on another PC
            UserCredential credential;
            using (var stream = new FileStream("c:\\temp\\WMT.json", FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { Google.Apis.Webmasters.v3.WebmastersService.Scope.Webmasters },
                    "user", CancellationToken.None, new FileDataStore("WebmastersService"));
            }

            // Create the service.
            WebmastersService service = new WebmastersService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = appName,
            });

            //_service = service;
            return service;

        }

        private static async Task<bool> GetPageData(string appName, string fromDate, string toDate, string searchType, string device, string siteUrl, List<string> pageUrls)
        {
            // Get the service from the initial method
            bool ret = false;

            WebmastersService service = await GetService(appName);
            Google.Apis.Requests.BatchRequest b = new Google.Apis.Requests.BatchRequest(service);

            try
            {
                foreach (string pageUrl in pageUrls)
                {
                    SearchAnalyticsQueryRequest qry = new SearchAnalyticsQueryRequest();
                    qry.StartDate = fromDate;
                    qry.EndDate = toDate;
                    qry.SearchType = searchType;
                    qry.RowLimit = 5000;
                    qry.Dimensions = new List<string>() { "query" };
                    qry.DimensionFilterGroups = new List<ApiDimensionFilterGroup>();
                    ApiDimensionFilterGroup filterGroup = new ApiDimensionFilterGroup();
                    ApiDimensionFilter filter = new ApiDimensionFilter();
                    filter.Dimension = "device";
                    filter.Expression = device;
                    filter.Operator__ = "equals";

                    ApiDimensionFilter filter2 = new ApiDimensionFilter();
                    filter2.Dimension = "page";
                    filter2.Expression = pageUrl;
                    filter2.Operator__ = "equals";

                    filterGroup.Filters = new List<ApiDimensionFilter>();
                    filterGroup.Filters.Add(filter);
                    filterGroup.Filters.Add(filter2);
                    qry.DimensionFilterGroups.Add(filterGroup);

                    var req = service.Searchanalytics.Query(qry, siteUrl);
                    b.Queue<SearchAnalyticsQueryResponse>(req, (response, error, i, message) =>
                    {
                        if (error == null)
                        {
                            // Process the results
                            ret = true;
                        }
                        else
                        {
                            Console.WriteLine(error.Message);
                        }

                    });
                    await b.ExecuteAsync();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception occurred getting page  stats : " + ex.Message);
                ret = false;
            }

            return ret;
        }        
    }
}

将其粘贴到新控制台应用程序的 program.cs 中,并通过 nuget 添加 Google.Apis.Webmasters.v3。它会在 c:\temp 中查找 wmt.json 文件,但会调整身份验证代码以适合您的设置。如果我在列表中添加超过 5 个页面 url,pageUrls那么我会得到 Quota Exceeded 异常。

4

1 回答 1

4

我发现规定的配额似乎并不是真正的配额。我不得不放慢我的请求速度以避免同样的问题(1/秒),即使我总是处于或低于规定的速率限制(20/秒)。此外,它声称它在文档中给出了 rateLimitExceeded 错误,因为速度太快了,但实际上它返回了一个 quotaExceeded 错误。这可能与 Google 如何随时间平均请求速率有关(因为我们提出的一些请求是同时进行的,即使长期平均值设计为等于或低于 20/秒),但我不能确定.

于 2016-03-06T00:36:52.333 回答