1. 程式人生 > >編寫windows服務 定時爬取部落格園文章 郵件提醒以及入庫

編寫windows服務 定時爬取部落格園文章 郵件提醒以及入庫

這段時間工作比較忙,每天也沒那麼多的時間逛部落格園看文章,於是就想寫一個工具 每天早上9點爬取文章給自己發郵件

作為每天的技術早餐。

相對而言,爬取部落格園的文章還是比較簡單的,主要思路就是分析部落格園文章列表的分頁,請求方式,頁面渲染方式等,

寫篇隨筆簡單share一下。

這個小工具主要用到的由nlog、HtmlAgilityPack、ef、quartz.net 。

首先就是分析文章列表以及分頁,當對文章列表切換頁碼的時候,

url是這種形式: https://www.cnblogs.com/#p3

p1 p2 p3 ...p(n) 剛開始我也是以為列表分頁是靠這種形式走的,在url中傳頁碼引數,用.net 的httpclient請求了幾十頁,

發現返回內容都是一樣的,這是一個坑,接著分析,F12分析一下,切換頁碼的時候發現是一個post請求,

請求地址為:

https://www.cnblogs.com/mvc/AggSite/PostList.aspx

 

分析下請求引數,

 

CategoryId、CategoryType、ItemListActionName、PageIndex、ParentCategoryId、TotalPostCount

對每個引數的具體意義不做過多分析,pageindex就是頁碼,因此文章列表在分頁的時候,請求地址為

https://www.cnblogs.com/mvc/AggSite/PostList.aspx

傳遞引數如:{"CategoryType":"SiteHome","ParentCategoryId":0,"CategoryId":808,"PageIndex":4,"TotalPostCount":4000,"ItemListActionName":"PostList"}

按照此地址以及引數請求一下,確定能夠返回期望結果,讓人不舒服的地方又來了,返回結果非json 而是當前頁面的html 。

 

至此,分頁請求方式已經解決了,下一步就是處理請求結果,獲取請求頁的文章列表內容。

因為返回結果是html 我們首先看下文章列表頁:

在此列表內,我們能獲取到的資訊 有標題、作者、釋出 時間、摘要,一般爬蟲返回結果為json、html、xml等

部落格園返回結果為html,我們可以通過正則表示式去處理,Regex,也可以通過xpath去處理,因為返回結果就是一個html dom樹,

我們可以通過xpath語法去處理 http://www.w3school.com.cn/xpath/xpath_syntax.asp

同時,我們也可以F12 Elements選項下 選擇對應文章標題 右鍵copy  xpath 

 比如某一標題的xpath為  //*[@id="post_list"]/div[1]/div[2]/h3/a 

 相應的c#中 可以使用HtmlAgilityPack 這個工具來進行解析,程式碼如下:

 

                    HtmlDocument htmlDocument = new HtmlDocument();
                    htmlDocument.LoadHtml(html);
                    HtmlNodeCollection postItems = i == 1 ? htmlDocument.DocumentNode.SelectNodes("//*[@id='post_list']/*") : htmlDocument.DocumentNode.SelectNodes("./div");

                    foreach (HtmlNode item in postItems)
                    {
                        var titleNode = item.SelectSingleNode("./*/h3");
                        var footNode = item.SelectSingleNode("./*/div[@class='post_item_foot']");
                        if (Articles.Any(c => c.Title == titleNode.InnerText)) continue; Articles.Add(new Article { Title = titleNode.InnerText, ItemUrl = titleNode.FirstChild.Attributes["href"].Value, Sumary = item.SelectSingleNode("./*/p").InnerText, Author = footNode.SelectSingleNode("./a").InnerText, PubDate = footNode.SelectSingleNode("./text()[2]").InnerText.Replace("釋出於", "").Trim() }); }


 

其中的html就是當前列表的html內容,程式碼可自行寫。Article為自定義的實體類 

到這一步,文章的簡單資訊獲取到了 url 標題 作者 釋出時間 摘要

下一步就是獲取文章的內容

比如某一文章的url為,https://www.cnblogs.com/senlinmu/p/9805684.html

文章詳情仍然採用HtmlAgilityPack

                Articles.ForEach(v =>
                {
                    string html = client.GetStringAsync(v.ItemUrl).Result;
                    htmlDocument.LoadHtml(html);
                    HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//*[@id='cnblogs_post_body']");
                    v.Content = htmlNode?.InnerHtml;
                });

html為文章詳情,此xpath為 //*[@id='cnblogs_post_body']

至此,文章的標題、時間、摘要、內容獲取完畢。

然後就可給自己發郵件提醒。

獲取內容大致完成,下一步就是部署成windows服務 ,