.Net解析html文檔類庫HtmlAgilityPack完整使用說明

來源:互聯網
上載者:User

標籤:des   class   blog   code   java   http   

在前幾篇文章中([搜房網房產資料擷取程式demo--GeckoWebBrowser執行個體] )都有提到一個解析html的C#類庫HtmlAgilityPack,

今天終於有時間整理一下,並把Demo分享一下。

HtmlAgilityPack是一個基於.Net的、第三方免費開源的微型類庫,主要用於在伺服器端解析html文檔(在B/S結構的程式中用戶端可以用Javascript、jquery解析html)。截止到本文發表時,HtmlAgilityPack的最新版本為 1.4.6。:http://htmlagilitypack.codeplex.com/。最新版本支援Linq to Objects ( LINQ to Xml ).

準備:

如果你有安裝Nuget的話,可以直接尋找安裝即可。

下載後解壓縮後有3個檔案,這裡只需要將其中的HtmlAgilityPack.dll(程式集)、HtmlAgilityPack.xml(文檔,用於Visual Studio 2008中代碼智能提示和協助說明之用)引入解決方案中即可使用,無需安裝任何東西,非常好用。

在C#類檔案開頭引入using HtmlAgilityPack;就可以使用該命名空間下的類型了。實際使用中,幾乎都是以HtmlDocument類為主線的,這一點非常類似於微軟.net framework中的XmlDocument類。XmlDocument類是操作的是xml文檔,而HtmlDocument類操作的是html文檔(其實也可以操作xml文檔),它們的操作方式都是基於Dom,所不同的是後者取消了諸如GetElementsByTagName這樣的方法,強化了GetElementById方法(在HtmlDocument中可以直接使用,而XmlDocument則不可以)。

HtmlAgilityPack中定位節點基本上都用Xpath運算式,Xpath運算式的參考文檔可見:http://www.w3school.com.cn/xpath/xpath_syntax.asp。自行學習。

不過可以先用幾個簡單就可以。比如,我們用到最多可能就是針對某個元素(div)、或者某個class屬性的div、或者某個id的div,或者以什麼開頭的div,

類似這樣的Xpath還是比較簡單的。

Xpath舉幾個例子,下面的代碼中我們就會用到:

"//comment()"在XPath中表示“所有注釋節點”

1、擷取網頁title:doc.DocumentNode.SelectSingleNode("//title").InnerText;  解釋:XPath中“//title”表示所有title節點。SelectSingleNode用於擷取滿足條件的唯一的節點。

2、擷取所有的超連結:doc.DocumentNode.Descendants("a")

3、擷取name為kw的input,也就是相當於getElementsByName():             var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name=‘kw‘]");

解釋:"//input[@name=‘kw‘]"也是XPath的文法,表示:name屬性等於kw的input標籤。

//li/h3/a[@href]:所有li下面的h3包含a超級連結有href屬性才符合。有的a可能是支援的js事件

//div[starts-with(@class,‘content_single‘)]:所有合格div,並且它的class是由字串content_single 開頭的。

//標示擷取documet下的所有符合條件。/div標示從根目錄開始的合格。

 

以上是準備工作。下面說一下HtmlAgilityPack讀取web頁面,並解析的方法步驟。

1.讀取url:

 

                HtmlAgilityPack.HtmlWeb hw = new HtmlAgilityPack.HtmlWeb();

                HtmlAgilityPack.HtmlDocument doccc = hw.Load(url);//是你需要解析的url

                ArrayList ImagePtahs = GetHrefs(doccc);

這裡可能會遇到2個問題。

一個是編碼問題,一個是gzip不支援的問題。

首先編碼問題解決辦法:就是不用HtmlAgilityPack去擷取Url的data資料,自己擷取了。大家可能就問了:我自己擷取了他不給我解析那?

沒事,他不會那麼笨的。誰的肉不是吃啊?

方法如下:

 

              WebProxy proxyObject = new WebProxy(IP, port);//這裡我是用的代理。

                //向指定地址發送請求

               HttpWebRequest HttpWReq = (HttpWebRequest)WebRequest.Create(url);

                HttpWReq.Proxy = proxyObject;

                HttpWReq.Timeout = 10000;

                HttpWebResponse HttpWResp = (HttpWebResponse)HttpWReq.GetResponse();               

                StreamReader sr = new StreamReader(HttpWResp.GetResponseStream(), System.Text.Encoding.GetEncoding("UTF-8"));              

                //注意上面的編碼了嗎??

                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();

                doc.Load(sr);

                int res = CheckIsGoodProxy(doc); //這是我解析的函數,還沒到那一步。不解釋了。

                sr.Close();

                HttpWResp.Close();

                HttpWReq.Abort();

另一個問題就是很奇怪了。gzip的問題開啟了gzip壓縮的網頁請求時會報錯。報錯資訊為“gzip”不是受支援的編碼名。

 在Google上搜尋了半天,終於找到解決方案,而且不必更換HttpRequest或WebClient進行請求。同時還可以用此方法設定cookie,render偽裝等等。。。
解決後代碼如下:在你發起請求的是修改一下。

 

HtmlWeb webClient = new HtmlWeb();

HtmlAgilityPack.HtmlWeb.PreRequestHandler handler = delegate(HttpWebRequest request)

{

       request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";

       request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;

       request.CookieContainer = new System.Net.CookieContainer();

       return true;

};

webClient.PreRequest += handler;

HtmlDocument doc = webClient.Load(this.getUrl());

可能最新版本的HtmlAgilityPack會修複這個問題吧。期待中。

2.用Xpath解析。

這一步就比較簡單了。就用Xpath選出你想要的資料,遍曆他們,取出他們的value即可。

執行個體代碼:

 

    private ArrayList GetHrefs(HtmlAgilityPack.HtmlDocument _doc)

        {

            try

            {

                Images = new ArrayList();

                HtmlNodeCollection hrefs = _doc.DocumentNode.SelectNodes("//li/h3/a[@href]");

                   HtmlNodeCollection hrefs2 = _doc.DocumentNode.SelectNodes("//div[starts-with(@class,‘content_single‘)]");

                if (hrefs == null)

                    return new ArrayList();

                foreach (HtmlNode href in hrefs)

                {

                    //  Images.Add(href.Attributes["src"].Value);

                    string hreff = href.Attributes["href"].Value;// 排除  博海拾貝第二百零二期】吃完薯條寂寞了 

                    string title = href.Attributes["title"].Value;

                  if (title.IndexOf("邪惡") >= 0)

                    {

                        continue;

                    }

                    if (title.IndexOf("惡搞") >= 0)

                    {

                        continue;

                    }

                    if (title.IndexOf("雷人") >= 0)

                    {

                        continue;

                    }

                    ///執行資料儲存的邏輯

                }

}

 catch (Exception ex)

            {

                ShowLogMsg("出錯了:"+ex.Message+ex.StackTrace);

                return new ArrayList();

            }

        }

 

每一個Htmlnode,你要擷取他的資料用這個方法:  img.Attributes["src"].Value

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.