Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aviso
Em 30 de outubro de 2020, as APIs de Pesquisa do Bing foram transferidas dos serviços de IA do Azure para os Serviços de Pesquisa do Bing. Esta documentação é fornecida apenas para referência. Para obter a documentação atualizada, consulte a documentação da API de pesquisa do Bing . Para obter instruções sobre como criar novos recursos do Azure para a pesquisa do Bing, consulte Criar um recurso de Pesquisa do Bing por meio dodo Azure Marketplace.
Este aplicativo de página única demonstra como recuperar, analisar e exibir os resultados da pesquisa da API de Pesquisa na Web do Bing. O tutorial usa HTML clichê e CSS e se concentra no código JavaScript. Arquivos HTML, CSS e JS estão disponíveis no github com instruções de início rápido.
Este aplicativo de exemplo pode:
- Chamar a API de Pesquisa na Web do Bing com opções de pesquisa
- Exibir resultados da Web, imagem, notícias e vídeo
- Paginar resultados
- Gerenciar chaves de assinatura
- Gerenciar erros
Para usar esse aplicativo, é necessária uma conta serviços de IA do Azure com APIs de Pesquisa do Bing.
Pré-requisitos
Aqui estão algumas coisas que você precisará para executar o aplicativo:
Uma assinatura do Azure – crie uma gratuitamente
Depois de ter sua assinatura do Azure, criar um recurso de Pesquisa do Bing no portal do Azure para obter sua chave e ponto de extremidade. Depois que a implantação for concluída, clique em Ir para o recurso.
Node.js 8 ou posterior
A primeira etapa é clonar o repositório com o código-fonte do aplicativo de exemplo.
git clone https://github.com/Azure-Samples/cognitive-services-REST-api-samples.git
Em seguida, execute npm install. Para este tutorial, Express.js é a única dependência.
cd <path-to-repo>/cognitive-services-REST-api-samples/Tutorials/bing-web-search
npm install
Componentes do aplicativo
O aplicativo de exemplo que estamos criando é composto por quatro partes:
-
bing-web-search.js- Nosso aplicativo Express.js. Ele manipula a lógica de solicitação/resposta e o roteamento. -
public/index.html- O esqueleto do nosso aplicativo; define como os dados são apresentados ao usuário. -
public/css/styles.css– Define estilos de página, como fontes, cores, tamanho do texto. -
public/js/scripts.js- Contém a lógica para fazer solicitações à API de Pesquisa na Web do Bing, gerenciar chaves de assinatura, manipular e analisar respostas e exibir resultados.
Este tutorial se concentra em scripts.js e na lógica necessária para chamar a API de Pesquisa na Web do Bing e lidar com a resposta.
Formulário HTML
O index.html inclui um formulário que permite que os usuários pesquisem e selecionem opções de pesquisa. O atributo onsubmit é acionado quando o formulário é enviado, chamando o método bingWebSearch() definido em scripts.js. São necessários três argumentos:
- Consulta de pesquisa
- Opções selecionadas
- Chave de assinatura
<form name="bing" onsubmit="return bingWebSearch(this.query.value,
bingSearchOptions(this), getSubscriptionKey())">
Opções de consulta
O formulário HTML inclui opções que são mapeadas para parâmetros de consulta na API de pesquisa web do Bing v7. Esta tabela fornece um detalhamento de como os usuários podem filtrar os resultados da pesquisa usando o aplicativo de exemplo:
| Parâmetro | Descrição |
|---|---|
query |
Um campo de texto para inserir uma cadeia de caracteres de consulta. |
where |
Um menu suspensível para selecionar o mercado (local e idioma). |
what |
Caixas de seleção para destacar tipos específicos de resultados. Promover imagens, por exemplo, aumenta a classificação de imagens nos resultados da pesquisa. |
when |
Um menu suspenso que permite que o usuário limite os resultados da pesquisa a hoje, esta semana ou este mês. |
safe |
Uma caixa de seleção para habilitar o Bing SafeSearch, que filtra o conteúdo adulto. |
count |
Campo oculto. O número de resultados da pesquisa a serem retornados em cada solicitação. Altere esse valor para exibir menos ou mais resultados por página. |
offset |
Campo oculto. O deslocamento do primeiro resultado da pesquisa na solicitação, que é usado para paginação. Ele é redefinido para 0 com cada nova solicitação. |
Observação
A API de Pesquisa na Web do Bing oferece parâmetros de consulta adicionais para ajudar a refinar os resultados da pesquisa. Este exemplo usa apenas alguns. Para obter uma lista completa dos parâmetros disponíveis, consulte referência da API de Pesquisa na Web do Bing v7.
A função bingSearchOptions() converte essas opções para corresponder ao formato exigido pela API de Pesquisa do Bing.
// Build query options from selections in the HTML form.
function bingSearchOptions(form) {
var options = [];
// Where option.
options.push("mkt=" + form.where.value);
// SafeSearch option.
options.push("SafeSearch=" + (form.safe.checked ? "strict" : "moderate"));
// Freshness option.
if (form.when.value.length) options.push("freshness=" + form.when.value);
var what = [];
for (var i = 0; i < form.what.length; i++)
if (form.what[i].checked) what.push(form.what[i].value);
// Promote option.
if (what.length) {
options.push("promote=" + what.join(","));
options.push("answerCount=9");
}
// Count option.
options.push("count=" + form.count.value);
// Offset option.
options.push("offset=" + form.offset.value);
// Hardcoded text decoration option.
options.push("textDecorations=true");
// Hardcoded text format option.
options.push("textFormat=HTML");
return options.join("&");
}
SafeSearch pode ser definido como strict, moderateou off, com moderate sendo a configuração padrão da Pesquisa na Web do Bing. Esse formulário usa uma caixa de seleção, que tem dois estados: strict ou moderate.
Se qualquer uma das caixas de seleção Promover estiverem selecionadas, o parâmetro answerCount será adicionado à consulta.
answerCount é necessário ao usar o parâmetro promote. Neste snippet, o valor é definido como 9 para retornar todos os tipos de resultados disponíveis.
Observação
Promover um tipo de resultado não garantir que ele será incluído nos resultados da pesquisa. Em vez disso, a promoção aumenta a classificação desses tipos de resultados em relação à sua classificação habitual. Para limitar pesquisas a determinados tipos de resultados, use o parâmetro de consulta responseFilter ou chame um ponto de extremidade mais específico, como Pesquisa de Imagem do Bing ou Pesquisa de Notícias do Bing.
Os parâmetros de consulta textDecoration e textFormat são codificados no script e fazem com que o termo de pesquisa seja em negrito nos resultados da pesquisa. Esses parâmetros não são necessários.
Gerenciar chaves de assinatura
Para evitar a codificação da chave de assinatura da API de Pesquisa do Bing, este aplicativo de exemplo usa o armazenamento persistente de um navegador para armazenar a chave de assinatura. Se nenhuma chave de assinatura for armazenada, o usuário será solicitado a inserir uma. Se a chave de assinatura for rejeitada pela API, o usuário será solicitado a inserir novamente uma chave de assinatura.
A função getSubscriptionKey() usa as funções storeValue e retrieveValue para armazenar e recuperar a chave de assinatura de um usuário. Essas funções usam o objeto localStorage, se houver suporte, ou cookies.
// Cookie names for stored data.
API_KEY_COOKIE = "bing-search-api-key";
CLIENT_ID_COOKIE = "bing-search-client-id";
BING_ENDPOINT = "https://api.cognitive.microsoft.com/bing/v7.0/search";
// See source code for storeValue and retrieveValue definitions.
// Get stored subscription key, or prompt if it isn't found.
function getSubscriptionKey() {
var key = retrieveValue(API_KEY_COOKIE);
while (key.length !== 32) {
key = prompt("Enter Bing Search API subscription key:", "").trim();
}
// Always set the cookie in order to update the expiration date.
storeValue(API_KEY_COOKIE, key);
return key;
}
Como vimos anteriormente, quando o formulário é enviado, onsubmit é acionado, chamando bingWebSearch. Essa função inicializa e envia a solicitação.
getSubscriptionKey é chamado em cada envio para autenticar a solicitação.
Chamar Pesquisa do Bing na Internet
Considerando a consulta, a cadeia de caracteres de opções e a chave de assinatura, a função BingWebSearch cria um objeto XMLHttpRequest para chamar o endpoint de Pesquisa na Web do Bing.
// Perform a search constructed from the query, options, and subscription key.
function bingWebSearch(query, options, key) {
window.scrollTo(0, 0);
if (!query.trim().length) return false;
showDiv("noresults", "Working. Please wait.");
hideDivs("pole", "mainline", "sidebar", "_json", "_http", "paging1", "paging2", "error");
var request = new XMLHttpRequest();
var queryurl = BING_ENDPOINT + "?q=" + encodeURIComponent(query) + "&" + options;
// Initialize the request.
try {
request.open("GET", queryurl);
}
catch (e) {
renderErrorMessage("Bad request (invalid URL)\n" + queryurl);
return false;
}
// Add request headers.
request.setRequestHeader("Ocp-Apim-Subscription-Key", key);
request.setRequestHeader("Accept", "application/json");
var clientid = retrieveValue(CLIENT_ID_COOKIE);
if (clientid) request.setRequestHeader("X-MSEdge-ClientID", clientid);
// Event handler for successful response.
request.addEventListener("load", handleBingResponse);
// Event handler for errors.
request.addEventListener("error", function() {
renderErrorMessage("Error completing request");
});
// Event handler for an aborted request.
request.addEventListener("abort", function() {
renderErrorMessage("Request aborted");
});
// Send the request.
request.send();
return false;
}
Após uma solicitação bem-sucedida, o manipulador de eventos load é acionado e chama a função handleBingResponse.
handleBingResponse analisa o objeto de resultado, exibe os resultados e contém a lógica de erro para solicitações com falha.
function handleBingResponse() {
hideDivs("noresults");
var json = this.responseText.trim();
var jsobj = {};
// Try to parse results object.
try {
if (json.length) jsobj = JSON.parse(json);
} catch(e) {
renderErrorMessage("Invalid JSON response");
return;
}
// Show raw JSON and the HTTP request.
showDiv("json", preFormat(JSON.stringify(jsobj, null, 2)));
showDiv("http", preFormat("GET " + this.responseURL + "\n\nStatus: " + this.status + " " +
this.statusText + "\n" + this.getAllResponseHeaders()));
// If the HTTP response is 200 OK, try to render the results.
if (this.status === 200) {
var clientid = this.getResponseHeader("X-MSEdge-ClientID");
if (clientid) retrieveValue(CLIENT_ID_COOKIE, clientid);
if (json.length) {
if (jsobj._type === "SearchResponse" && "rankingResponse" in jsobj) {
renderSearchResults(jsobj);
} else {
renderErrorMessage("No search results in JSON response");
}
} else {
renderErrorMessage("Empty response (are you sending too many requests too quickly?)");
}
}
// Any other HTTP response is considered an error.
else {
// 401 is unauthorized; force a re-prompt for the user's subscription
// key on the next request.
if (this.status === 401) invalidateSubscriptionKey();
// Some error responses don't have a top-level errors object, if absent
// create one.
var errors = jsobj.errors || [jsobj];
var errmsg = [];
// Display the HTTP status code.
errmsg.push("HTTP Status " + this.status + " " + this.statusText + "\n");
// Add all fields from all error responses.
for (var i = 0; i < errors.length; i++) {
if (i) errmsg.push("\n");
for (var k in errors[i]) errmsg.push(k + ": " + errors[i][k]);
}
// Display Bing Trace ID if it isn't blocked by CORS.
var traceid = this.getResponseHeader("BingAPIs-TraceId");
if (traceid) errmsg.push("\nTrace ID " + traceid);
// Display the error message.
renderErrorMessage(errmsg.join("\n"));
}
}
Importante
Uma solicitação HTTP bem-sucedida não significa que a própria pesquisa foi bem-sucedida. Se ocorrer um erro na operação de pesquisa, a API de Pesquisa na Web do Bing retornará um código de status HTTP não 200 e incluirá informações de erro na resposta JSON. Se a solicitação estiver sujeita a um limite de taxa, a API retornará uma resposta vazia.
Grande parte do código em ambas as funções anteriores é dedicada ao tratamento de erros. Erros podem ocorrer nos seguintes estágios:
| Etapa | Possíveis erros | Gerenciado por |
|---|---|---|
| Compilando o objeto de solicitação | URL inválida | bloco try / catch |
| Fazendo a solicitação | Erros de rede, conexões anuladas | manipuladores de eventos error e abort |
| Executando a pesquisa | Solicitação inválida, JSON inválido, limites de taxa | Testes no manipulador de eventos load |
Os erros são tratados chamando renderErrorMessage(). Se a resposta for aprovada em todos os testes de erro, renderSearchResults() será chamado para exibir os resultados da pesquisa.
Exibir resultados da pesquisa
Existem requisitos para o uso e a exibição de resultados retornados pela API de Pesquisa na Web do Bing. Como uma resposta pode incluir vários tipos de resultados, não é suficiente percorrer a coleção de WebPages de nível superior. Em vez disso, o aplicativo de exemplo usa RankingResponse para ordenar os resultados conforme as especificações.
Observação
Se você quiser apenas um único tipo de resultado, use o parâmetro de consulta responseFilter ou considere usar um dos outros pontos de extremidade da Pesquisa do Bing, como a Pesquisa de Imagem do Bing.
Cada resposta tem um objeto RankingResponse que pode incluir até três coleções: pole, mainlinee sidebar.
pole, se presente, é o resultado da pesquisa mais relevante e deve ser exibido com destaque.
mainline contém a maioria dos resultados da pesquisa e é exibido imediatamente após pole.
sidebar inclui resultados de pesquisa auxiliares. Se possível, esses resultados devem ser exibidos na barra lateral. Se os limites de tela tornarem uma barra lateral impraticável, esses resultados deverão aparecer após os resultados do mainline.
Cada RankingResponse inclui uma matriz RankingItem que especifica como os resultados devem ser ordenados. Nosso aplicativo de exemplo usa os parâmetros answerType e resultIndex para identificar o resultado.
Observação
Há maneiras adicionais de identificar e classificar resultados. Para obter mais informações, consulte Usando a classificação para exibir resultados.
Vamos dar uma olhada no código:
// Render the search results from the JSON response.
function renderSearchResults(results) {
// If spelling was corrected, update the search field.
if (results.queryContext.alteredQuery)
document.forms.bing.query.value = results.queryContext.alteredQuery;
// Add Prev / Next links with result count.
var pagingLinks = renderPagingLinks(results);
showDiv("paging1", pagingLinks);
showDiv("paging2", pagingLinks);
// Render the results for each section.
for (section in {pole: 0, mainline: 0, sidebar: 0}) {
if (results.rankingResponse[section])
showDiv(section, renderResultsItems(section, results));
}
}
A função renderResultsItems() percorre os itens de cada coleção RankingResponse, mapeia cada ranking para um resultado de pesquisa utilizando os valores answerType e resultIndex, e chama a função de renderização apropriada para gerar o HTML. Se resultIndex não for especificado para um item, renderResultsItems() itera todos os resultados desse tipo e chama a função de renderização para cada item. O HTML resultante é inserido no elemento de <div> apropriado no index.html.
// Render search results from the RankingResponse object per rank response and
// use and display requirements.
function renderResultsItems(section, results) {
var items = results.rankingResponse[section].items;
var html = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
// Collection name has lowercase first letter while answerType has uppercase
// e.g. `WebPages` RankingResult type is in the `webPages` top-level collection.
var type = item.answerType[0].toLowerCase() + item.answerType.slice(1);
if (type in results && type in searchItemRenderers) {
var render = searchItemRenderers[type];
// This ranking item refers to ONE result of the specified type.
if ("resultIndex" in item) {
html.push(render(results[type].value[item.resultIndex], section));
// This ranking item refers to ALL results of the specified type.
} else {
var len = results[type].value.length;
for (var j = 0; j < len; j++) {
html.push(render(results[type].value[j], section, j, len));
}
}
}
}
return html.join("\n\n");
}
Examinar funções do renderizador
Em nosso aplicativo de exemplo, o objeto searchItemRenderers inclui funções que geram HTML para cada tipo de resultado de pesquisa.
// Render functions for each result type.
searchItemRenderers = {
webPages: function(item) { ... },
news: function(item) { ... },
images: function(item, section, index, count) { ... },
videos: function(item, section, index, count) { ... },
relatedSearches: function(item, section, index, count) { ... }
}
Importante
O aplicativo de exemplo tem renderizadores para páginas da Web, notícias, imagens, vídeos e pesquisas relacionadas. Seu aplicativo precisará de renderizadores para qualquer tipo de resultados que possa receber, o que pode incluir cálculos, sugestões ortográficas, entidades, fusos horários e definições.
Algumas das funções de renderização aceitam apenas o parâmetro item. Outros aceitam parâmetros adicionais, que podem ser usados para renderizar itens de forma diferente com base no contexto. Um renderizador que não usa essas informações não precisa aceitar esses parâmetros.
Os argumentos de contexto são:
| Parâmetro | Descrição |
|---|---|
section |
A seção resultados (pole, mainlineou sidebar) na qual o item é exibido. |
indexcount |
Disponível quando o item RankingResponse especifica que todos os resultados em uma determinada coleção devem ser exibidos; undefined caso contrário. O índice do item dentro de sua coleção e o número total de itens nessa coleção. Você pode usar essas informações para numerar os resultados, para gerar HTML diferente para o primeiro ou o último resultado e assim por diante. |
No aplicativo de exemplo, os renderizadores images e relatedSearches usam os argumentos de contexto para personalizar o HTML gerado. Vamos dar uma olhada mais de perto no renderizador de images:
searchItemRenderers = {
// Render image result with thumbnail.
images: function(item, section, index, count) {
var height = 60;
var width = Math.round(height * item.thumbnail.width / item.thumbnail.height);
var html = [];
if (section === "sidebar") {
if (index) html.push("<br>");
} else {
if (!index) html.push("<p class='images'>");
}
html.push("<a href='" + item.hostPageUrl + "'>");
var title = escape(item.name) + "\n" + getHost(item.hostPageDisplayUrl);
html.push("<img src='"+ item.thumbnailUrl + "&h=" + height + "&w=" + width +
"' height=" + height + " width=" + width + " title='" + title + "' alt='" + title + "'>");
html.push("</a>");
return html.join("");
},
// Other renderers are omitted from this sample...
}
O renderizador de imagem:
- Calcula o tamanho da miniatura da imagem (a largura varia, enquanto a altura é fixada em 60 pixels).
- Insere o HTML que precede o resultado da imagem com base no contexto.
- Cria a marca html
<a>que é vinculada à página que contém a imagem. - Cria a tag HTML
<img>para exibir a miniatura da imagem.
O renderizador de imagem usa as variáveis section e index para exibir resultados de forma diferente, dependendo de onde eles aparecem. Uma quebra de linha (tag <br>) é inserida entre os resultados de imagem na barra lateral, para que a barra lateral exiba uma coluna de imagens. Em outras seções, o primeiro resultado da imagem (index === 0) é precedido por uma tag <p>.
O tamanho da miniatura é utilizado na marca <img> e nos campos h e w na URL da miniatura. Os atributos title e alt (uma descrição textual da imagem) são construídos a partir do nome da imagem e do nome do host na URL.
Veja um exemplo de como as imagens são exibidas no aplicativo de exemplo:
Persistir a identificação do Cliente
As respostas das APIs de pesquisa do Bing podem incluir um cabeçalho X-MSEdge-ClientID que deve ser enviado de volta à API com cada solicitação sucessiva. Se mais de uma das APIs de Pesquisa do Bing for usada pelo aplicativo, verifique se a mesma ID do cliente é enviada com cada solicitação entre serviços.
Fornecer o cabeçalho X-MSEdge-ClientID permite que as APIs do Bing associem as pesquisas de um usuário. Primeiro, ele permite que o mecanismo de pesquisa do Bing aplique contexto passado a pesquisas para encontrar resultados que satisfaçam melhor a solicitação. Se um usuário tiver pesquisado anteriormente termos relacionados à vela, por exemplo, uma pesquisa posterior por "nós" talvez retorne preferencialmente informações sobre nós usados na navegação. Em segundo lugar, o Bing pode selecionar aleatoriamente os usuários para experimentar novos recursos antes que eles sejam amplamente disponibilizados. Fornecer a mesma ID do cliente com cada solicitação garante que os usuários escolhidos para ver um recurso sempre o vejam. Sem a ID do cliente, o usuário pode ver um recurso aparecer e desaparecer, aparentemente aleatoriamente, nos resultados da pesquisa.
As políticas de segurança do navegador, como CORS (Compartilhamento de Recursos entre Origens), podem impedir que o aplicativo de exemplo acesse o cabeçalho X-MSEdge-ClientID. Essa limitação ocorre quando a resposta de pesquisa tem uma origem diferente da página que a solicitou. Em um ambiente de produção, você deve abordar essa política hospedando um script do lado do servidor que faz a chamada à API no mesmo domínio que a página da Web. Como o script tem a mesma origem que a página da Web, o cabeçalho X-MSEdge-ClientID está disponível para JavaScript.
Observação
Em um aplicativo Web de produção, você deve realizar a solicitação do lado do servidor mesmo assim. Caso contrário, sua chave de assinatura da API de Pesquisa do Bing deve ser incluída na página da Web, onde ela está disponível para qualquer pessoa que visualize o código-fonte. Você é cobrado por todo o uso em sua chave de assinatura de API, até mesmo solicitações feitas por partes não autorizadas, portanto, é importante não expor sua chave.
Para fins de desenvolvimento, você pode fazer uma solicitação por meio de um proxy CORS. A resposta desse tipo de proxy tem um cabeçalho Access-Control-Expose-Headers que filtra cabeçalhos de resposta e os disponibiliza para JavaScript.
É fácil instalar um proxy CORS para permitir que nosso aplicativo de exemplo acesse o cabeçalho da ID do cliente. Execute este comando:
npm install -g cors-proxy-server
Em seguida, altere o endpoint da Pesquisa Web do Bing em script.js para:
http://localhost:9090/https://api.cognitive.microsoft.com/bing/v7.0/search
Inicie o proxy CORS com este comando:
cors-proxy-server
Deixe a janela de comando aberta enquanto você usa o aplicativo de exemplo; fechar a janela interrompe o proxy. Na seção Cabeçalhos HTTP expansíveis abaixo dos resultados da pesquisa, o cabeçalho X-MSEdge-ClientID deve estar visível. Verifique se é o mesmo para cada solicitação.