爬蟲技術 -- 進階學習(十)網易新聞頁面資訊抓取(htmlagilitypack搭配scrapysharp)

lmei發表於2014-04-13

最近在弄網頁爬蟲這方面的,上網看到關於htmlagilitypack搭配scrapysharp的文章,於是決定試一試~

於是到https://www.nuget.org/packages/ScrapySharp去看看,

看到這句下載提示:To install ScrapySharp, run the following command in the Package Manager Console

PM> Install-Package ScrapySharp

接下去我就去找package manager console,(http://docs.nuget.org/docs/start-here/using-the-package-manager-console

操作說明:From the Tools menu, select Library Package Manager and then click Package Manager Console.

發現還沒裝~@_@!!

那麼就去裝一下外掛吧!閱讀了這篇博文http://www.cnblogs.com/baiyu/archive/2011/09/07/2170028.html

一、 安裝Nuget

  1. Visual studio 2012-> Tool-> Extension Manager。

  2. 選擇Online Gallery,在右上角的搜尋中輸入Nuget,之後按提示安裝即可。

  3. 安裝之後選單View-> Other windows中會出現Package Manager Console, 這是一個整合到VS中的控制檯工具。

 

注意:在選擇ScrapySharp的版本的時候也要考慮htmlAgilityPack的版本 

附:scrapySharp官網連結:https://www.nuget.org/packages/ScrapySharp

於是,繼續操作Tools->Library Package Manager->Package Manager Console

 

PM> Install-Package HtmlAgilityPack
正在安裝“HtmlAgilityPack 1.4.6”。
已成功安裝“HtmlAgilityPack 1.4.6”。
正在將“HtmlAgilityPack 1.4.6”新增到 WindowsFormsDemo0320。
已成功將“HtmlAgilityPack 1.4.6”新增到 WindowsFormsDemo0320。
PM> Install-Package ScrapySharp
正在嘗試解析依賴項“HtmlAgilityPack (≥ 1.4.6)”。
正在安裝“ScrapySharp 2.2.63”。
已成功安裝“ScrapySharp 2.2.63”。
正在將“ScrapySharp 2.2.63”新增到 WindowsFormsDemo0320。
已成功將“ScrapySharp 2.2.63”新增到 WindowsFormsDemo0320。

 

接下來開始進行抓取,

原始網頁是網易一新聞網頁:http://news.163.com/14/0413/18/9PNVIBV000014JB6.html

下面實現的效果是,抓取title標籤的內容和正文內容(也就是<div id="endText">…(捕捉<p></p>中間的內容)…</div>)

捕捉title的時候需要注意,有時候一個網頁不只一對title標籤!!

 

但是,其實網易新聞頁面顯示的標題儲存的標籤<h1 id="hltitle">……</h1>

所以提取標題的核心程式碼為

String title = doc.DocumentNode.SelectSingleNode("//h1[@id='h1title']").InnerText;

 

捕捉正文內容的核心程式碼:

html.CssSelect("p").CssSelectAncestors("div#endText");

 

下面看下該新聞頁面正文部分的html程式碼:

<div id="endText"></p><p>人民網蘭州4月13日電 蘭州市今天下午召開新聞釋出會,初步查明瞭導致自流溝內水體苯超標的原因。根據環保專家現場初步分析判斷,周邊地下含油汙水是引起自流溝內水體苯超標的直接原因。</p><p>根據目前的調查情況初步判定,自流溝周邊地下含油汙水形成的原因有三點:一是原蘭化公司原料動力廠原油蒸餾車間R205A#渣油罐曾於1987年12月28日8時50分發生物理爆破事故,罐體破裂造成90立方渣油瀉出,其中有34噸渣油跑料未能回收,滲入地下;二是原蘭化公司原料動力廠原油蒸餾車間泵B-113出口總管曾於2002年4月3日發生開裂著火,洩漏的渣油及救火過程中產生的大量消防汙水滲入地下。</p><p>另據中新網蘭州4月13日電&nbsp; 蘭州市“4·11”區域性自來水苯指標超標事故應急處置領導小組副組長鄭志強13日說,調查組從11日下午3時開始展開調查工作,採取開挖深坑的方法,查詢到了導致水體苯超標的方位。根據環保專家現場初步分析判斷,周邊地下含油汙水是引起自流溝內水體苯超標的直接原因。</p><p>蘭州官方通報稱,根據目前的調查情況初步判定,自流溝周邊地下含油汙水的形成原因有兩個:</p><p>一是原蘭化公司原料動力廠原油蒸餾車間R205A#渣油罐(該址原為蘭化公司原料動力廠250萬噸/年煉油裝置,該裝置建於1982年,2003年停用,2006年拆除。拆除後,在原址建成現有的40萬噸/年芳烴抽提裝置,罐區設計分別儲存餾份油、輕油、渣油),曾於1987年12月28日8時50分發生物理爆破事故,罐體破裂造成90立方渣油洩出,其中有34噸渣油跑料未能回收,滲入地下。</p><p><!-- AD200x300_2 -->
<div class="gg200x300">
<iframe src="http://g.163.com/r?site=netease&affiliate=news&cat=article&type=logo300x250&location=13" width="300" height="250" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling="no"> </iframe>
</div><p>二是原蘭化公司原料動力廠原油蒸餾車間泵B—113出口總管曾於2002年4月3日發生開裂著火,洩漏的渣油(具體數量當時未統計)及救火過程中產生的大量消防汙水滲入地下。</p><p>鄭志強說,目前蘭州石化現有生產裝置及罐區執行正常,未發現物料及產品洩漏現象。生產區域內雨排井、化汙系統水封井未發現物料洩漏現象,消防井內發現有少量飄油。</p><p>事故調查組下一步調查工作的重點是,對從開挖深坑中提取的含油廢水組份進行化驗,進一步從技術層面核實地下含油汙水與自流溝內苯超標水體的關聯性。同時,對4號、3號自流溝內的具體洩漏點位進行實地勘查核實,並對造成區域性自來水苯超標事件的相關責任單位和責任人進行進一步的調查取證。(完)</p>
<div class="ep-source cDGray"> <span class="left"><a href="http://news.163.com/"><img src="http://img1.cache.netease.com/cnews/css13/img/end_news.png" alt="netease" width="13" height="12" class="icon"></a> 本文來源:人民網 作者:高翔、銀燕、苗亮軍</span> <span class="ep-editor">責任編輯:NN102</span>
</div> </div>

下面貼一下實現的核心程式碼(但是編碼處理部分程式碼沒有貼出)

新增 :using ScrapySharp.Extensions;

namespace HtmlAgilityDemo 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            var uri = new Uri("http://news.163.com/14/0413/18/9PNVIBV000014JB6.html"); 
            var browser1 = new ScrapingBrowser(); 
            var html1 = browser1.DownloadString(uri); 
            var doc = new HtmlDocument(); 
            doc.LoadHtml(html1); 
            var html = doc.DocumentNode;

            var title = html.CssSelect("title"); 
            foreach (var htmlNode in title) 
            { 
                Console.WriteLine(htmlNode.InnerText); 
            }

var ps = html.CssSelect("p").CssSelectAncestors("div#endText"); foreach (var htmlNode in ps) { Console.WriteLine(htmlNode.InnerHtml); } } } }

執行後輸出:

蘭州官方公佈自流溝周邊地下含油汙水形成原因_網易新聞中心
                
人民網蘭州4月13日電 蘭州市今天下午召開新聞釋出會,初步查明瞭導致自流溝內水體苯超標的原因。根據環保專家現場初步分析判斷,周邊地下含油汙水是引起自流溝內水體苯超標的直接原因。根據目前的調查情況初步判定,自流溝周邊地下含油汙水形成的原因有三點:一是原蘭化公司原料動力廠原油蒸餾車間R205A#渣油罐曾於1987年12月28日8時50分發生物理爆破事故,罐體破裂造成90立方渣油瀉出,其中有34噸渣油跑料未能回收,滲入地下;二是原蘭化公司原料動力廠原油蒸餾車間泵B-113出口總管曾於2002年4月3日發生開裂著火,洩漏的渣油及救火過程中產生的大量消防汙水滲入地下。另據中新網蘭州4月13日電&nbsp; 蘭州市“4·11”區域性自來水苯指標超標事故應急處置領導小組副組長鄭志強13日說,調查組從11日下午3時開始展開調查工作,採取開挖深坑的方法,查詢到了導致水體苯超標的方位。根據環保專家現場初步分析判斷,周邊地下含油汙水是引起自流溝內水體苯超標的直接原因。蘭州官方通報稱,根據目前的調查情況初步判定,自流溝周邊地下含油汙水的形成原因有兩個:一是原蘭化公司原料動力廠原油蒸餾車間R205A#渣油罐(該址原為蘭化公司原料動力廠250萬噸/年煉油裝置,該裝置建於1982年,2003年停用,2006年拆除。拆除後,在原址建成現有的40萬噸/年芳烴抽提裝置,罐區設計分別儲存餾份油、輕油、渣油),曾於1987年12月28日8時50分發生物理爆破事故,罐體破裂造成90立方渣油洩出,其中有34噸渣油跑料未能回收,滲入地下。<!-- AD200x300_2 --> 二是原蘭化公司原料動力廠原油蒸餾車間泵B—113出口總管曾於2002年4月3日發生開裂著火,洩漏的渣油(具體數量當時未統計)及救火過程中產生的大量消防汙水滲入地下。鄭志強說,目前蘭州石化現有生產裝置及罐區執行正常,未發現物料及產品洩漏現象。生產區域內雨排井、化汙系統水封井未發現物料洩漏現象,消防井內發現有少量飄油。事故調查組下一步調查工作的重點是,對從開挖深坑中提取的含油廢水組份進行化驗,進一步從技術層面核實地下含油汙水與自流溝內苯超標水體的關聯性。同時,對4號、3號自流溝內的具體洩漏點位進行實地勘查核實,並對造成區域性自來水苯超標事件的相關責任單位和責任人進行進一步的調查取證。(完)                                                                                                     本文來源:人民網  作者:高翔、銀燕、苗亮軍     
     責任編輯:NN102                                            

然後看下輸出,發現出現殘留【<!-- AD200x300_2 -->

部分註釋程式碼未被清除,那麼處理一下,

foreach (HtmlNode nodeScripte in node.Descendants("script").ToList())
{ nodeScripte.Remove(); }
foreach (HtmlNode nodeStyle in node.Descendants("style").ToList()) { nodeStyle.Remove(); } foreach (HtmlNode nodeComment in node.Descendants("//comment()").ToList()) { nodeComment.Remove(); }

 發現巢狀在其中的註釋標籤用上面的方法無法清除乾淨。

那麼採用下面方法,

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();
}

執行後發現,已經清除乾淨。

把所有的script、style標籤從dom樹中去掉(為了解決迭代器在工作時不能從集合中Remove元素的問題,使用ToArray()轉換為陣列再遍歷)。

HtmlAgilityPack是使用XPath語法,"//comment()"在XPath中表示“所有註釋節點”。

 

 【補充】獲取html中meta標籤中的content的內容

 

一些相關的語句:

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標籤。

4、其他:

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");

 

參考連結:

http://www.cnblogs.com/rupeng/archive/2012/02/07/2342012.html

http://www.cnblogs.com/cappuccino/p/3403495.html

http://www.cnblogs.com/dc-lancer/archive/2013/03/27/2985163.html

http://www.cnblogs.com/sswwsw/archive/2012/12/06/2805097.html

http://www.cnblogs.com/linfei721/archive/2013/05/08/3066697.html

http://www.cnblogs.com/cxlings/archive/2013/05/31/3110858.html

 

相關文章