Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Warnung
Am 30. Oktober 2020 wurden die Bing Search-APIs von Azure AI-Diensten zu Bing Search Services verschoben. Diese Dokumentation wird nur zur Referenz bereitgestellt. Eine aktualisierte Dokumentation finden Sie in der Dokumentation zu den Bing-Suche-APIs. Anweisungen zum Erstellen neuer Azure-Ressourcen für die Bing-Suche finden Sie unter Erstellen einer Ressource für die Bing-Suche über Azure Marketplace.
Mit der Bing-Bildsuche-API können Sie das Web nach qualitativ hochwertigen, relevanten Bildern durchsuchen. Verwenden Sie dieses Lernprogramm, um eine einzelseitige Webanwendung zu erstellen, die Suchabfragen an die API senden und die Ergebnisse auf der Webseite anzeigen kann. Dieses Lernprogramm ähnelt dem entsprechenden Lernprogramm für Bing Web Search.
Die Lernprogramm-App veranschaulicht Folgendes:
- Ausführen eines Bing Image Search-API-Aufrufs in JavaScript
- Verbessern von Suchergebnissen mithilfe von Suchoptionen
- Anzeigen und Durchblättern von Suchergebnissen
- Anfordern und Verarbeiten eines API-Abonnementschlüssels und der Bing-Client-ID.
Voraussetzungen
- Die neueste Version von Node.js.
- Das Express.js Framework für Node.js. Installationsanweisungen für den Quellcode sind in der GitHub-Beispiel-Infodatei verfügbar.
Verwalten und Speichern von Benutzerabonnementschlüsseln
Diese Anwendung verwendet den persistenten Speicher von Webbrowsern zum Speichern von API-Abonnementschlüsseln. Wenn kein Schlüssel gespeichert ist, fordert die Webseite den Benutzer zur Eingabe seines Schlüssels auf und speichert ihn zur späteren Verwendung. Wenn der Schlüssel später von der API abgelehnt wird, wird er von der App aus dem Speicher entfernt. In diesem Beispiel wird der globale Endpunkt verwendet. Sie können auch den benutzerdefinierten Unterdomänen- Endpunkt verwenden, der im Azure-Portal für Ihre Ressource angezeigt wird.
Definieren Sie storeValue
- und retrieveValue
-Funktionen, um entweder das localStorage
-Objekt (sofern der Browser es unterstützt) oder ein Cookie zu verwenden.
// Cookie names for data being stored
API_KEY_COOKIE = "bing-search-api-key";
CLIENT_ID_COOKIE = "bing-search-client-id";
// The Bing Image Search API endpoint
BING_ENDPOINT = "https://api.cognitive.microsoft.com/bing/v7.0/images/search";
try { //Try to use localStorage first
localStorage.getItem;
window.retrieveValue = function (name) {
return localStorage.getItem(name) || "";
}
window.storeValue = function(name, value) {
localStorage.setItem(name, value);
}
} catch (e) {
//If the browser doesn't support localStorage, try a cookie
window.retrieveValue = function (name) {
var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++) {
var keyvalue = cookies[i].split("=");
if (keyvalue[0].trim() === name) return keyvalue[1];
}
return "";
}
window.storeValue = function (name, value) {
var expiry = new Date();
expiry.setFullYear(expiry.getFullYear() + 1);
document.cookie = name + "=" + value.trim() + "; expires=" + expiry.toUTCString();
}
}
Die getSubscriptionKey()
-Funktion versucht, einen zuvor gespeicherten Schlüssel mithilfe von retrieveValue
abzurufen. Wenn ein Schlüssel nicht gefunden wird, fordert er den Benutzer zur Eingabe seines Schlüssels auf, und speichert ihn mit storeValue
.
// Get the stored API subscription key, or prompt if it's not 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;
}
Das HTML-<form>
-Tag onsubmit
ruft die bingWebSearch
-Funktion auf, um Suchergebnisse zurückzugeben.
bingWebSearch
verwendet getSubscriptionKey
, um jede Abfrage zu authentifizieren. Wie in der vorherigen Definition gezeigt, fordert getSubscriptionKey
den Benutzer zur Eingabe des Schlüssels auf, wenn der Schlüssel nicht eingegeben wurde. Der Schlüssel wird dann zur fortgesetzten Verwendung durch die Anwendung gespeichert.
<form name="bing" onsubmit="this.offset.value = 0; return bingWebSearch(this.query.value,
bingSearchOptions(this), getSubscriptionKey())">
Senden von Suchanforderungen
Diese Anwendung verwendet ein HTML-<form>
, um anfänglich Benutzersuchanfragen zu senden, wobei das Attribut onsubmit
verwendet wird, um newBingImageSearch()
aufzurufen.
<form name="bing" onsubmit="return newBingImageSearch(this)">
Standardmäßig gibt der onsubmit
-Handler false
zurück, wobei das Formular nicht übermittelt wird.
Auswählen von Suchoptionen
Die Bing Image Search-API bietet mehrere Filterabfrageparameter, um Suchergebnisse einzugrenzen und zu filtern. Das HTML-Formular in dieser Anwendung verwendet und zeigt die folgenden Parameteroptionen an:
Auswahlmöglichkeit | BESCHREIBUNG |
---|---|
where |
Ein Dropdownmenü zum Auswählen des Marktes (Standort und Sprache), das für die Suche verwendet wird. |
query |
Das Textfeld, in das die Suchbegriffe eingegeben werden sollen. |
aspect |
Optionsfelder zum Auswählen der Proportionen der gefundenen Bilder: ungefähr quadratisch, breit oder hoch. |
color |
|
when |
Dropdownmenü zum optionalen Einschränken der Suche auf den letzten Tag, die letzte Woche oder den letzten Monat. |
safe |
Ein Kontrollkästchen, das angibt, ob das SafeSearch-Feature von Bing verwendet werden soll, um "erwachsene" Ergebnisse herauszufiltern. |
count |
Ausgeblendetes Feld. Die Anzahl der Suchergebnisse, die für jede Anforderung zurückgegeben werden sollen. Ändern, um weniger oder mehr Ergebnisse pro Seite anzuzeigen. |
offset |
Ausgeblendetes Feld. Der Offset des ersten Suchergebnisses in der Anfrage wird zur Seitennummerierung verwendet. Sie wird bei einer neuen Anfrage auf 0 zurückgesetzt. |
nextoffset |
Ausgeblendetes Feld. Beim Empfang eines Suchergebnisses wird dieses Feld auf den Wert des nextOffset in der Antwort festgelegt. Die Verwendung dieses Felds verhindert überlappende Ergebnisse auf aufeinander folgenden Seiten. |
stack |
Ausgeblendetes Feld. Eine JSON-codierte Liste der Offsets der vorherigen Seiten der Suchergebnisse, um zurück zu vorherigen Seiten zu navigieren. |
Die bingSearchOptions()
-Funktion formatiert diese Optionen in eine partielle Abfragezeichenfolge, die in den API-Anforderungen der App verwendet werden kann.
// Build query options from the HTML form
function bingSearchOptions(form) {
var options = [];
options.push("mkt=" + form.where.value);
options.push("SafeSearch=" + (form.safe.checked ? "strict" : "off"));
if (form.when.value.length) options.push("freshness=" + form.when.value);
var aspect = "all";
for (var i = 0; i < form.aspect.length; i++) {
if (form.aspect[i].checked) {
aspect = form.aspect[i].value;
break;
}
}
options.push("aspect=" + aspect);
if (form.color.value) options.push("color=" + form.color.value);
options.push("count=" + form.count.value);
options.push("offset=" + form.offset.value);
return options.join("&");
}
Durchführen der Anforderung
Mithilfe der Suchabfrage, der Optionszeichenfolge und des API-Schlüssels verwendet die BingImageSearch()
-Funktion ein XMLHttpRequest-Objekt, um die Anforderung an den Bing Image Search-Endpunkt zu senden.
// perform a search given query, options string, and API key
function bingImageSearch(query, options, key) {
// scroll to top of window
window.scrollTo(0, 0);
if (!query.trim().length) return false; // empty query, do nothing
showDiv("noresults", "Working. Please wait.");
hideDivs("results", "related", "_json", "_http", "paging1", "paging2", "error");
var request = new XMLHttpRequest();
var queryurl = BING_ENDPOINT + "?q=" + encodeURIComponent(query) + "&" + options;
// open 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 erorrs
request.addEventListener("error", function() {
renderErrorMessage("Error completing request");
});
// event handler for aborted request
request.addEventListener("abort", function() {
renderErrorMessage("Request aborted");
});
// send the request
request.send();
return false;
}
Nach erfolgreichem Abschluss der HTTP-Anforderung ruft JavaScript den "load"-Ereignishandler handleBingResponse()
auf, um eine erfolgreiche HTTP GET-Anforderung zu verarbeiten.
// handle Bing search request results
function handleBingResponse() {
hideDivs("noresults");
var json = this.responseText.trim();
var jsobj = {};
// try to parse JSON results
try {
if (json.length) jsobj = JSON.parse(json);
} catch(e) {
renderErrorMessage("Invalid JSON response");
}
// show raw JSON and 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 HTTP response is 200 OK, try to render search 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 === "Images") {
if (jsobj.nextOffset) document.forms.bing.nextoffset.value = jsobj.nextOffset;
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 an error
else {
// 401 is unauthorized; force re-prompt for API key for next request
if (this.status === 401) invalidateSubscriptionKey();
// some error responses don't have a top-level errors object, so gin one up
var errors = jsobj.errors || [jsobj];
var errmsg = [];
// display 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]);
}
// also display Bing Trace ID if it isn't blocked by CORS
var traceid = this.getResponseHeader("BingAPIs-TraceId");
if (traceid) errmsg.push("\nTrace ID " + traceid);
// and display the error message
renderErrorMessage(errmsg.join("\n"));
}
}
Wichtig
Erfolgreiche HTTP-Anforderungen enthalten möglicherweise fehlerhafte Suchinformationen. Wenn während des Suchvorgangs ein Fehler auftritt, gibt die Bing Image Search-API einen NICHT-200 HTTP-Statuscode und Fehlerinformationen in der JSON-Antwort zurück. Außerdem, wenn die Anforderung ratenbegrenzt war, gibt die API eine leere Antwort zurück.
Anzeigen der Suchergebnisse
Suchergebnisse werden von der renderSearchResults()
-Funktion angezeigt, die den vom Bing Image Search-Dienst zurückgegebenen JSON-Code verwendet und eine entsprechende Rendererfunktion für alle zurückgegebenen Bilder und verwandten Suchvorgänge aufruft.
function renderSearchResults(results) {
// add Prev / Next links with result count
var pagingLinks = renderPagingLinks(results);
showDiv("paging1", pagingLinks);
showDiv("paging2", pagingLinks);
showDiv("results", renderImageResults(results.value));
if (results.relatedSearches)
showDiv("sidebar", renderRelatedItems(results.relatedSearches));
}
Die Bildsuchergebnisse sind im obersten value
-Objekt innerhalb der JSON-Antwort enthalten. Diese werden an renderImageResults()
übergeben, der die Ergebnisse durchläuft und jedes Element in HTML konvertiert.
function renderImageResults(items) {
var len = items.length;
var html = [];
if (!len) {
showDiv("noresults", "No results.");
hideDivs("paging1", "paging2");
return "";
}
for (var i = 0; i < len; i++) {
html.push(searchItemRenderers.images(items[i], i, len));
}
return html.join("\n\n");
}
Die Bing Image Search-API kann vier Arten von Suchvorschlägen zurückgeben, um die Suchfunktionen der Benutzer zu unterstützen, die jeweils in einem eigenen Objekt der obersten Ebene enthalten sind:
Vorschlag | BESCHREIBUNG |
---|---|
pivotSuggestions |
Abfragen, die ein Pivotwort in der ursprünglichen Suche durch eine andere ersetzen. Wenn Sie beispielsweise nach "rote Blumen" suchen, kann ein Pivotwort "rot" sein, und ein Pivotvorschlag könnte "gelbe Blumen" sein. |
queryExpansions |
Abfragen, die die ursprüngliche Suche einschränken, indem weitere Ausdrücke hinzugefügt werden. Wenn Sie beispielsweise nach "Microsoft Surface" suchen, kann eine Abfrageerweiterung "Microsoft Surface Pro" sein. |
relatedSearches |
Abfragen, die auch von anderen Benutzern eingegeben wurden, die die ursprüngliche Suche eingegeben haben. Wenn Sie z. B. nach "Mount Rainier" suchen, könnte eine verwandte Suche "Mt. Rainier" sein. St. Helens." |
similarTerms |
Abfragen, die der ursprünglichen Suche ähnlich sind. Wenn Sie beispielsweise nach "Kätzchen" suchen, könnte ein ähnlicher Begriff "süß" sein. |
Diese Anwendung rendert nur die relatedItems
Vorschläge und platziert die resultierenden Links in der Randleiste der Seite.
Rendern von Suchergebnissen
In dieser Anwendung enthält das searchItemRenderers
-Objekt Rendererfunktionen, die HTML für jede Art von Suchergebnis generieren.
searchItemRenderers = {
images: function(item, index, count) { ... },
relatedSearches: function(item) { ... }
}
Diese Rendererfunktionen akzeptieren die folgenden Parameter:
Parameter | BESCHREIBUNG |
---|---|
item |
Das JavaScript-Objekt, das die Eigenschaften des Elements enthält, z. B. seine URL und seine Beschreibung. |
index |
Der Index des Ergebniselements innerhalb seiner Sammlung. |
count |
Die Anzahl der Elemente in der Auflistung des Suchergebniselements. |
Die Parameter index
und count
werden verwendet, um Ergebnisse zu nummerieren, HTML für Sammlungen zu generieren und den Inhalt zu organisieren. Insbesondere weist es darauf hin:
- Berechnet die Miniaturansichtsgröße des Bilds (breite variiert mit mindestens 120 Pixeln, während die Höhe bei 90 Pixeln festgelegt ist).
- Erstellt das HTML-
<img>
-Tag, um die Miniaturansicht des Bilds anzuzeigen. - Erstellt die HTML-
<a>
-Tags, die mit dem Bild und der Seite verknüpft sind, die sie enthält. - Erstellt die Beschreibung, die Informationen über das Bild und die Website anzeigt, auf der es sich befindet.
images: function (item, index, count) {
var height = 120;
var width = Math.max(Math.round(height * item.thumbnail.width / item.thumbnail.height), 120);
var html = [];
if (index === 0) html.push("<p class='images'>");
var title = escape(item.name) + "\n" + getHost(item.hostPageDisplayUrl);
html.push("<p class='images' style='max-width: " + width + "px'>");
html.push("<img src='"+ item.thumbnailUrl + "&h=" + height + "&w=" + width +
"' height=" + height + " width=" + width + "'>");
html.push("<br>");
html.push("<nobr><a href='" + item.contentUrl + "'>Image</a> - ");
html.push("<a href='" + item.hostPageUrl + "'>Page</a></nobr><br>");
html.push(title.replace("\n", " (").replace(/([a-z0-9])\.([a-z0-9])/g, "$1.<wbr>$2") + ")</p>");
return html.join("");
}, // relatedSearches renderer omitted
Die height
und width
des Miniaturbilds werden sowohl im <img>
-Tag als auch in den Feldern h
und w
in der URL der Miniaturansicht verwendet. Dadurch kann Bing eine Miniaturansicht genau dieser Größe zurückgeben.
Beibehalten der Client-ID
Antworten von den Bing-Such-APIs können einen X-MSEdge-ClientID
Header enthalten, der mit aufeinander folgenden Anforderungen an die API zurückgesendet werden soll. Wenn mehrere Bing Search-APIs verwendet werden, sollte nach Möglichkeit dieselbe Client-ID mit allen verwendet werden.
Wenn Sie den X-MSEdge-ClientID
-Header bereitstellen, können die Bing-APIs alle Suchvorgänge eines Benutzers zuordnen, was nützlich ist.
Erstens ermöglicht es der Bing-Suchmaschine, den früheren Kontext auf Suchvorgänge anzuwenden, um Ergebnisse zu finden, die den Benutzer besser erfüllen. Wenn ein Benutzer zuvor nach Begriffen im Zusammenhang mit Segeln gesucht hat, z. B. könnte eine spätere Suche nach "Knoten" bevorzugt Informationen zu Knoten zurückgeben, die beim Segeln verwendet werden.
Zweitens kann Bing zufällig benutzer auswählen, um neue Features zu erleben, bevor sie allgemein verfügbar gemacht werden. Wenn Sie die gleiche Client-ID für jede Anforderung bereitstellen, wird sichergestellt, dass Benutzer, die ausgewählt wurden, ein Feature immer sehen. Ohne die Client-ID wird dem Benutzer möglicherweise ein Feature angezeigt und verschwindet scheinbar zufällig in den Suchergebnissen.
Browsersicherheitsrichtlinien (CORS) verhindern möglicherweise, dass der X-MSEdge-ClientID
-Header für JavaScript verfügbar ist. Diese Einschränkung tritt auf, wenn die Suchantwort einen anderen Ursprung von der Seite hat, die sie angefordert hat. In einer Produktionsumgebung sollten Sie diese Richtlinie adressieren, indem Sie ein serverseitiges Skript hosten, das den API-Aufruf in derselben Domäne wie die Webseite ausführt. Da das Skript denselben Ursprung wie die Webseite hat, ist der X-MSEdge-ClientID
Header dann für JavaScript verfügbar.
Hinweis
In einer Produktionswebanwendung sollten Sie die serverseitige Anforderung trotzdem ausführen. Andernfalls muss Ihr Bing Search-API-Schlüssel auf der Webseite enthalten sein, wo er für alle Personen verfügbar ist, die die Quelle anzeigen. Sie werden für alle Nutzungen unter Ihrem API-Abonnementschlüssel in Rechnung gestellt, auch Anfragen von nicht autorisierten Parteien, daher ist es wichtig, Ihren Schlüssel nicht verfügbar zu machen.
Für Entwicklungszwecke können Sie die Bing Web Search-API-Anforderung über einen CORS-Proxy stellen. Die Antwort eines solchen Proxys verfügt über einen Access-Control-Expose-Headers
Header, der Antwortheader zulässt und sie javaScript zur Verfügung stellt.
Es ist einfach, einen CORS-Proxy zu installieren, damit unsere Lernprogramm-App auf den Client-ID-Header zugreifen kann. Zuerst, wenn du ihn noch nicht hast, Node.jsinstalliere. Geben Sie dann den folgenden Befehl in einem Befehlsfenster aus:
npm install -g cors-proxy-server
Ändern Sie als Nächstes den Bing Web Search-Endpunkt in der HTML-Datei in:
http://localhost:9090/https://api.cognitive.microsoft.com/bing/v7.0/search
Starten Sie schließlich den CORS-Proxy mit dem folgenden Befehl:
cors-proxy-server
Lassen Sie das Befehlsfenster geöffnet, während Sie die Lernprogramm-App verwenden. Durch schließen des Fensters wird der Proxy beendet. Im Abschnitt "erweiterbare HTTP-Header" unter den Suchergebnissen können Sie nun den X-MSEdge-ClientID
-Header (unter anderem) sehen und überprüfen, ob es für jede Anforderung identisch ist.