向HtmlAgilityPack道歉:解析HTML還是你好用


去年寫過一篇文章《解析HTML最好的類還是微軟自己的》,回復中有朋友提到可以使用HtmlAgilityPack來進行HTML的解析。當時只是匆匆的測試了一下,發現HtmlAgilityPack得到的InnerText中有很多的不干凈的script、樣式內容,就斷定“不是很滿意,解析DiscuzNT!論壇的帖子頁面的時候有問題,沒法正確得到Body.InnerText的內容,有很多殘留html、js代碼夾雜在其中,解析的不是很好。”

 

如鵬網內部有一個工具是我開發的,其中的HTML解析部分就是我使用MSHTML完成的,但是今天發現這個軟件一個Bug,是MSHTML的HTMLDocumentClass在多線程並發時候有時候會造成死鎖。MSHTML是工作在UI線程中的(如果不把DesignMode設置為On,則HTML中的javascript會被執行就是證明),並不是一個干凈的、獨立的HTML解析組件,因此出現這樣的問題很難調試。因此決定還是換用向HtmlAgilityPack實現。


那么如何解決HtmlAgilityPack得到的InnerText中有殘留的script、樣式的問題呢,在google上搜索“HtmlAgilityPack script innerText”找到了stackoverflow上的這篇文章《C#: HtmlAgilityPack extract inner text》

代碼如下:

foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();

string innerText = doc.DocumentNode.InnerText;

 

原來這樣簡單呀,就是把所有的script、style標簽從dom樹中去掉(為了解決迭代器在工作時不能從集合中Remove元素的問題,使用ToArray()轉換為數組再遍歷)。

這樣操作發現還是有殘留的script:

<!--[if IE]>
<script language="JavaScript"> var objmain = document.getElementById("main"); function updatesize(){ var bodyw = window.document.body.offsetWidth; var w=(bodyw<=790?"790px":"100%"); objmain.style.width=w; } updatesize(); window.onresize = updatesize; </script>
<![endif]-->

 

仔細一看原來是帶條件注釋的script,因此用下面的方法去掉所有的注釋節點:

代碼如下:

foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();

foreach (var comment in doc.DocumentNode.SelectNodes("//comment()").ToArray())
comment.Remove();//新增的代碼

string innerText = doc.DocumentNode.InnerText;

 

解釋:HtmlAgilityPack是使用XPath語法,"//comment()"在XPath中表示“所有注釋節點”,關於XPath的詳細用法請參考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標簽。

 

經過這次使用HtmlAgilityPack得出結論:還是HtmlAgilityPack強大!!!再見MSHTML!

如鵬網.Net培訓班正在報名,有網絡的地方就可以參加如鵬網的學習,學完就能高薪就業,點擊此處了解

 

    三年前只要懂“三層架構”就可以說“精通分層架構”;現在則需要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值錢;

    三年前只要會SQLServer就可以說自己“精通數據庫開發”;現在則需還需要掌握MySQL等開源數據庫才能說是“.Net開源”時代的程序員;

    三年前只要會進行用戶上傳內容的安全性處理即可;現在則需要熟悉雲存儲、CDN等才能在雲計算時代游刃有余;

    三年前只要掌握Lucene.Net就會說自己“熟悉站內搜索引擎開發”;現在大家都用ElasticSearch了,你還用Lucene.Net就太老土了;

    三年前發郵件還是用SmtpClient;現在做大型網站發郵件必須用雲郵件引擎;

    三年前緩存就是Context.Cache;現在則是Redis、Memcached的天下;

    如鵬網再次引領.Net社區技術潮流!點擊此處了解如鵬網.Net最新課程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM