如何使用 C# 爬蟲得到專欄博客更新排行

昨天,夢姐問咱們,她存在一個任務,找到 關注數排行100 和 瀏覽量排行100 的專欄博客,在2017年還有更新的專欄。javascript

夢姐說他要出去一趟,M大神在吃飯,因而我估算時間,只有半個鍾。html

整理一下:半個鍾時間,找到兩個表格中,在2017年更新的專欄。這就是需求。java

<!--more-->

我開始分開需求,第一步,讀取數據,讀取兩個表的數據。第二步獲取博客更新時間,博客更新時間就是最近的文章的發佈時間。第三步,把結果寫到文件裏。web

開始由於xlsx的讀取問題卡了我一下,我計算了,讀取excel的方法,我須要20分鐘寫完,而把excel轉換爲csv讀取,我只要1分鐘,因而我就把excel格式換爲csv。sql

到這裏,預處理就作完了。markdown

我須要定義一個數據結構,用來存儲數據。數據結構

存儲從表格讀取到的數據,須要看一下表格存在哪些數據。app

因而我定義一個類ide

由於不知道專欄做家叫什麼,因而我就把這個類叫專家函數

class Proficient 
    {
        /// <summary>
        /// 標題
        /// </summary>
        public string Title
        {
            get; set;
        }
        /// <summary>
        /// 網址
        /// </summary>
        public string Url
        {
            get; set;
        }

        /// <summary>
        /// 最後更新時間
        /// </summary>
        public string Date
        {
            get; set;
        }
    }

須要讀取的數據有 標題 和 網址,時間是須要進行計算。標題的做用是去重,網站是輸入。可是表格還有其餘內容,因而隨意添加兩個屬性把他放進去。

接下來,如何從一個博客專欄網站讀取到最新更新的博客?

我這裏使用 HtmlAgilityPack 幫助解析網頁。

HtmlAgilityPack 是一個強大的東西,使用的方法是從nuget搜索一下,就能夠獲得他。

安裝進去,就可使用了。

因而我寫了一個函數 static void GetDate(Proficient proficient)用於讀取時間。

獲取網址:var url = proficient.Url;

獲取到了網址,就能夠獲取網頁。

獲取網頁的方法請看代碼

HtmlWeb web = new HtmlWeb();
            HtmlDocument doc = web.Load(url);

經過查看csdn的代碼,能夠知道存放博客的是 detail_list

如何從 HtmlAgilityPack 獲取指定的 class ?

由於有xpath的存在,使用 xpath 就能夠指定 class ,xpath 是和正則差很少的東西。

關於 xpath ,請看C#+HtmlAgilityPack+XPath帶你採集數據(以採集天氣數據爲例子) - 數據之巔 - 博客園

看到detail_list前面是 ul 因此 xpath能夠這樣寫

var temp = doc.DocumentNode.SelectNodes("//ul[@class='detail_list']/li");

其中的//就是從網頁任意位置

ul就是標籤,指定哪一個標籤,以後就是標籤是否存在屬性,這裏指定屬性是 class ,看起來很簡單。那麼後面的/li就是路徑,其實知道一個元素在哪,能夠直接用路徑來寫。

可是我發現,其實找到detail_b更快

下面就是專欄的代碼,能夠看到時間使用的 class 是detail_b

<ul class="detail_list">
                <li>
                  <h4><a href="http://blog.csdn.net/lindexi_gd/article/details/52041944" target="_blank">win10 uwp 入門</a></h4>
                  <p class="detail_p">UWP是什麼我在這裏就不說,本文主要是介紹如何入門UWP,也是合併我寫的博客。</p>
                  <div class="detail_b"><span>2016-07-27 08:55</span>
                    <div class="fa fa-eye"></div><em>2752</em>
                  </div>
                </li>

因而把代碼改成

temp = doc.SelectNodes("//div[@class='detail_b']");

和上面同樣,只是這裏使用的是div,接下來就是拿到時間。

去掉html以後的文本就是時間

因而拿到第一個的時間就是博客的更新時間了,可能有些大神排序不是按照時間排的,可是這裏不處理。

如何獲取文本?請看代碼

proficient.Date = temp.Elements().FirstOrDefault().InnerText;

這樣就是獲取到了日期了,由於存在一些時間是 昨天 9:00的,我就沒轉換了

日期獲取完成,就是寫入文件,寫入的文件很簡單,直接放代碼

private static void Write(List<Proficient> proficient)
        {
            string file = "E:\\專欄排行\\csdn排行100.csv";
            using (StreamWriter stream=new StreamWriter(new FileStream(file,FileMode.Create),Encoding.GetEncoding("gbk")))
            {
                foreach (var temp in proficient)
                {
                    stream.WriteLine(temp.Title+","+temp.Url+","+temp.Date+","+temp.Folpv+","+temp.Num);
                }
            }
        }

須要改進的:

使用命令行指定讀取文件,判斷博客最新的日期,不可使用第一篇博客。

去重不可使用博客專欄標題,由於存在重複。

若是你們有寫質量高的文章,想推薦到csdn首頁,能夠聯繫我哦……我會在夢姐面前多多美言

2017 CSDN博客專欄評選

參見:使用HtmlAgilityPack XPath 表達式抓取博客園數據 - 曉風拂月 - 博客園
Html Agility Pack基礎類介紹及運用 - itmuse - 博客園

知識共享許可協議
本做品採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。歡迎轉載、使用、從新發布,但務必保留文章署名林德熙(包含連接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的做品務必以相同的許可發佈。若有任何疑問,請與我聯繫

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
相關文章
相關標籤/搜索