今天特別學習和實踐了一下HtmlAgilityPack和XPath,並作下筆記。
1.下載HtmlAgilityPack.dll並將其添加引用到項目中,然後在代碼中聲明引用。 下載地址:http://www.codeplex.com/htmlagilitypack 引用: using HtmlAgilityPack;
2.下載獲取HTML頁面的步驟和我上篇文章裡介紹的差不多,都是先用WebClient或者WebRequest類來下載HTML頁面然後處理成字符串。
3.與上次不同的是,這裡分析和抓取HTML節點中的數據不再是之前那種STRING字符串操作的方式,而是封裝成一個HtmlDocument對象,通過HtmlDocument中的方法來索引你需要抓取HTML節點,進而取出節點中的值。
4.若需要抓取的節點有ID,類似「<div id='post_list'>value</div>」這種,那很簡單只需調用GetElementbyId方法根據節點ID即可獲取所需節點。從而通過HtmlNode中的InnerText或Attribute屬性來獲取你想要的值。 CODE: //實例化HtmlAgilityPack.HtmlDocument對像 HtmlDocument doc = new HtmlDocument(); //載入HTML doc.LoadHtml(mainData); //根據HTML節點NODE的ID獲取節點 HtmlNode navNode = doc.GetElementbyId("post_list");
5.但很多情況下HTML節點是沒有ID的,那就需要通過XPATH語言來查找匹配所需節點(XPath教程)。以抓取博客園首頁文章為例,通過查看博客園HTML可以發現博客園首頁裡的文章列表都是放在一個ID為"post_list"的"<div>"節點中的。
這樣的話就可以通過調用GetElementbyId方法來定位到這個節點了。
6.在獲取到"post_list"節點後,接下來就可以調用SelectSingleNode方法通過XPATH表達式來索引出需要抓取的節點,從而抓取到文章的標題和鏈接地址。 (PS:在博客園首頁"post_list"節點裡,平均每4個DIV就是一篇新的文章可以利用這一規律遍歷出首頁所有文章) CODE: //實例化HtmlAgilityPack.HtmlDocument對像 HtmlDocument doc = new HtmlDocument(); //載入HTML doc.LoadHtml(mainData); //根據HTML節點NODE的ID獲取節點 HtmlNode navNode = doc.GetElementbyId("post_list"); //根據XPATH來索引節點 //div[2]表示文章鏈接a位於post_list裡面第3個div節點中 HtmlNode navNode2 = navNode.SelectSingleNode("//div[2]/h3/a"); //獲取文章鏈接地址 string articleTitle = navNode2.Attributes["href"].Value.ToString(); //獲取文章標題 string articleName = navNode2.InnerText; 對比一下之前使用string截取字符串的方法: //以"<a class=\"titlelnk\" href=\""作為抓取點開始採集 mainData=mainData.Substring(mainData.IndexOf("<a class=\"titlelnk\" href=\"") + 26); //獲取文章頁面的鏈接地址 string articleAddr = mainData.Substring(0,mainData.IndexOf("\"")); //獲取文章標題 string articleTitle = mainData.Substring(mainData.IndexOf("target=\"_blank\">") + 16, mainData.IndexOf("</a>") - mainData.IndexOf("target=\"_blank\">") - 16); 可見與之前相比,使用HtmlAgilityPack.HtmlDocument類來實現前台HTML的分析和採集在頁面編碼和數據分析上面處理更加合理、優化,代碼也更加簡潔。
目前只是粗淺地學了一下HtmlAgilityPack提取HTML節點數值的應用,更多應用以及採集速度的優化處理等方面尚未仔細研究,還望高人指點。 |
[轉貼] 通過HtmlAgilityPack+XPath來優化網頁採集
相關文章