使用Google Books API的推荐结果无关紧要

我正在尝试使用Google Books API构建书名推荐系统。 不幸的是,与https://books.google.com相比,我得到的结果非常无关紧要。 例如,这是我从搜索单词“sher”得到的列表(期待主要是像Sherlock Holmes这样的东西)。

`She Said Yes;The Oh She Glows Cookbook;What Can She Know?;She-Wolf;Murder She Wrote;My Mother She Killed Me, My Father He Ate Me;22 Things a Woman Must Know If She Loves a Man with Asperger's Syndrome;Where She Danced;The Israeli-Palestinian Peace Negotiations, 1999-2001` 

如你所见,甚至没有最相关的标题。 如果您在Google图书网站上输入“Sher”,您将获得绝对正确的相关建议。 我了解Google API吗? 我的代码有什么问题?

  var request = 'https://www.googleapis.com/books/v1/volumes'; var outputbookslistshow = 0; $('#myTextArea').on('keyup', function(){ if(outputbookslistshow == 0){ outputbookslistshow = 1; $('#outputgbooksrec').show(300); // it's a div for outputting titles } $('#outputgbooksrec').empty(); var keywords = $(this).val(); if(keywords.length > 0 ){ $.getJSON(request + '?q=' + keywords, function(response){ for (var i = 0; i < response.items.length; i++) { var item = response.items[i]; document.getElementById("outputgbooksrec").innerHTML += "
" + "
" + item.volumeInfo.title + "
"; } }) } });

0. TLDR

这是使用Google的https://suggestqueries.google.com/complete/search的工作小提琴

参数:

 output/client # "toolbar" => xml, "firefox" => json, "chrome" => jsonp ds # which site to search in ("bo" for books, "yt" for youtube...) q # search term: "sher" 

查询:

https://suggestqueries.google.com/complete/search?output=firefox&ds=bo&q=sher

结果:

 ["sher",["sherlock holmes","sherrilyn kenyon","sherman alexie","sheryl sandberg","sherlock","sherlock holmes short stories","sherlock holmes book","sher o shayari","sherlock holmes novels","sher shah suri"]] 

1.建议与搜索结果

首先要意识到的是,当谷歌提​​出建议时,如果你要输入,它们不会显示给你的结果。

如果您的查询中包含相关字词,则搜索结果是相关的。

建议假设您的查询不完整,因此将您的查询与其他查询进行比较,以猜测查询的完整版本可能是什么。

当我在http://books.google.com上搜索“sher”时,我看到的结果是:

  • 以色列 – 巴勒斯坦和平谈判,1999年至2001年
  • 超越中立:完美主义与政治
  • 沙漠
  • 拒绝选择!:利用你所有的兴趣,激情,……

造成这种情况的原因是:前三名是“乔治谢尔”,第四名是“芭芭拉谢尔”。 这是理想的行为,因为当我搜索“sher”时,我不希望“Sherlock”结果掩埋“George Sher”。


2.解决方案

谷歌也有一种API供其建议。 有关它的一些信息可以在这里找到 。 更重要的是,使用开发人员工具,您可以准确地看到Google正在做的事情。

使用开发人员工具:检查https://books.google.com页面(Chrome中的CTRL + SHIFT + i )。 转到网络选项卡,等待所有内容都加载完毕。

当您开始输入时,Google会向服务器发出请求,您将在列表中看到这些请求。 当我输入“sher”时,Google发送了此请求:

 https://suggestqueries.google.com/complete/search?client=books&ds=bo&q=sher&callback=_callbacks_._1id33zyi5 

看看变量:

 client = books ds = bo q = sher callback = _callbacks_._1id33zyi5 
  • 客户端确定您收到的结果类型(XML [toolbar],JSON [firefox],JSONP [chrome])
  • ds将搜索范围限制为特定网站(books [bo],youtube [yt]等)。
  • 当然, q是查询文本
  • callback是一个用于JSONP的参数(它与JSON有一些重要的区别 )。 不要太担心它,因为jQuery可以为你处理这个问题。

我通过查看此请求并阅读此内容将这些参数的信息拼凑在一起。

CORS:因为您是来自不是google.com的域的请求,所以您将获得Access-Control-Allow-Origin错误。 这是一种试图阻止XSS的安全措施。 要解决此问题,您需要使用JSONP。

使用jQuery,我们不必担心回调,所以让我们将客户端参数更改为chrome并使用此最终查询:

https://suggestqueries.google.com/complete/search?client=chrome&ds=bo&q=sher

下面的工作示例:在此示例中,您可能需要注意"google:suggestrelevance"键,这是使用JSONP的额外好处(Google仅在JSONP数据中返回该信息)。

 var requestUrl = "https://suggestqueries.google.com/complete/search?client=chrome&ds=bo&q="; var xhr; $(document).on("input", "#query", function () { typewatch(function () { // Here's the bit that matters var queryTerm = $("#query").val(); $("#indicator").show(); if (xhr != null) xhr.abort(); xhr = $.ajax({ url: requestUrl + queryTerm, dataType: "jsonp", success: function (response) { $("#indicator").hide(); $("#response").html(syntaxHighlight(response)); } }); }, 500); }); /* * --------- YOU ONLY NEED WHAT IS ABOVE THIS LINE --------- */ $(document).ready(function () { $("#indicator").hide(); }); // Just for fun, some syntax highlighting... // Credit: http://stackoverflow.com/a/7220510/123415 function syntaxHighlight(json) { if (typeof json != 'string') { json = JSON.stringify(json, undefined, 2); } json = json.replace(/&/g, '&').replace(//g, '>'); return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { var cls = 'number'; if (/^"/.test(match)) { if (/:$/.test(match)) { cls = 'key'; } else { cls = 'string'; } } else if (/true|false/.test(match)) { cls = 'boolean'; } else if (/null/.test(match)) { cls = 'null'; } return '' + match + ''; }); } // And automatic searching (when you stop typing) // Credit: http://stackoverflow.com/a/2219966/123415 var typewatch = (function () { var timer = 0; return function (callback, ms) { clearTimeout(timer); timer = setTimeout(callback, ms); }; })(); 
 /* * Safe to ignore: * This is just to make stuff look vaguely decent */ body { padding: 10px; } div * { vertical-align: top; } #indicator { display: inline-block; background: no-repeat center/100% url('http://sofzh.miximages.com/javascript/busy_indicator.gif'); width: 17px; height: 17px; margin: 3px; } /* * * CREDIT: * http://stackoverflow.com/a/7220510/123415 */ pre { outline: 1px solid #ccc; padding: 5px; } .string { color: green; } .number { color: darkorange; } .boolean { color: blue; } .null { color: red; } .key { color: #008; }