記錄一次C#爬蟲記錄,獲取必應圖片
記錄一次C#爬蟲記錄,獲取必應圖片
起因
事情是這樣的,我建立了一個倉庫,裡面有2018年到目前為止每日的必應桌布,在八月份的時候我看到微軟有介面文件,於是寫了一個服務,每天早上八點鐘會獲取必應桌布(目前已經可以作為api來使用了,暫時不對外開放)
然後推送到微信上面。這個專案的地址是 https://gitee.com/Pridejoy/Bing,有興趣的可以去看看。但是吧,這個倉庫有兩個問題
- 2018年以前的桌布沒有的
- 2018年後的桌布沒有版權說明
為了更新這個倉庫,我偶然見發現一個網站裡面有必應桌布,而且免費開放,我就絕對去爬這個網站
經過
說幹就幹,我學的是C#,聽聞python的爬蟲很厲害,但是0基礎入門就不怎麼回來,下定決心就幹,我發現了一個neget包爬蟲挺簡單的。我分析了需要爬蟲的網站。然後就開始下程式碼
步驟
不如授人以魚不如授人以漁
使用的具體詳情 https://www.cnblogs.com/xuliangxing/p/8004403.html
安裝包
HtmlAgilityPack
如何載入Html
主要常見的有三種方式;從檔案載入、從字串載入、從網頁連結載入。
// 從物理路徑的檔案載入 var doc = new HtmlDocument(); doc.Load(filePath);//檔案路徑 // 從Stream當中載入 var doc = new HtmlDocument(); doc.LoadHtml(html); // 從網頁的Url連結載入 var url = "http://www.cnblogs.com/xuliangxing/"; var web = new HtmlWeb(); var doc = web.Load(url);
以Stream物件為主的過載方法:
(1)public void Load(Stream stream) ///從指定的Stream物件中載入html; (2)public void Load(Stream stream, bool detectEncodingFromByteOrderMarks) ///指定是否從順序位元組流中解析編碼格式 (3)public void Load(Stream stream, Encoding encoding) ///指定編碼格式 (4)public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks) (5)public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize) ///緩衝區大小
以指定的物理路徑為主的過載方法:
(1)public void Load(string path)
(2)public void Load(string path, bool detectEncodingFromByteOrderMarks) ///指定是否從順序位元組流中解析編碼格式
(3)public void Load(string path, Encoding encoding) ///指定編碼格式
(4)public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
(5)public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)
如何精準定位到我們需要的資料
這個時候我們需要用到HtmlNodeCollection和HtmlNode這兩個類,我們把Html每個標籤看作一個Node,所有我們想到定位到某個標籤的內容,就需要知道這個標籤的相關屬性。順便說一下,HtmlNode類實現了IXPathNavigable介面,這說明了它可以通過xpath來定位資料了,如果你對解析XML格式資料的XmlDocument類瞭解的話,特別是使用過了SelectNodes()和SelectSingleNode()方法的人來說,對使用HtmlNode類將會很熟悉。其實Html Agility Pack內部是把html解析成xml文件格式了的,所以支援xml中的一些常用查詢方式。下面通過簡單示例對HtmlNode的一些主要的常用成員作簡要的說明。
1.通過ID屬性(或者其他屬性)來選擇對應的節點
通用格式:@id=‘xxxx’(id可以是其他屬性等等),比如我們要定位到本文部落格主頁的標題和副標題內容。
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(url)//部落格主頁URL
//下面的意思是:通過屬性id的值,來定位header下的blogTitle節點資訊
HtmlNode titleNode = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='blogTitle']");
我們還可以不通過屬性id去定位,還有通過索引去定位,如下所示,這個效果和上面是等同的:
//下面的意思是:通過索引定位,div[2]是表示根節點的第二個
HtmlNode titleNode = doc.DocumentNode.SelectSingleNode("//div[2]/div[1]");
備註:注意路徑裡"//"表示從根節點開始查詢,兩個斜槓‘//’表示查詢所有childnodes;一個斜槓'/'表示只查詢第一層的childnodes(即不查詢grandchild);點斜槓"./"表示從當前結點而不是根結點開始查詢
2.如何獲取節點文字內容
IDNode.OuterHtml ///返回結果是:<h1><a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法號阿興</a></h1>
IDNode.InnerHtml ///返回結果是:<a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">法號阿興</a>
IDNode.InnerText ///返回結果是:法號阿興
3.如何獲取節點屬性值
假如我們上面Html資料當中,博主部落格地址,在標籤<div id="header">
裡的<a>
標籤裡,這個時候就需要使用HtmlNode下的Attribute屬性了。
string url = doc.DocumentNode.SelectSingleNode("//div[@id='header']/div[@id='blogTitle']/a").Attributes["href"].Value;
4.如何獲取某個標籤的所有節點
我們如果獲取前面Html資料的li所有分類,這個時候需要使用方法SelectNodes了
HtmlNodeCollection uiListNodes = doc.DocumentNode.SelectNodes("//ui[@id='navList']/li")
5.如何去掉外層的html tag只留下文字內容
回到我們剛剛上面講到的地方,用remove方法。假設要刪除上文結點<a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/xuliangxing/">
法號阿興</a>
,你想留下部落格名稱而不要的話,那你需要先得到這個Html結點,通過remove方法刪除掉多餘的HTML Tag假設該節點叫Node:
Node.ParentNode.RemoveChild(Node,true);
結果
結構當然是ok的了,經過一個小時的爬蟲整理上傳。
已經上傳
2016年桌布(366張)
2017年必應桌布(365)
2018年必應桌布(365張)
2019年必應桌布(365張)
2020年必應桌布(366張)
每一張都是精彩絕倫
等到後面會把api開放出來,可以通過情求獲取桌布,包括不同的解析度
先說明下,
具體的原始碼 https://wwa.lanzoui.com/iXeZTv7pevi