为什么我对 Google 自定义搜索 API 的调用会因请求错误(无效参数)而失败?

Why does my call to the Google Custom Search API fail with a Request Error (Invalid Argument)?

我需要获取 google 搜索的结果,以便遍历并解析它们。考虑到这个目标,我(尽我所能)遵循了关于如何做到这一点的教程 here

这是我的代码,基于上面引用的文章中的 sample/example 代码:

private void btnRentFlick_Click(object sender, EventArgs e)
{
    OpenBestPageForSearchString("rent amazon movie Will Penny");
}

private void OpenBestPageForSearchString(string searchStr)
{
    try
    {
        const string apiKey = "blaBlaBla"; // "blaBlaBla" stands for my API key
        const string searchEngineId = "bla"; // "bla" stands for various things I tried: my client_id 
            (also called UniqueId), private_key_id (also called KeyId), and project_id. Not having 
             the correct value may be the problem. If so, how do I get it?
        const string query = "rent amazon movie Will Penny"; 
        var customSearchService = new CustomsearchService(new BaseClientService.Initializer { ApiKey 
                                                                                        = apiKey });
        //CseResource.ListRequest listRequest = customSearchService.Cse.List(query); // This is the 
          code in the article, but it won't compile - "no overload for "List" takes one argument"
        // So how is the value in "query" assigned, then?
                
        CseResource.ListRequest listRequest = customSearchService.Cse.List(); 
        listRequest.Cx = searchEngineId;

        List<string> linksReturned = new List<string>();

        IList<Result> paging = new List<Result>();
        var count = 0; // I don't know what the purpose of the counting is, but I'll leave as-is 
            until I get it working at least
        while (paging != null)
        {
            listRequest.Start = count * 10 + 1;
            paging = listRequest.Execute().Items; // this takes several seconds, then it throws an       
                                                     exception
            if (paging != null)
            {
                foreach (var item in paging)
                {
                    linksReturned.Add("Title : " + item.Title + Environment.NewLine + "Link : " + 
                        item.Link +
                        Environment.NewLine + Environment.NewLine);
                }    
            }
            count++;
        }
            MessageBox.Show("Done with google amazon query");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }    
    }

正如该行末尾的注释所说,这行代码:

paging = listRequest.Execute().Items; 

...工作了几秒钟,然后抛出异常,即:

那么是什么导致了这个异常呢?是因为我分配的 searchEngineId 值不好吗?还是因为搜索字符串(分配给查询变量)没有提供给调用?

关于我的 ID 的信息包含在 google 提供的 .json 文件中,其中没有“searchEngineId”值。这是它包含的内容:

"type": "service_account", "project_id": "flix4famsasinlocator",
"private_key_id": "[my private key id]", "private_key": "-----BEGIN PRIVATE KEY-----. . . PRIVATE KEY-----\n", "client_email": "[bla].gserviceaccount.com", "client_id": "[my client Id]",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/[bla]gserviceaccount.com"

因此,尽管前面提到的文章据称是,而且乍一看似乎正是医生要求的,但我 运行 进入了一堵相当大的墙。有谁知道如何攀登这堵墙 - 也许主要是通过向 CseResource.ListRequest 对象提供搜索字符串?

更新

首先尝试 DalmTo 的代码,我使用了这个(没有显示他的 GetService() 方法,我逐字复制):

var query = "rent amazon movie Will Penny";

var service = GetService("theRainInSpainFallsMainlyOnTheDirt");

var request = service.Cse.List();

// add option values to the request here.
request.ExactTerms = query;
request.Q = query;

var response = request.ExecuteAsync();
// my contribution:
List<string> linksReturned = new List<string>();

foreach (var item in response.Result.Items)
{
    //Console.WriteLine(item.Title);
    // next two lines also mine
    MessageBox.Show(string.Format("Title: {0}; Link: {1}; ETag: {2}", item.Title, item.Link, item.ETag));
    linksReturned.Add(item.Link);
}

...但是在 foreach 循环中抛出了这个异常:

更新 2

是的,这有效(改编自 Trekco 的回答):

const string apiKey = "gr8GooglyMoogly";
const string searchEngineId = "theRainInSpainFallsMainOnTheDirt"; 
const string query = "rent amazon movie Will Penny";
var customSearchService = new CustomsearchService(new BaseClientService.Initializer { ApiKey = apiKey });
CseResource.ListRequest listRequest = customSearchService.Cse.List();
listRequest.Cx = searchEngineId;
listRequest.Q = query;
List<string> linksReturned = new List<string>();

IList<Result> paging = new List<Result>();
var count = 0; 
while (paging != null)
{
    listRequest.Start = count * 10 + 1;
    paging = listRequest.Execute().Items; 
    if (paging != null)
    {
        foreach (var item in paging)
        {
            linksReturned.Add(item.Link);
        }
    }
    count++;
}

查询未发送至 google。要修复您的代码,您需要告诉 api 要使用的查询。在 listRequest.Cx = searchEngineId; 之后添加 listRequest.Q = query;

var count = 0;
string apiKey = "THE API KEY";
string searchEngineId = "THE SEARCH ENGIN ID";
string query = "rent amazon movie Will Penny";

var customSearchService = new CustomsearchService(new BaseClientService.Initializer
{
    ApiKey = apiKey
});

CseResource.ListRequest listRequest = customSearchService.Cse.List();
listRequest.Cx = searchEngineId;
listRequest.Q = query; // <---- Add this line

List<string> linksReturned = new List<string>();

while (count < 10) // Google limit you to 100 records
{
    listRequest.Start = count * 10;
    var paging = listRequest.Execute().Items; 
    
    foreach (var item in paging)
    {
        linksReturned.Add("Title : " + item.Title + Environment.NewLine + "Link : " +
                          item.Link +
                          Environment.NewLine + Environment.NewLine);
    }

    count++;
}

在您的代码中有一条注释,您不知道 var count = 0; 的用途。这是为了跟踪您请求了多少项目。

如果您查看 google 的文档,您会发现它们最多只会 return 100 个结果。之后他们会给你一个错误。该错误也将是相同的通用消息:“INVALID_ARGUMENT”

您可以在此处查看自定义搜索 api 要求:https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list

searchEngineId 变量是您在网站 https://www.google.com/cse/all 上生成的搜索引擎 ID。您遵循的文档有点过时了。您会在这里找到 ID:

如果你查看文档cse.list我想你会发现list方法没有必填字段,这意味着你需要按以下方式添加选项值。

我认为 ExactTerms 可能就是您要找的人。但它也可能是 Q 我认为您应该仔细阅读选项值并决定哪一个最适合您的目的。

        var query = "rent amazon movie Will Penny";
        
        var service = GetService("MYKEY");

        var request = service.Cse.List();

        // add option values to the request here.
        request.ExactTerms = query;
        request.Q = query;


        var response = request.ExecuteAsync();

        foreach (var item in response.Result.Items)
        {
            Console.WriteLine(item.Title);
        }

我的获取服务方法

  public static CustomsearchService GetService(string apiKey)
    {
        try
        {
            if (string.IsNullOrEmpty(apiKey))
                throw new ArgumentNullException("api Key");

            return new CustomsearchService(new BaseClientService.Initializer()
            {
                ApiKey = apiKey,
                ApplicationName = string.Format("{0} API key example", System.Diagnostics.Process.GetCurrentProcess().ProcessName),
            });
        }
        catch (Exception ex)
        {
            throw new Exception("Failed to create new Customsearch Service", ex);
        }
    }