Jumony是一套基于.NET Framework 3.5的HTML分析處理引擎,使得可以在C#中方便簡(jiǎn)單的操縱HTML文檔,同時(shí)也可以充當(dāng)Web的頁(yè)面引擎使用。
Jumony是一個(gè)開(kāi)源項(xiàng)目,已經(jīng)有三年的歷史了,在這三年中,秉承提供給.NET程序員完整的HTML掌控能力,Jumony歷經(jīng)無(wú)數(shù)次的改進(jìn),終于進(jìn)入了一個(gè)新的階段。Jumony Core 3是一個(gè)真正意義上的HTML引擎。
Jumony Core 3目前已經(jīng)在NuGet上發(fā)布,請(qǐng)直接在NuGet包管理器中搜索 Jumony Core ,即可下載。
項(xiàng)目地址:https://github.com/Ivony/Jumony
一、解析器
也許很多人會(huì)認(rèn)為,目前的HTML解析器已經(jīng)足夠了,甚至于簡(jiǎn)單的正則,也已經(jīng)可以滿足操縱HTML文檔的需求。是的,對(duì)于互聯(lián)網(wǎng)上絕大多數(shù)的HTML文檔,事實(shí)上都大部分滿足了XHTML的規(guī)范,對(duì)于它們的解析,并不需要多么強(qiáng)大的解析器。但是強(qiáng)大的解析器是一回事,而完美的解析器又是另一回事。
Jumony Core首先提供了一個(gè)近乎完美的HTML解析引擎,其解析結(jié)果無(wú)限逼近瀏覽器的解析結(jié)果。不論是無(wú)結(jié)束標(biāo)簽的元素,可選結(jié)束標(biāo)簽的元素,或是標(biāo)記屬性,或是CSS選擇器和樣式,一切合法的,不合法的HTML文檔,瀏覽器解析成啥樣,Jumony就解析成啥樣。也就是說(shuō),Jumony解析的結(jié)果,與瀏覽器解析的結(jié)果別無(wú)二致,讓你可以再也不用關(guān)心HTML文檔是否可以被識(shí)別,瀏覽器能看,Jumony就能解。
完美和強(qiáng)大只有一步之遙,但是完美的解析器可以讓你永遠(yuǎn)不用關(guān)心HTML源文檔。
以下是Jumony解析器所支持的特性不完全列表
特性 例子
孤立的<解析為文本 < a應(yīng)當(dāng)解析為< a
孤立的>解析為文本 <a>></a>應(yīng)當(dāng)解析為<a>></a>
標(biāo)記屬性(沒(méi)有值的屬性) <input type="text" checked />
元素丟失結(jié)束標(biāo)簽 <div><a href="test.html">測(cè)試鏈接</div>
可選結(jié)束標(biāo)簽元素
"body", "colgroup", "dd", "dt", "head", "html", "li", "option", "p", "tbody", "td", "tfoot", "th", "thead", "tr" <p>abc<p>123
無(wú)結(jié)束標(biāo)簽元素
"area", "base", "basefont", "br", "col", "frame", "hr", "img", "input", "isindex", "link", "meta", "param", "wbr", "bgsound", "spacer", "keygen" <img src="1.jpg">
CData元素 <script>if ( 1<a ) alert( "<div>" );</script>
"script", "style", "textarea", "title"
預(yù)格式化元素 <pre> 前面有空格</pre>
屬性值使用單引號(hào) <a href='#'>
屬性值使用雙引號(hào) <a href="#"
屬性值不使用引號(hào) <a href=#>
屬性值丟失(但有等號(hào)) <a href=>
屬性值前面有空格 <a href= "test.html">
解析HTML聲明 <!DOCTYPE html>
不僅僅是可以從文本中解析HTML,Jumony的API可以從互聯(lián)網(wǎng)上直接抓取文檔分析,并根據(jù)HTTP頭自動(dòng)識(shí)別編碼:
new JumonyParser().LoadDocument( "http://www.cnblogs.com/" ).Find( ".post_item a.titlelnk" )
而目前僅次于Jumony的HTML解析開(kāi)源項(xiàng)目HtmlAgilityPack早已停止了更新 ,這么多年過(guò)去了,對(duì)于最基本的<form>元素的解析都還存在問(wèn)題。
二、CSS樣式設(shè)置支持
僅僅只是完美解析HTML,并不能帶來(lái)多少好處,上面已經(jīng)說(shuō)過(guò),事實(shí)上大部分的HTML文檔,都可以用二流的解析器甚至是簡(jiǎn)單的正則表達(dá)式加以分析,那么為什么我們需要Jumony呢?
答案是一個(gè)HTML引擎不僅僅是解析DOM結(jié)構(gòu)這么簡(jiǎn)單。
考慮這樣的場(chǎng)景:我需要給一個(gè)元素的display樣式設(shè)置一個(gè)none值。在瀏覽器中,我們只需要簡(jiǎn)單的element.style.display = "none"便可以滿足我們的要求?,F(xiàn)在,通過(guò)解析器已經(jīng)得到了我們所需要的DOM,但設(shè)置樣式還需要進(jìn)行字符串的拼接么?
不需要,Jumony支持CSS樣式解析,甚至部分CSS樣式縮寫規(guī)則也能識(shí)別,在Jumony中,給元素設(shè)置一個(gè)樣式和在瀏覽器中一樣簡(jiǎn)單:
element.Style( "display", "none" )
我們?cè)賮?lái)看這樣的例子:<div style="padding: 5px"></div>,如果我們對(duì)這個(gè)元素設(shè)置padding-left: 0px會(huì)怎樣?
在Jumony中,結(jié)果會(huì)是:<div style="padding-left: 0px; padding-right: 5px; padding-top:5px; padding-bottom: 5px"></div>,看,padding屬性被神奇的自動(dòng)展開(kāi)了。
三、CSS 3選擇器支持
CSS選擇器是HTML世界通行的查詢語(yǔ)言,其簡(jiǎn)潔有力且被眾多瀏覽器支持。Jumony也支持幾乎完整的CSS3選擇器(除去運(yùn)行時(shí)偽類及偽對(duì)象)。借助選擇器,我們可以輕松的在HTML中找到我們感興趣的對(duì)象。例如抓取博客園首頁(yè)所有文章標(biāo)題:
new JumonyParser().LoadDocument( "http://www.cnblogs.com/" ).Find( ".post_item a.titlelnk" )
抓取,分析,選擇,一氣呵成,只需要簡(jiǎn)單的代碼,我們就能在控制臺(tái)輸出我們抓取到的數(shù)據(jù):
foreach( var title = new JumonyParser().LoadDocument( "http://www.cnblogs.com/" ).Find( ".post_item a.titlelnk" ) )
Console.WriteLine( title.InnerText() );
Jumony支持的CSS3選擇器列表:
選擇器 描述
* 選擇所有元素
p a 選擇子代元素
p>a 選擇子級(jí)元素
p+a 選擇相鄰元素
p~a 選擇后繼元素
[attr] 屬性存在選擇
[attr=value] 屬性值精確匹配
[attr~=value] 屬性值近似匹配
[attr^=value] 屬性值開(kāi)頭匹配
[attr*=value] 屬性值包含匹配
[attr$=value] 屬性值結(jié)尾匹配
[attr!=value] 屬性值否定匹配
:not 否定偽類
:only-child 唯一子元素偽類
:only-of-type 唯一類型偽類
:empty 空元素偽類
:nth-child 結(jié)構(gòu)化偽類
:nth-last-child 結(jié)構(gòu)化偽類
:nth-of-type 結(jié)構(gòu)化偽類
:nth-last-of-type 結(jié)構(gòu)化偽類
:first-child 結(jié)構(gòu)化偽類
:last-child 結(jié)構(gòu)化偽類
:first-of-type 結(jié)構(gòu)化偽類
:last-of-type 結(jié)構(gòu)化偽類
四、強(qiáng)大的可擴(kuò)展性
在Jumony Core 3,為用戶提供了最大的可擴(kuò)展性,你可以自定義HTML規(guī)范,實(shí)現(xiàn)自己的解析器,將其他DOM模型嫁接到Jumony API上,發(fā)明自己的CSS選擇器偽類,甚至于自己換一套API,例如jQuery風(fēng)格的。
Jumony Core擁有許多的衍生項(xiàng)目,例如爬取網(wǎng)站,提供jQuery風(fēng)格的 API、進(jìn)行網(wǎng)站開(kāi)發(fā)、制作MHT文件、為HAP的解析結(jié)果增加CSS選擇器支持等等,這些項(xiàng)目都得益于Jumony Core強(qiáng)大的可擴(kuò)展性,從而發(fā)揮出強(qiáng)大的功能。
Jumony也提供了一個(gè)快速上手的指南,幫助大家快速的熟悉Jumony:
http://demo.jumony.net/help?path=~%2fHelpEntries%2fQuickStart%2f
如你所見(jiàn),這個(gè)網(wǎng)站也是采用Jumony進(jìn)行驅(qū)動(dòng)的,它會(huì)檢索網(wǎng)站下所有的HTML頁(yè)面,并抽取頁(yè)面的標(biāo)題以及簡(jiǎn)介,形成導(dǎo)航目錄和概要頁(yè)面。
為了照顧沒(méi)有Visual Studio的同學(xué),這里提供一個(gè)壓縮包的下載:
http://files.cnblogs.com/Ivony/JumonyCore.3.0.5.2.zip
但使用Visual Studio開(kāi)發(fā)的最佳實(shí)踐是直接使用NuGet管理你所有的程序包。