把Bing搜索的背景图片设置为自己网站的背景,实现背景及资讯的每日更新
效果图如下:
理一下思路,首先我们要抓取Bing的每日图片及最新资讯,然后保存图片及信息到本地,最后显示图片及资讯到网站首页。
第一步:抓取图片
首先打开Bing,然后使用开发者工具 F12,点击审查网页元素,分析HTML结构如下图:
这里可以看到背景的图片地址,这就准备从HTML元素中获取图片链接了。于是我还下载了Jumony 一个提取网页元素的帮助类,来获取background-image的元素(Jumony的使用可以直接在NuGet管理中搜索Jumony,然后安装,最后记得引用命名空间,Jumony的详细使用请移步http://www.cnblogs.com/Ivony/p/3447536.html)
结果发现 获取的HTML标签里并没有CSS的属性,那也就取不到 背景图片的URL了,然后怎么办呢?
继续使用开发者工具查看Bing网页,发现了一个Ajax请求,返回了一个Json数据,如下图:
说明这个请求返回的Json就是Bing的每日图片的信息,这就能得到图片信息的请求网址了,查看消息头:
请求网址:http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=1470798060031&pid=hp&video=1
然后检测请求中可以省略的参数,最后得到URL:http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1
接下来就需要在程序中获取Json数据,使用WebClient 进行网页请求:
这时我们就要对Json进行解析,获取我们想要的数据,也就是背景图片的URL:
对Json的解析有很多方法:Json转换为dataTable,Json反序列化,也有第三方组件等,
这里用自己比较擅长的方法:VS自带的javaScriptSerializer类将wallejson转换为模型,这个模型根据返回的Json数据结构创建
解析完之后就得到了图片的URL,根据WebClient的DownLoadFile()方法保存图片到本地;
附上模型:
1 //用于解析Bing返回的Json数据
2
3
4 public class Walle
5 {
6 public List<images> images { get; set; }
7 public tooltips tooltips { get; set; }
8 }
9
10 public class images
11 {
12 public string startdate { get; set; }
13 public string fullstartdate { get; set; }
14 public string enddate { get; set; }
15 public string url { get; set; }
16 public string urlbase { get; set; }
17 public string copyright { get; set; }
18 public string copyrightlink { get; set; }
19 public string wp { get; set; }
20 public string hsh { get; set; }
21 public string drk { get; set; }
22 public string top { get; set; }
23 public string bot { get; set; }
24 public List<int> hs { get; set; }
25
26
27 }
28
29 public class tooltips
30 {
31 public string loading { get; set; }
32 public string previous { get; set; }
33 public string next { get; set; }
34 public string walle { get; set; }
35 public string walls { get; set; }
36
37 }
第二步:获取每日资讯
我们要获取这里的数据:
继续使用开发者工具查看数据的位置:
这就可以使用Jumony抓取数据了吧,和刚开始一样,
结果很郁闷,在HTML页面中找不到类名为"hplaCata"的元素内容。
仔细查看了网络连接后,发现了一个很有意思的事情:
如下图:
打开这个请求后:
原来是个单独的页面,怪不得在原来的页面上找不到,接下来就好办了:
保存这个页面的请求:http://cn.bing.com/cnhp/life?currentDate=20160809&IID=SERP.5045&IG=CC0CACB23C324D99A37ACF3604BF19FE,
经过简单的测试,currentDate是当天的日期,其他的参数则不需要。
下面直接看代码,根据Jumony抓取数据:
string date = DateTime.Now.ToString("yyyyMMdd");
//获取文本信息
string BingUrl = "https://cn.bing.com/cnhp/life?currentDate="+date;
var Source = new JumonyParser().LoadDocument(BingUrl);
string Title="";
string Text="";
//标题
foreach (var item in Source.Find(".hplaCata > .hplatt"))
{
Title = item.InnerText();
}
//文本
foreach (var item in Source.Find("#hplaSnippet"))
{
Text = item.InnerText();
}
第三步:保存数据到本地
前面两步已经获取到了图片以及资讯,然后应该保存数据了,
一般来说我们都是保存图片路径 和 资讯数据到数据库,不过需求是替换原来的网站首页背景,偏向于对UI的改进,再动数据库就不太合适了。
而且,图片会每日更新,系统则自动获取,这些数据只提供每天的查询,写操作则一天一次。
解决思路:图片以当前日期为文件名,资讯信息以XML形式,文件名也是当前日期(如20160810)保存到网站目录下,每次首页加载都会查看以当前日期为文件名的Xml文件或JPG文件是否存在,不存在就执行程序抓取Bing图片和每日资讯,存在则获取数据传递给首页显示。
保存资讯为XML,这里我用的是XmlSerializer,将Model转换并创建XML文件,这个Model主要根据保存的信息来创建,字段有: 标题,副标题,文本信息,图片路径,当前日期。获取数据时反序列化XML为Model;
模型:
1 /// <summary>
2 /// 用于保存和传输Bing背景图片及文本信息
3 /// </summary>
4 public class BgImages
5 {
6 /// <summary>
7 /// 标题
8 /// </summary>
9 public string Title { get; set; }
10
11 /// <summary>
12 /// 副标题
13 /// </summary>
14 public string STitle { get; set; }
15 /// <summary>
16 /// 文本
17 /// </summary>
18 public string Text { get; set; }
19 /// <summary>
20 /// 图片路径
21 /// </summary>
22 public string Url { get; set; }
23 /// <summary>
24 /// 保存日期
25 /// </summary>
26 public string Date { get; set; }
27 }
View Code
附上控制器内完整代码:
1 #region 联网抓取图片
2
3 /// <summary>
4 /// 读取背景信息
5 /// </summary>
6 /// <returns></returns>
7 public ActionResult ReturnBgInfo()
8 {
9 //读取XML文件
10 string Path = Server.MapPath("/Images/BingInfo/" + DateTime.Now.ToString("yyyyMMdd") + ".xml");
11
12 FileInfo file = new FileInfo(Path);
13
14 if (!file.Exists)
15 {
16 GetNewBing();
17 }
18
19 FileStream files = new FileStream(Path, FileMode.Open);
20 XmlSerializer xml = new XmlSerializer(typeof(BgImages));
21 BgImages BgImage = (BgImages)xml.Deserialize(files);
22 files.Close();
23
24 return Json(BgImage);
25
26 }
27
28 /// <summary>
29 /// //联网抓取图片
30 /// </summary>
31 public void GetNewBing()
32 {
33 string date = DateTime.Now.ToString("yyyyMMdd");
34
35
36 //获取文本信息
37 string BingUrl = "https://cn.bing.com/cnhp/life?currentDate=" + date;
38
39 var Source = new JumonyParser().LoadDocument(BingUrl);
40 string Title = "";
41 string Text = "";
42 string STitle = "";
43
44 //标题
45 foreach (var item in Source.Find(".hplaCata > .hplatt"))
46 {
47 Title = item.InnerText();
48 }
49
50 //副标题
51 foreach (var item in Source.Find(".hplaCata > .hplats"))
52 {
53 STitle = item.InnerText();
54 }
55
56 //文本
57 foreach (var item in Source.Find("#hplaSnippet"))
58 {
59 Text = item.InnerText();
60 }
61
62
63 //Bing网址
64 string url = "http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1";
65
66 //获取Bing的图片 Json数据
67 WebClient BingClient = new WebClient();
68 BingClient.Encoding = System.Text.Encoding.UTF8;//定义对象的编码语言,此处或者是gb2312
69 string wallejson = BingClient.DownloadString(url);
70
71 if (wallejson != "null")
72 {
73 //解析Json数据
74 JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
75 Walle walleinfo = javaScriptSerializer.Deserialize<Walle>(wallejson);
76
77 //保存图片到本地
78 string ImagePath = DateTime.Now.ToString("yyyyMMdd") + ".JPG";
79 BingClient.DownloadFile(walleinfo.images.First().url, Server.MapPath("/Images/BingInfo/") + ImagePath);
80
81 //保存信息到Model -- BgImages
82 BgImages model = new BgImages();
83 model.Date = walleinfo.images.First().enddate;
84 model.Text = Text;
85 model.Title = Title;
86 model.STitle = STitle;
87 model.Url = "/Images/BingInfo/" + ImagePath;
88
89 string xmlPath = Server.MapPath("/Images/BingInfo/" + DateTime.Now.ToString("yyyyMMdd") + ".xml");
90
91 //序列化XML
92 CreateXML(model, xmlPath);
93
94 }
95
96 }
97
98
99
100
101 #region XML序列化
102 public void CreateXML(BgImages model, string Path)
103 {
104 FileStream fs = new FileStream(Path, FileMode.Create);
105 //执行XML序列化
106 XmlSerializer xml = new XmlSerializer(typeof(BgImages));
107 xml.Serialize(fs, model);
108 fs.Close();
109 }
110 #endregion
111 #endregion
View Code
文章评论