1. 程式人生 > 其它 >記錄一次C#爬蟲記錄,獲取必應圖片

記錄一次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的了,經過一個小時的爬蟲整理上傳。

https://gitee.com/Pridejoy/Bing

已經上傳
2016年桌布(366張)
2017年必應桌布(365)
2018年必應桌布(365張)
2019年必應桌布(365張)
2020年必應桌布(366張)
每一張都是精彩絕倫

等到後面會把api開放出來,可以通過情求獲取桌布,包括不同的解析度


先說明下,
具體的原始碼 https://wwa.lanzoui.com/iXeZTv7pevi