使用 C# 获取必应每日图片





5.00/5 (6投票s)
使用不同的 JSON 解析方法获取必应每日图片
概述
必应每日图片多年来一直非常受欢迎,它包含了过去5年来在必应主页上展示的来自世界各地的最壮观的用户提交的图片。我非常喜欢必应桌面应用程序中“必应每日壁纸”部分。必应桌面应用程序每天都会将您的壁纸更改为必应每日图片,这很酷,并且可以给您带来心灵的平静,而无需手动每天更改壁纸。Windows Phone 也采用了类似的概念,您可以将锁屏设置为必应每日图片。
我对这个想法非常感兴趣,以至于我想自己尝试构建一个应用程序来检索必应图片。我知道一旦我能够检索到图片,未来就有了无数的可能性。我可以将其保存并在我选择的特定时间后更改桌面,或者将其设置为我的锁屏,就像桌面壁纸一样,您明白了,关键在于获取必应每日图片。
幸运的是,必应有一个REST API
可以检索包含必应图片URL的JSON
字符串,我们将使用它。这部分很容易,现在难的部分是从JSON字符串中解析和检索URL。我将详细讨论可以用于解析的不同方法以及如何使用它们来提取必应图片URL。
步骤 1. 检索 JSON 字符串
第一步是从必应 REST API 端点检索JSON字符串。我们使用 HttpClient
检索字符串,我们可以选择使用 Windows.Web.Http
或 System.Net.Http 命名空间
。我倾向于选择 Windows.Web.Http.HttpClient 的简单原因是 System.Net.Http.HttpClient 可能会随着时间的推移而被弃用。另一个原因是System.Net.Http.HttpClient 只支持 .Net 语言,而 Windows.Web.Http.HttpClient 的创建目的是为了整合不同 Windows 应用程序语言的所有 HTTP API,因此它支持所有 Windows 应用商店应用程序语言。对于有兴趣的读者,这里是两者的详细比较。
// We can specify the region we want for the Bing Image of the Day.
string strRegion = "en-US";
string strBingImageURL = string.Format("http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n={0}&mkt={1}", _numOfImages, strRegion);
string strJSONString = "";
HttpClient client = new HttpClient();
// Using an Async call makes sure the app is responsive during the time the response is fetched.
// GetAsync sends an Async GET request to the Specified URI.
HttpResponseMessage response = await client.GetAsync(new Uri(strBingImageURL));
// Content property get or sets the content of a HTTP response message.
// ReadAsStringAsync is a method of the HttpContent which asynchronously
// reads the content of the HTTP Response and returns as a string.
strJSONString = await response.Content.ReadAsStringAsync();
步骤 2. 解析 JSON 字符串
现在我们可以使用 3 种方法解析检索到的 JSON 字符串:
- 使用
Windows.Data.Json
(原生方式) - 使用
JSON.NET
(Newtonsoft)的LINQ-to-JSON
API 的 JObject - 使用 JSON.NET(Newtonsoft)的
dynamic
对象和DeserializeObject
方法
JSON.Net 在 Windows.Data.Json 出现之前就已经存在了,但是,Microsoft 引入了具有原生支持的 JSON 解析的 Windows.Data.Json。要使用 JSON.NET,您需要添加 Newtonsoft
Nuget 包,这会增加额外的库依赖项。我个人更喜欢原生方式,但是对于这个应用程序,我已经讨论了使用JSON.NET 和Windows.Data.Json 命名空间解析 JSON 字符串的两种方法。
检索到的 JSON 字符串
{"images":[
{"startdate":"20160719","fullstartdate":"201607190700","enddate":"20160720","url":"/az/hprichbg/rb/NeonMuseum_EN-US8131993872_1920x1080.jpg","urlbase":"/az/hprichbg/rb/NeonMuseum_EN-US8131993872","copyright":"Neon Museum, Las Vegas, Nevada (© Kerrick James/Getty Images)","copyrightlink":"http://www.bing.com/search?q=neon+museum&form=hpcapt&filters=HpDate:%2220160719_0700%22","wp":false,"hsh":"96d3e7bbe87ad583a17ef765ed935d8f","drk":1,"top":1,"bot":1,"hs":[]}
,
{"startdate":"20160718","fullstartdate":"201607180700","enddate":"20160719","url":"/az/hprichbg/rb/DiamondHead_EN-US10119574903_1920x1080.jpg","urlbase":"/az/hprichbg/rb/DiamondHead_EN-US10119574903","copyright":"Aerial view of Diamond Head, O’ahu, Hawaii (© Biederbick & Rumpf/Offset)","copyrightlink":"http://www.bing.com/search?q=diamond+head+hawaii&form=hpcapt&filters=HpDate:%2220160718_0700%22","wp":true,"hsh":"1aff492416f5e2fcf6e898743154fbda","drk":1,"top":1,"bot":1,"hs":[]}
,
{"startdate":"20160717","fullstartdate":"201607170700","enddate":"20160718","url":"/az/hprichbg/rb/MuizenbergSA_EN-US9176714978_1920x1080.jpg","urlbase":"/az/hprichbg/rb/MuizenbergSA_EN-US9176714978","copyright":"Beach huts in Muizenberg, South Africa (© Getty Images)","copyrightlink":"http://www.bing.com/search?q=Muizenberg,+South+Africa&form=hpcapt&filters=HpDate:%2220160717_0700%22","wp":true,"hsh":"8d4bf37f9d61ab103283005264b4b8cb","drk":1,"top":1,"bot":1,"hs":[]}
]
,"tooltips":{"loading":"Loading...","previous":"Previous image","next":"Next image","walle":"This image is not available to download as wallpaper.","walls":"Download this image. Use of this image is restricted to wallpaper only."}
步骤 2a. 使用 Windows.Data.Json 解析 JSON 字符串
此方法解析获取的 JSON 字符串,并使用 Microsoft Windows.Data.Json
类检索图片 URL。我们使用 JsonObject
,它实现了IMap 接口,可以像字典一样帮助操作名称/值对。我们使用 JsonObject.TryParse
方法将 JSON 字符串解析为 JSON 值,它返回一个布尔值,表示成功或失败。检索的关键部分是 jsonObject["images"].GetArray()[i].GetObject()["url"].GetString()
。如上面的 JSON 字符串所示,我们有一个根对象 "images"
,它进一步有 3 个数组,分别对应于步骤 1 中指定的图片数量。每个数组都有一个名为 url 的对象,这是必应图片 URL 的一部分。我们检索每个图片的 url 并将其存储到一个列表中。
// Parse using Windows.Data.Json.
JsonObject jsonObject;
bool boolParsed = JsonObject.TryParse(_strRawJSONString, out jsonObject);
if (boolParsed)
{
for (int i = 0; i < _numOfImages; i++)
{
_lstBingImageURLs.Add(jsonObject["images"].GetArray()[i].GetObject()["url"].GetString());
}
}
步骤 2b. 使用 LINQ-to-JSON API 的 JObject 解析 JSON 字符串
此方法解析获取的 JSON 字符串,并显式使用 LINQ-to-JSON
API 的 JObject
来检索图片 URL。当我们提前不知道 JSON 结构时,我们就使用此方法。如果只需要整个 JSON 字符串中的一两个值,则推荐此方法。
// Parse using LINQ-to-JSON API's JObject explicitly.
JObject jResults = JObject.Parse(_strRawJSONString);
foreach (var image in jResults["images"])
{
_lstBingImageURLs.Add((string)image["url"]);
}
步骤 2c. 使用 DeserializeObject 和 dynamic 对象解析 JSON 字符串
此方法解析获取的 JSON 字符串,并使用 DeserializeObject
方法检索图片 URL。当我们已经知道 JSON 结构以及我们想要反序列化的强类型类时,我们使用 JsonConvert.DeserializeObject
方法。我们使用 dynamic
对象,因为它省去了声明一个特定类来保存 JSON 对象的麻烦。
// Parse using DeserializeObject method.
for (int i = 0; i < _numOfImages; i++)
{
_lstBingImageURLs.Add(Convert.ToString((JsonConvert.DeserializeObject<dynamic>(_strRawJSONString)).images[i].url));
}
步骤 3. 使用 BitmapImage 在 UI 上显示图片
每个 URL 都被转换为 Bitmap Image 并动态添加到 Stack Panel 中,以显示为 Image 对象。BitmapImage
类继承自 BitmapSource
类,并且是一个专门化的 BitmapSource
,它针对使用 XAML 加载图片进行了优化。
foreach (string url in _lstBingImageURLs)
{
// We use the Image control to display an image on the UI.
Image imgbingImage = new Image();
var bingURL = "https://www.bing.com" + url;
BitmapSource imgbingImageSource = new BitmapImage(new Uri(bingURL));
imgbingImage.Source = imgbingImageSource;
// Add the Image control to the Stack Panel
spImages.Children.Add(imgbingImage);
}
工作的 Windows 10 UWP 应用
这是工作中的Windows 10 UWP 应用的截图。我已将Visual Studio 解决方案文件及源代码托管在 Github 仓库 Bing-Image-JSON,您可以自行尝试。
最后说明
Github 仓库中的源代码包含完整的详细代码,您可以用来尝试并跟随。如果您仍然遇到任何问题或有任何疑问,请随时留下评论,我很乐意为您提供帮助。祝您一切顺利 :)