自從 Web 應用程序自 1993 年 W3C 設立以來就開始發展,而且 HTML 也歷經了數個版本的演化(1.0 – 2.0 – 3.0 – 3.2 – 4.0 – 4.01),現在也已經成為Web網頁或應用程序的最基礎,想要學習如何設計 Web 網頁或開發 Web 應用程序,這已經是絕對必須要學的東西了,就算是方便的控件(例如 ASP.NET),但 HTML 仍然有學習它的必要性,因此如果不會 HTML,就等於沒學過 Web 網頁一般。
拜 HTML 與 Web 瀏覽器蓬勃發展之賜,各式各樣的應用都在網絡上迅速發展,舉凡電子商務、企業門戶、在線下單、企業間協同應用等,乃至於社交、個性化、Web 2.0 等商務與組織運用等能力,而在信息爆炸的時代,很多信息整合的應用也隨之出爐,而這些信息整合的應用程序都會連接到不同的網站下載其信息,並且在重重的 HTML 中剖析出想要的數據(例如每股價格、漲跌幅、成交量等)。
但是 HTML 本身並不是一個結構嚴謹的語言,它允許卷標(tag)可以在不 close 的情況下繼續使用。這也是因為瀏覽器設計的高容錯性(Fault Tolerance)所致,如此一來,想要依照規則來剖析 HTML 文件幾乎變得不可能,而且對方的網站的 HTML 結構也可能會隨時變化,在這種情況下,剖析 HTML 變得非常辛苦,雖然 W3C 有另外推展 XHTML(遵守 XML 嚴謹格式的 HTML),但使用它來設計網頁的案例仍為少數,大多數的網站仍然是使用 HTML。因此我們會需要一個工具,能夠有方法快速的解析 HTML 以取出我們需要的數據。
大家都知道,HTML 本身其實只是一個 HTML 標記的字符串而已,因此一般說到要解析 HTML,第一個會想到的大概就是字符串比對(string comparison),自己針對 HTML 的結構寫一個 pattern,然后由函式去做逐一的比對,例如:
[C#]
1. string pattern = "<td id='stockPrice'>";
2. html.IndexOf(pattern);
不過傳統的字符串比對效能太差,也沒有一個規則性,因而才發展出正則表達式(Regular Expression)技術,例如下列這樣的語法:
[Regular Expression]
1. </?\w+((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)/?>
但 Regular Expression 的學習曲線很高,若要使用它來解析 HTML,並且再加以定制化(Customization)的話,對於一般開發人員來說,實在沒有什么親和力。
HTML 還有一個特色,就是它是具層性(Hierarchy)的,因此瀏覽器在解譯它的時候都會以文件樹(document tree)的方式,再用遞歸(recursive)的方法來處理它,但 Regular Expression 沒有支持層級性的剖析,而最接近階層剖析又好用的工具,莫過於 XML Parser 了,它的 DOM 以及 XPath 的特性,都可以讓解析 XML 的工作變得輕松,然而 XML Parser 無法讀取一般的 HTML(XHTML 可以),因為一般的 HTML 是結構松散的類型,XML Parser 會在讀入時檢查語法結構是否完整(也就是 Well-known 的結構),若讀入的是結構松散的內容的話會擲出例外訊息,因此無法直接使用 XML Parser 來輔助。
HTML Agility Pack 是由法國的一位軟件架構師 Simon Mourier 所開發,並且由 DarthObiwan 以及 Jessynoo 輔助開發出來的一個軟件工具,它可以讓剖析松散格式 HTML 的工作就像剖析 XML 一樣簡單,它也有類似於 System.Xml 命名空間中的 XML DOM 的許多類別,除了可以使用階層的方式存取 HTML 以外,它也支持使用 XPath 的方式來搜尋 HTML,這會較以往使用文字比對或是 Regular Expression 的比對方式來得更明確。
若要使用 HTML Agility Pack 組件,可先上 Codeplex 的 HTML Agility Pack 網站下載二進制文件(同時也提供源代碼、說明文件以及 HAP Explorer 工具程序可下載),並解壓縮后,在項目加入對 HtmlAgilityPack.dll 的引用。
Html Agility Pack 源碼中的類大概有28個左右,其實不算一個很復雜的類庫,但它的功能確不弱,為解析DOM已經提供了足夠強大的功能支持,可以跟jQuery操作DOM媲美:)Html Agility Pack最常用的基礎類其實不多,對解析DOM來說,就只有HtmlDocument和HtmlNode這兩個常用的類,還有一個 HtmlNodeCollection集合類。
HTML Agility Pack的操作起來還是很麻煩,下面我們要介紹的這個組件是ScrapySharp,他在2個方面針對Html Agility Pack進行了包裝,使得解析Html頁面不再痛苦,幸福指數直線上升到90分哈。
ScapySharp有了一個真實的瀏覽器包裝類(處理Reference,Cookie等),另外一個就是使用類似於jQuery一樣的Css選擇器和Linq語法。讓我們使用起來非常的爽。它的代碼放在 https://bitbucket.org/rflechner/scrapysharp。也可以通過Nuget添加
下面我們來看一段解析博客園的博客文章的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using ScrapySharp.Extensions;
using ScrapySharp.Network;
namespace HTMLAgilityDemo
{
class Program
{
static void Main(string[] args)
{
var uri = new Uri("http://www.cnblogs.com/shanyou/archive/2012/05/20/2509435.html");
var browser1 = new ScrapingBrowser();
var html1 = browser1.DownloadString(uri);
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(html1);
var html = htmlDocument.DocumentNode;
var title = html.CssSelect("title");
foreach (var htmlNode in title)
{
Console.WriteLine(htmlNode.InnerHtml);
}
var divs = html.CssSelect("div.postBody");
foreach (var htmlNode in divs)
{
Console.WriteLine(htmlNode.InnerHtml);
}
divs = html.CssSelect("#cnblogs_post_body");
foreach (var htmlNode in divs)
{
Console.WriteLine(htmlNode.InnerHtml);
}
}
}
}
Basic examples of CssSelect usages:
var divs = html.CssSelect("div"); //all div elements
var nodes = html.CssSelect("div.content"); //all div elements with css class ‘content’
var nodes = html.CssSelect("div.widget.monthlist"); //all div elements with the both css class
var nodes = html.CssSelect("#postPaging"); //all HTML elements with the id postPaging
var nodes = html.CssSelect("div#postPaging.testClass"); // all HTML elements with the id postPaging and css class testClass
var nodes = html.CssSelect("div.content > p.para"); //p elements who are direct children of div elements with css class ‘content’
var nodes = html.CssSelect("input[type=text].login"); // textbox with css class login
We can also select ancestors of elements:
var nodes = html.CssSelect("p.para").CssSelectAncestors("div.content > div.widget");
參考文章:
HTML Agility Pack:簡單好用的快速 HTML Parser
開源項目Html Agility Pack實現快速解析Html
.Net解析html文檔類庫HtmlAgilityPack完整使用說明--采集軟件開發尤其好用
挖掘百度關鍵詞示例:BaiduTools.zip

