使用 C# 生成控制台应用搜索客户端
警告
2020 年 10 月 30 日,必应搜索 API 从 Azure AI 服务迁移到必应搜索服务。 本文档仅供参考。 有关更新的文档,请参阅必应搜索 API 文档。 关于为必应搜索创建新的 Azure 资源的说明,请参阅通过 Azure 市场创建必应搜索资源。
本教程介绍如何生成一个简单的 .NET Core 控制台应用,以允许用户查询必应 Web 搜索 API 并显示排名结果。
本教程介绍如何:
- 对必应 Web 搜索 API 进行简单查询
- 按排名顺序显示查询结果
先决条件
若要跟随本教程进行学习,你需要:
- Azure 订阅 - 免费创建订阅
- 拥有 Azure 订阅后,在 Azure 门户中创建必应搜索资源来获取密钥和终结点。 部署后,单击“转到资源”。
- Visual Studio IDE。
创建新的控制台应用项目
在 Visual Studio 中,使用 Ctrl
+Shift
+N
创建项目。
在“新建项目”对话框中,单击“Visual C#”>“Windows 经典桌面”>“控制台应用(.NET Framework)”。
将应用程序命名为“MyConsoleSearchApp”,然后单击“确定” 。
向项目添加 JSON.net NuGet 包
JSON.net 允许使用 API 返回的 JSON 响应。 将其 NuGet 包添加到项目中:
- 在“解决方案资源管理器”中,右键单击项目并选择“管理 NuGet 包...” 。
- 在“浏览”选项卡中,搜索
Newtonsoft.Json
。 选择最新版本,然后单击“安装”。 - 单击“查看更改”窗口中的“确定”按钮 。
- 关闭标题为“NuGet: MyConsoleSearchApp”的 Visual Studio 选项卡。
添加对 System.Web 的引用
本教程依赖于 System.Web
程序集。 将对此程序集的引用添加到项目中:
- 在“解决方案资源管理器”中,右键单击“引用”并选择“添加引用...”
- 选择“程序集”>“框架”,然后向下滚动并选中“System.Web”
- 选择“确定”
添加一些必要的 using 语句
本教程中的代码还需要三个 using 语句。 在 Program.cs 顶部的现有 using
语句下面添加这些语句:
using System.Web;
using System.Net.Http;
要求用户发出查询
在“解决方案资源管理器”中,打开“Program.cs” 。 更新 Main()
方法:
static void Main()
{
// Get the user's query
Console.Write("Enter Bing query: ");
string userQuery = Console.ReadLine();
Console.WriteLine();
// Run the query and display the results
RunQueryAndDisplayResults(userQuery);
// Prevent the console window from closing immediately
Console.WriteLine("\nHit ENTER to exit...");
Console.ReadLine();
}
此方法:
- 要求用户发出查询
- 调用
RunQueryAndDisplayResults(userQuery)
执行查询并显示结果 - 等待用户输入,以防控制台窗口立即关闭。
使用必应 Web 搜索 API 搜索查询结果
接下来,添加一个用于查询 API 并显示结果的方法:
static void RunQueryAndDisplayResults(string userQuery)
{
try
{
// Create a query
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "<YOUR_SUBSCRIPTION_KEY_GOES_HERE>");
var queryString = HttpUtility.ParseQueryString(string.Empty);
queryString["q"] = userQuery;
var query = "https://api.cognitive.microsoft.com/bing/v7.0/search?" + queryString;
// Run the query
HttpResponseMessage httpResponseMessage = client.GetAsync(query).Result;
// Deserialize the response content
var responseContentString = httpResponseMessage.Content.ReadAsStringAsync().Result;
Newtonsoft.Json.Linq.JObject responseObjects = Newtonsoft.Json.Linq.JObject.Parse(responseContentString);
// Handle success and error codes
if (httpResponseMessage.IsSuccessStatusCode)
{
DisplayAllRankedResults(responseObjects);
}
else
{
Console.WriteLine($"HTTP error status code: {httpResponseMessage.StatusCode.ToString()}");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
此方法:
- 创建
HttpClient
以查询 Web 搜索 API - 设置必应用于验证请求的
Ocp-Apim-Subscription-Key
HTTP 标头 - 执行请求并使用 JSON.net 反序列化结果
- 调用
DisplayAllRankedResults(responseObjects)
以按排名顺序显示所有结果
确保将 Ocp-Apim-Subscription-Key
的值设置为订阅密钥。
显示排名结果
在介绍如何按排名顺序显示结果之前,请先查看 Web 搜索响应示例:
{
"_type" : "SearchResponse",
"webPages" : {
"webSearchUrl" : "https:\/\/www.bing.com\/cr?IG=70BE289346...",
"totalEstimatedMatches" : 982000,
"value" : [{
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/v7\/#WebPages.0",
"name" : "Contoso Sailing Club - Seattle",
"url" : "https:\/\/www.bing.com\/cr?IG=70BE289346ED4594874FE...",
"displayUrl" : "https:\/\/contososailingsea...",
"snippet" : "Come sail with Contoso in Seattle...",
"dateLastCrawled" : "2017-04-07T02:25:00"
},
{
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/7\/#WebPages.6",
"name" : "Contoso Sailing Lessons - Official Site",
"url" : "http:\/\/www.bing.com\/cr?IG=70BE289346ED4594874FE...",
"displayUrl" : "https:\/\/www.constososailinglessonsseat...",
"snippet" : "Contoso sailing lessons in Seattle...",
"dateLastCrawled" : "2017-04-09T14:30:00"
},
...
],
"someResultsRemoved" : true
},
"relatedSearches" : {
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/7\/#RelatedSearches",
"value" : [{
"text" : "sailing lessons",
"displayText" : "sailing lessons",
"webSearchUrl" : "https:\/\/www.bing.com\/cr?IG=70BE289346E..."
}
...
]
},
"rankingResponse" : {
"mainline" : {
"items" : [{
"answerType" : "WebPages",
"resultIndex" : 0,
"value" : {
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/v7\/#WebPages.0"
}
},
{
"answerType" : "WebPages",
"resultIndex" : 1,
"value" : {
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/v7\/#WebPages.1"
}
}
...
]
},
"sidebar" : {
"items" : [{
"answerType" : "RelatedSearches",
"value" : {
"id" : "https:\/\/api.cognitive.microsoft.com\/api\/v7\/#RelatedSearches"
}
}]
}
}
}
rankingResponse
JSON 对象(文档)描述了搜索结果的相应显示顺序。 它包括以下一个或多个按优先级排列的组:
-
pole
:要获得最明显的处理(例如,显示在主线和边栏上方)的搜索结果。 -
mainline
:要显示在主线中的搜索结果。 -
sidebar
:要显示在边栏中的搜索结果。 如果没有边栏,则在主线下方显示结果。
排名响应 JSON 可能包括一个或多个组。
在 Program.cs 中添加以下方法,以按正确排名顺序显示结果:
static void DisplayAllRankedResults(Newtonsoft.Json.Linq.JObject responseObjects)
{
string[] rankingGroups = new string[] { "pole", "mainline", "sidebar" };
// Loop through the ranking groups in priority order
foreach (string rankingName in rankingGroups)
{
Newtonsoft.Json.Linq.JToken rankingResponseItems = responseObjects.SelectToken($"rankingResponse.{rankingName}.items");
if (rankingResponseItems != null)
{
foreach (Newtonsoft.Json.Linq.JObject rankingResponseItem in rankingResponseItems)
{
Newtonsoft.Json.Linq.JToken resultIndex;
rankingResponseItem.TryGetValue("resultIndex", out resultIndex);
var answerType = rankingResponseItem.Value<string>("answerType");
switch (answerType)
{
case "WebPages":
DisplaySpecificResults(resultIndex, responseObjects.SelectToken("webPages.value"), "WebPage", "name", "url", "displayUrl", "snippet");
break;
case "News":
DisplaySpecificResults(resultIndex, responseObjects.SelectToken("news.value"), "News", "name", "url", "description");
break;
case "Images":
DisplaySpecificResults(resultIndex, responseObjects.SelectToken("images.value"), "Image", "thumbnailUrl");
break;
case "Videos":
DisplaySpecificResults(resultIndex, responseObjects.SelectToken("videos.value"), "Video", "embedHtml");
break;
case "RelatedSearches":
DisplaySpecificResults(resultIndex, responseObjects.SelectToken("relatedSearches.value"), "RelatedSearch", "displayText", "webSearchUrl");
break;
}
}
}
}
}
此方法:
- 循环访问响应包含的
rankingResponse
组 - 通过调用
DisplaySpecificResults(...)
显示每个组中的项目
在 Program.cs 中,添加以下两种方法:
static void DisplaySpecificResults(Newtonsoft.Json.Linq.JToken resultIndex, Newtonsoft.Json.Linq.JToken items, string title, params string[] fields)
{
if (resultIndex == null)
{
foreach (Newtonsoft.Json.Linq.JToken item in items)
{
DisplayItem(item, title, fields);
}
}
else
{
DisplayItem(items.ElementAt((int)resultIndex), title, fields);
}
}
static void DisplayItem(Newtonsoft.Json.Linq.JToken item, string title, string[] fields)
{
Console.WriteLine($"{title}: ");
foreach( string field in fields )
{
Console.WriteLine($"- {field}: {item[field]}");
}
Console.WriteLine();
}
将这些方法结合使用可将搜索结果输出到控制台。
运行应用程序
运行应用程序。 输出应如下所示:
Enter Bing query: sailing lessons seattle
WebPage:
- name: Contoso Sailing Club - Seattle
- url: https://www.bing.com/cr?IG=70BE289346ED4594874FE...
- displayUrl: https://contososailingsea....
- snippet: Come sail with Contoso in Seattle...
WebPage:
- name: Contoso Sailing Lessons Seattle - Official Site
- url: http://www.bing.com/cr?IG=70BE289346ED4594874FE...
- displayUrl: https://www.constososailinglessonsseat...
- snippet: Contoso sailing lessons in Seattle...
...
后续步骤
详细了解使用排名显示结果。