【问题标题】:Google Custom Search JSON API Constantly Refreshing when called谷歌自定义搜索 JSON API 调用时不断刷新
【发布时间】:2020-05-12 05:37:04
【问题描述】:

由于某种原因,当我使用下面的代码在我设置了谷歌自定义搜索引擎的网站上搜索术语时,它会无限刷新,我相信代码中有一些我无法捕捉到的错误。我从另一个位于 here 的 stackoverflow 答案中找到了代码,我在这里要做的是获取从每个搜索查询返回的 JSON 数据,并将其显示为类似于普通谷歌搜索结果的设计。

Search.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <form action="results.html" id="cse-search-box">
        <div>
            <input class="" name="q" type="text"> 
            <input class="" type="submit">
        </div>
    </form>
</body>
</html>

Results.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>JSON Custom Search API</title>

    <style type="text/css">
        body{
            width: 100%;
        }
        .gs-image{
            max-width: 100px;
        }
    </style>
</head>
<body>
    <h2 style="font-weight: bold; ">Search Results:</h2>
    <div class="gsc-result-info" id="resInfo-0"></div>
    <hr/>
    <div id="googleContent"></div>

    <script>
    //Handler for response from google.
    function hndlr(response) {
        if (response.items == null) {
            //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
            //So if we get to the invalid one, send them back a page.
            window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
            return;
        }
        //Search results load time
        document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
        //Clear the div first, CMS is inserting a space for some reason.
        document.getElementById("googleContent").innerHTML = "";
        //Loop through each item in search results
        for (var i = 0; i < response.items.length; i++) {
            var item = response.items[i];
            var content = "";

            content += "<div class='gs-webResult gs-result'>" +
            "<table class='gsc-table-result'><tbody><tr>";
            //Thumbnail image
            // if (item.pagemap.cse_thumbnail != null)
            //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
            // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
            //Link
            content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
            //File format for PDF, etc.
            if (item.fileFormat != null)
                content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
            //description text and URL text.
            content += item.htmlSnippet.replace('<br>','') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl +"</div>" +
            "<br/></td></tr></tbody></table></div>";
            document.getElementById("googleContent").innerHTML += content;
        }
        //Page Controls
        var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
        var currentPage = Math.floor(start / 10 + 1);
        var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
        //Page change controls, 10 max.
        for (var x = 1; x <= totalPages && x<=10; x++) {
            pageControls += "<span class='gsc-cursor-page";
            if (x === currentPage)
                pageControls += "gsc-cursor-current-page";
            var pageLinkStart = x * 10 - 9;
            pageControls+="'><a href='results.html?start="+pageLinkStart+"&q="+query+"'>"+x+"</a>&nbsp;&nbsp;</span>";
        }
        pageControls += "</div></div></div>";
        document.getElementById("googleContent").innerHTML += pageControls;
    }

    //Get search text from query string.a
    var query = document.URL.substr(document.URL.indexOf("q=") + 2);
    var start = document.URL.substr(document.URL.indexOf("start=") + 6, 2);
    if (start === "1&" || document.URL.indexOf("start=") === -1)
        start = 1;

    //Load the script src dynamically to load script with query to call.
    //DOM: Create the script element
    var jsElm = document.createElement("script");
    //Set the type attribute
    jsElm.type = "application/javascript";
    //Make the script element load file
    jsElm.src = "https://www.googleapis.com/customsearch/v1?key=yourAPIkeyHERE&cx=yourSEARCHengineIDhere&start="+start+"&q=" +query +"&callback=hndlr";
    //Finally insert the element to the body element in order to load the script
    document.body.appendChild(jsElm);
</script>
</body>
</html>

【问题讨论】:

    标签: javascript html google-api google-custom-search


    【解决方案1】:

    请处理响应数据。实际上,每次响应都不会有 items 属性,因为每个搜索关键字都没有结果。那么,你需要检查的响应对象是否有items属性?

    请用我的更改替换 hndlr() 函数并运行。我希望它会正常工作。如果你有时间检查和实施,我没有处理错误的事情。

    function hndlr(response) {
            if (response.items) {
                if (response.items == null) {
                    //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
                    //So if we get to the invalid one, send them back a page.
                    window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
                    return;
                }
                //Search results load time
                document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
                //Clear the div first, CMS is inserting a space for some reason.
                document.getElementById("googleContent").innerHTML = "";
                //Loop through each item in search results
                for (var i = 0; i < response.items.length; i++) {
                    var item = response.items[i];
                    var content = "";
    
                    content += "<div class='gs-webResult gs-result'>" +
                        "<table class='gsc-table-result'><tbody><tr>";
                    //Thumbnail image
                    // if (item.pagemap.cse_thumbnail != null)
                    //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
                    // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
                    //Link
                    content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
                    //File format for PDF, etc.
                    if (item.fileFormat != null)
                        content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
                    //description text and URL text.
                    content += item.htmlSnippet.replace('<br>', '') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl + "</div>" +
                        "<br/></td></tr></tbody></table></div>";
                    document.getElementById("googleContent").innerHTML += content;
                }
                //Page Controls
                var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
                var currentPage = Math.floor(start / 10 + 1);
                var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
                //Page change controls, 10 max.
                for (var x = 1; x <= totalPages && x <= 10; x++) {
                    pageControls += "<span class='gsc-cursor-page";
                    if (x === currentPage)
                        pageControls += "gsc-cursor-current-page";
                    var pageLinkStart = x * 10 - 9;
                    pageControls += "'><a href='results.html?start=" + pageLinkStart + "&q=" + query + "'>" + x + "</a>&nbsp;&nbsp;</span>";
                }
                pageControls += "</div></div></div>";
                document.getElementById("googleContent").innerHTML += pageControls;
            }
            else {
                document.getElementById("googleContent").innerHTML = "No result found on " + query + ", try other";
            }
        }
    

    【讨论】:

    • 有什么方法可以帮助解决错误吗?
    • 根据我的代码,它适用于错误的事情,但它不是正确的方式,所以,检查是否有错误,然后响应对象返回错误属性,根据错误只是根据那个设置条件..@自行车4431。
    • 如果您需要帮助,请给我留言。所以,我可以帮你
    【解决方案2】:

    我已将您的代码尝试到我的本地环境中。我在响应谷歌搜索时收到此错误。

    hndlr 当响应为空时,此函数会一次又一次地调用页面对吗?所以由于你的API keyresponse对象返回错误,这就是页面不断刷新的原因。

    如果您提供正确的API Key,那么 google 会返回响应并且页面不会刷新,因为您对其设置了如下条件:

    response.items === null
    

    我们可以通过向其中添加一个条件来再次管理更多条件以防止递归。

    我在hndlr函数的代码中更新了一个条件:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>JSON Custom Search API</title>
    
        <style type="text/css">
            body {
                width: 100%;
            }
    
            .gs-image {
                max-width: 100px;
            }
        </style>
    </head>
    
    <body>
        <h2 style="font-weight: bold; ">Search Results:</h2>
        <div class="gsc-result-info" id="resInfo-0"></div>
        <hr />
        <div id="googleContent"></div>
    
        <script>
            //Handler for response from google.
            function hndlr(response) {
                console.log(response);
                if (response.items == null && !response.error) {
    
                    //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
                    //So if we get to the invalid one, send them back a page.
                    window.location.replace("customsearch.html?start=" + (start - 10) + "&q=" + query);
                    return;
                }
                //Search results load time
                document.getElementById("resInfo-0").innerHTML = "About " + response.searchInformation.formattedTotalResults + " results (" + response.searchInformation.formattedSearchTime + " seconds)";
                //Clear the div first, CMS is inserting a space for some reason.
                document.getElementById("googleContent").innerHTML = "";
                //Loop through each item in search results
                for (var i = 0; i < response.items.length; i++) {
                    var item = response.items[i];
                    var content = "";
    
                    content += "<div class='gs-webResult gs-result'>" +
                        "<table class='gsc-table-result'><tbody><tr>";
                    //Thumbnail image
                    // if (item.pagemap.cse_thumbnail != null)
                    //     content += "<td class='gsc-table-cell-thumbnail gsc-thumbnail'><div class='gs-image-box gs-web-image-box gs-web-image-box-portrait'><a class='gs-image' href='" + item.link + "'>" +
                    // "<img class='gs-image' class = 'gs-image-box gs-web-image-box gs-web-image-box-portrait' src='" + item.pagemap.cse_thumbnail[0].src + "'></a></td>";
                    //Link
                    content += "<td><a class='gs-title' href='" + item.link + "'>" + item.htmlTitle + "</a><br/>";
                    //File format for PDF, etc.
                    if (item.fileFormat != null)
                        content += "<div class='gs-fileFormat'><span class='gs-fileFormat'>File Format: </span><span class='gs-fileFormatType'>" + item.fileFormat + "</span></div>";
                    //description text and URL text.
                    content += item.htmlSnippet.replace('<br>', '') + "<br/><div class='gs-bidi-start-align gs-visibleUrl gs-visibleUrl-long' dir='ltr' style='word-break:break-all;'>" + item.htmlFormattedUrl + "</div>" +
                        "<br/></td></tr></tbody></table></div>";
                    document.getElementById("googleContent").innerHTML += content;
                }
                //Page Controls
                var totalPages = Math.ceil(response.searchInformation.totalResults / 10);
                var currentPage = Math.floor(start / 10 + 1);
                var pageControls = "<div class='gsc-results'><div class='gsc-cursor-box gs-bidi-start-align' dir='ltr'><div class='gsc-cursor'>";
                //Page change controls, 10 max.
                for (var x = 1; x <= totalPages && x <= 10; x++) {
                    pageControls += "<span class='gsc-cursor-page";
                    if (x === currentPage)
                        pageControls += "gsc-cursor-current-page";
                    var pageLinkStart = x * 10 - 9;
                    pageControls += "'><a href='customsearch.html?start=" + pageLinkStart + "&q=" + query + "'>" + x + "</a>&nbsp;&nbsp;</span>";
                }
                pageControls += "</div></div></div>";
                document.getElementById("googleContent").innerHTML += pageControls;
            }
    
            //Get search text from query string.a
            var query =  document.URL.substr(document.URL.indexOf("q=") + 2);
            var start = document.URL.substr(document.URL.indexOf("start=") + 6, 2);
            if (start === "1&" || document.URL.indexOf("start=") === -1)
                start = 1;
    
            //Load the script src dynamically to load script with query to call.
            //DOM: Create the script element
            var jsElm = document.createElement("script");
            //Set the type attribute
            jsElm.type = "application/javascript";
            //Make the script element load file
            jsElm.src = "https://www.googleapis.com/customsearch/v1?key=yourAPIkeyHERE&cx=yourSEARCHengineIDhere&start=" + start + "&q=" + query + "&callback=hndlr";
            //Finally insert the element to the body element in order to load the script
            document.body.appendChild(jsElm);
        </script>
    </body>
    
    </html>
    

    【讨论】:

    • 这个 API 密钥是无效的,因为在这里堆栈溢出的帖子中我添加了一个占位符,所以不是每个人都有我的 API 密钥和搜索引擎 ID。
    【解决方案3】:

    如果响应不包含项目,则处理程序将一次又一次地将您重定向到同一页面。 API 返回的任何错误都可能发生这种情况(例如错误的 API 凭据、超出配额等)。在这种情况下,以下代码将start 设置为负值(甚至设置为 NaN),从而导致无限循环。

    if (response.items == null) {
        //Sometimes the results say there are 34 results/4 pages, but when you click through to 3 then there is only 30, so page 4 is invalid now.
        //So if we get to the invalid one, send them back a page.
        window.location.replace("results.html?start=" + (start - 10) + "&q=" + query);
        return;
    }
    

    我认为在这种情况下使用 substr 从 URL 中检索这些值不是一个好主意,但您可以改用 helper

    所以你可以在你的代码中做这样的事情:

    var query = getQueryVariable('q');
    var start = getQueryVariable('start');
    if (!start || start < 1) {
      start = 1
    }
    

    当然,根据@mayur 的回答处理可能的response.error

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      相关资源
      最近更新 更多