網絡採集軟件核心技術剖析系列(2)---如何使用C#語言得到任意站點博文的正文及標題

一 本系列隨筆概覽及產生的背景css

本系列開篇受到你們的熱烈歡迎,這對博主是莫大的鼓勵,此爲本系列第二篇,但願你們繼續支持,爲我繼續寫做提供動力。html

本身開發的豆約翰博客備份專家軟件工具問世3年多以來,深受廣大博客寫做和閱讀愛好者的喜好。同時也不乏一些技術愛好者諮詢我,這個軟件裏面各類實用的功能是如何實現的。node

該軟件使用.NET技術開發,爲回饋社區,現將該軟件中用到的核心技術,開闢一個專欄,寫一個系列文章,以饗廣大技術愛好者。git

本系列文章除了講解網絡採編發用到的各類重要技術以外,也提供了很多問題的解決思路和界面開發的編程經驗,很是適合.NET開發的初級,中級讀者,但願你們多多支持。github

不少初學者常有此類困惑,「爲何我書也看了,C#相關的各個方面的知識都有所瞭解,但就是無法寫出一個像樣的應用呢?」,web

這其實仍是沒有學會綜合運用所學知識,鍛煉出編程思惟,創建起學習興趣,我想該系列文章也許會幫到您,希望如此。chrome

開發環境:VS2008數據庫

本節源碼位置:https://github.com/songboriceboy/GetWebContent編程

源碼下載辦法:安裝SVN客戶端(本文最後提供下載地址),而後checkout如下的地址:https://github.com/songboriceboy/GetWebContent瀏覽器

系列文章提綱以下:

二 第二節主要內容簡介(如何使用C#語言得到任意站點博文的正文及標題)

使用C#語言得到任意站點博文的正文及標題的解決方案演示demo以下圖所示:可執行文件下載

 

三 基本原理

 要想獲取任意網頁文章的正文及標題,咱們除了要利用上一節提到的HtmlAgilityPack.dll程序集以外,還要藉助於另一個實用的程序集Fizzler.dll(http://fizzlerex.codeplex.com/)

HtmlAgilityPack是經過xpath來解析html元素,相對來講仍是稍微麻煩些;Fizzler提供了相似css選擇器的方式來解析html元素,很是符合咱們的習慣。

一般對於某篇文章,咱們只想保留文章的正文(去掉廣告,側邊欄等四周的網頁佈局元素),接下來,咱們就來看一下操做步驟,這裏咱們須要藉助一下強大的瀏覽器工具。

1.使用firefox瀏覽器或chrome瀏覽器打開咱們想要提取正文的網頁,firefox要安裝firebug插件,chrome直接按F12,這裏咱們以firefox舉例:

好比,打開咱們上一節的博文(http://www.cnblogs.com/ice-river/p/4110799.html),以下圖所示:

首先右上角的小蟲子圖標在咱們安裝完firebug插件後出現,點擊它,瀏覽器下端彈出調試界面,在調試界面中,點擊我紅線框起來的圖標(一藍色方框,上面有個箭頭),此時你會發現網頁中的各個元素都變爲可框選的,咱們框選正文以後,會發如今下面的調試界面對應的div元素被高亮選中,咱們對該div元素(博客園這裏是div#cnblogs_post_body)右鍵,彈出右鍵菜單,以下圖所示:

 咱們點擊[複製css路徑菜單項],此時咱們粘貼板中就獲得了正文的css路徑[html body div#home div#main div#mainContent div.forFlow div#topics div.post div.postBody div#cnblogs_post_body]

對於Fizzler來講,咱們只須要提供最後部分的div#cnblogs_post_body便可(你們記住,咱們只須要從得到的css路徑長字符串中從後往前看,拿到最後一個空格以後的字符串,這裏是div#cnblogs_post_body

把這個字符串填入到咱們demo的[正文css路徑]部分,以下圖所示:

其實對應於Fizzler來說,只需一行代碼:

   IEnumerable<HtmlNode> NodesMainContent = htmlDoc.DocumentNode.QuerySelectorAll(this.textBoxCssPath.Text);

是否是很簡單?

對於其餘技術博客,你們能夠自行練習,檢驗是否理解了我上面所說的方法,這裏給出幾個常見技術博客的正文Css路徑答案:

  站點        --->  CSS路徑
"Cnblogs"    ---> "div#cnblogs_post_body"
"Csdn"        ---> "div#article_content.article_content"
"51CTO"        ---> "div.showContent"
"Iteye"        ---> "div#blog_content.blog_content"
"ItPub"        ---> "div.Blog_wz1"
"ChinaUnix" ---> "div.Blog_wz1"

 好了,回過頭來咱們講講本節demo中的重點代碼:

獲取博客正文標題:

private void GetTitle()
        {
            string strContent
                = m_wd.GetPageByHttpWebRequest(this.textBoxUrl.Text, Encoding.UTF8);
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument
            {
                OptionAddDebuggingAttributes = false,
                OptionAutoCloseOnEnd = true,
                OptionFixNestedTags = true,
                OptionReadEncoding = true
            };

            htmlDoc.LoadHtml(strContent);
            string strTitle = "";
            HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//title");
            // Extract Title
            if (!Equals(nodes, null))
            {
                strTitle = string.Join(";", nodes.
                    Select(n => n.InnerText).
                    ToArray()).Trim();
            }
            strTitle = strTitle.Replace("博客園", "");
            strTitle = Regex.Replace(strTitle, @"[|/\;:*?<>&#-]", "").ToString();
            strTitle = Regex.Replace(strTitle, "[\"]", "").ToString();
            this.textBoxTitle.Text = strTitle.TrimEnd();
        }

主要流程是首先用咱們上一節給出的 WebDownloader類獲取到網頁的源代碼,而後經過下面一行代碼獲取網頁標題:

 HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//title");

這裏的藉助了HtmlAgilityPack的SelectNodes函數提取網頁中的title元素,注意通常的格式良好網頁都具備title元素,由於這樣方便搜索引擎索引收錄咱們的文章,下圖解釋下什麼是title元素

你們注意上圖,我用紅筆圈出的2個地方,應該不言自明瞭吧,不解釋。

獲取博客正文內容:

  private void GetMainContent()
        {
            string strContent
                = m_wd.GetPageByHttpWebRequest(this.textBoxUrl.Text, Encoding.UTF8);
            HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument
            {
                OptionAddDebuggingAttributes = false,
                OptionAutoCloseOnEnd = true,
                OptionFixNestedTags = true,
                OptionReadEncoding = true
            };

            htmlDoc.LoadHtml(strContent);

            IEnumerable<HtmlNode> NodesMainContent = htmlDoc.DocumentNode.QuerySelectorAll(this.textBoxCssPath.Text);

            if (NodesMainContent.Count() > 0)
            {
                this.richTextBox1.Text = NodesMainContent.ToArray()[0].OuterHtml;
                this.webBrowser1.DocumentText = this.richTextBox1.Text;
            }
        }

很簡單就是調用htmlDoc.DocumentNode.QuerySelectorAll函數,參數傳入咱們上面講到的正文div的css路徑,最後NodesMainContent.ToArray()[0].OuterHtml中保存的就是網頁正文內容的源代碼,放到richTextBox1.Text裏顯示html源代碼,放到webBrowser1.DocumentText裏顯示網頁內容。 

四 下節預告

網頁的抓取主要分爲3步:

1.經過分頁連接抓取到所有文章連接集合(第一節內容)

2.經過每個文章連接獲取到文章的標題及正文(本節內容)

3.從文章正文中解析出所有圖片連接,並將文章的所有圖片下載到本地(下節內容)

這3步有了,以後你就想怎麼折騰就怎麼折騰了,各類加工處理,生成pdf,chm,靜態站點,遠程發佈到其餘站點等等(請繼續關注本系列文章,並不吝點一下推薦,您的支持是我寫做的最大動力)。

做者: 宋波
出處: http://www.cnblogs.com/ice-river/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。
正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!
相關文章
相關標籤/搜索