一 前言
前段時間一直在了解關於Http相關的知識,然后園子里時不時有園友發關於采集網頁信息的文章,然后自己也想試試如何做網頁的數據采集,便開始在網找查找相關資料,
方法有很多種,如 用開源的框架忘了叫什么名了,或者用.net Framework自帶的HttpwebRequest對象與HttpwebResponse對象,當然也還有其它對象也可以做到如 WebClient 等,而我選擇用HttpwebRequest 與HttpWebResponse來處理。
經過幾個晚上的不斷折騰終於把這東西折騰出來了,我的定位就只是用來練手所以不免會有BUG,這個小工具有兩個BUG 一個在無限滾動這里,都以經按插件的參數配置了,可它就是不聽使喚,老是會自動觸發加載事件,不得以我來個限定最多只加載10頁的數據。如果有熟悉這個插件的朋友,下載源碼后幫忙修改下,我拿它真沒折了.......先謝過了~~
第二個BUG在構造Http請求時有時正常,有時卻出現請求超時 比如我在家里測試時,都可以正常運行,而同樣的代碼放到公司時卻出現請求超時,這個問題真心不知道是什么原因引起的,
這是我寫的第二個小工具
第一個在這里 文件夾管理工具(MVC+zTree+layer)(附源碼)
本項目地址在這里 采集博客園文章工具
文章還涉及到正則表達示,我總結了一篇相關的文章
在這里 讀懂正則表達式就這么簡單
二 工具介紹與思路介紹
2.1工具截圖
效果大至就是這樣了,樣式什么的就沒細調了,大伙將就下吧,能看就行了,主要這段時間比較忙,所以匆匆收尾了,還望見諒
2.2 工具所用到插件
masonry:
是 一款非常強大的jQuery動態網格布局插件,可以幫助開發人員快速開發類似剪貼畫的界面效果。和CSS中float的效果不太一樣的地方在 於,float先水平排列,然后再垂直排列,使用Masonry則垂直排列元素,然后將下一個元素放置到網格中的下一個開發區域。這種效果可以最小化處理 不同高度的元素在垂直方向的間隙
infinitescroll
是一個無限循環滾動的插件,做自動分頁加載是很好用的,再配合masonry 瀑布流就可以達到 類似於QQ空間自動加載的效果,
三 開發思路
3.1 分析請求
先用Fiddler 抓取博客園的請求信息大至如下,因為只需要獲取文章的信息,不需要做其它操作,所以Cookies部分就可以不考慮,
只要把請求頭的相關信息Copy就行了然后添加到HttpWebRequest對象中
3.2 構造請求 並獲取響應信息
通過HttpWebRequest創建一個請求,然后添加請求頭信息,最后獲取請求的響應信息到HttpWebResponse對象中,並讀取出相應數據。
HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://www.cnblogs.com/"); request.Accept = "text/plain, */*; q=0.01"; request.Method = "GET"; request.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3"); request.ContentLength = 0; request.ContentType = "keep-alive"; request.Host = "www.cnblogs.com"; request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream responStream = response.GetResponseStream(); StreamReader reader = new StreamReader(responStream,Encoding.UTF8); string content = reader.ReadToEnd();
3.3 通過正則取文章基本信息
個人覺得最難的部分就在用正則匹配出指定數據,因為沒有接觸過正則,而且正則又不太容易理解,所以學習正則花了一部分時間,並把正則相關的知識總結成了一篇文章
讀懂正則表達式就這么簡單 感謝大家的支持。,這里只列取一部分,具體的項目中都有詳細的代碼
//取推薦 regex =new Regex( "<div class=\"digg\">.*<span.*>(?<digNum>.*)" + @"</span>" + ".*<div class=\"post_item_body\">", RegexOptions.Singleline); article.DiggNum = regex.Match(item.Value).Groups["digNum"].Value; //取文章標題 需要去除轉義字符 regex = new Regex("<h3>(?<a>.*)</h3>", RegexOptions.Singleline); string a = regex.Match(item.Value).Groups["a"].Value; regex = new Regex("<a\\s.*href=\"(?<href>.*?)\".*>(?<summary>.*)</a>", RegexOptions.Singleline); article.AritcleUrl = regex.Match(a).Groups["href"].Value; article.AritcleTitle = regex.Match(a).Groups["summary"].Value; //取作者圖片 先取html img標簽再取Src regex = new Regex("<a.*>(?<img><img[^>].*>)</a>", RegexOptions.Singleline); string img = regex.Match(item.Value).Groups["img"].Value; regex = new Regex(@"<img.*src=(?<path>.*)\s+.*/>", RegexOptions.Singleline); article.AuthorImg = regex.Match(img).Groups["path"].Value.TrimEnd('"').TrimStart('"');
3.4 把數據返回給插件Masonry
具體的參數配置官網都有詳細的解釋,這里就不詳細說了,
$('.container').masonry({ itemSelector: '.item', columnWidth: 230,//一列的寬度 Integer isAnimated: true,//使用jquery的布局變化 Boolean animationOptions: { Object :{ queue: false, duration: 500 } //jquery animate屬性 漸變效果 }, gutterWidth: 10,//列的間隙 Integer isFitWidth: true,// 適應寬度 Boolean isResizableL: true,// 是否可調整大小 Boolean isRTL: false,//使用從右到左的布局 Boolean });
3.5 通過infinitescroll自動加載數據
通過觸發這個插件infinitescroll的事件,來達到自動加載的效果,這里要注意的是自動加需要一個div 與a 標簽,div是分頁的容器初始化后會隱藏,而a標簽的href屬性則
是你要自動加載數據的地址,后面的參數 id=2 默認是從第二頁開始,會自動累加。剛開始自己在網上找資料時,沒人把這兩個元素寫出來,讓我糾結了好久,我說不給地址
怎么去哪自動加載去啊,找了好久終於讓我發現了.....
<div id="page-nav"> <a href="/GetArticle/GetArticles/?id=2"></a> </div>
template 的函數返回值就是自動加載后返回的數據可以在DataType屬性設定返回的數據格式,注意插件的最后一個回調函數 function (newElements) 要把新的數據添加進瀑布流的布局里就是在這里處理的, 這里的 newElements 其實就是template的返回值,也就是自動加載后重新拼裝的數據。
$('.container').infinitescroll({ navSelector: '#page-nav', nextSelector: '#page-nav a', //下一頁選擇器 itemSelector: ".item", //下一頁中需要被加載進當前頁的塊 extraScrollPx: 150,//滾動條距離底部多少像素的時候開始加載,默認150 animate: true, maxPage:10,//最大頁數 dataType: 'json', loading: { //加載效果 finishedMsg: 'No more pages to load', }, template: function (data) { //data表示服務端返回的json格式數據,這里需要把data轉換成瀑布流塊的html格式,然后返回給回到函數 var article = ''; for (var i in data) { article += "<li class='item'>" + "<a href=" + data[i].AritcleUrl + " target='_blank'><h3> " + data[i].AritcleTitle + "</h3></a>" + "<p>推薦<b> " + data[i].DiggNum + "</b> <a href=" + data[i].AuthorUrl + "><img src=" + data[i].AuthorImg + " alt='' /> </a></p>" + "<p style='text-indent: 2em'>" + data[i].AritcleSummary + "</p>" + "<p><a href=" + data[i].AuthorUrl + ">" + data[i].Author + "</a>" + data[i].PublishTime + "</p>" + "<p>" + data[i].CommentNum +" "+data[i].ReadNum + "</p></li>"; } return article; }, }, function (newElements) { //回調函數,用Masonry布局 // 當加載時隱藏所有新項目 var $newElems = $(newElements).css({ opacity: 0 }); // 現在可以顯示所有的元素 $newElems.animate({ opacity: 1 }); $('.container').masonry('appended', $newElems, true); } );
通過上面5步就可以把數據正常的加載出來,具體的細節部分喜歡的朋友可以下載源碼看看。
四 總結
每次接觸新的知識我都盡量會把所學的做一個工具出來,以加強自己的印象。我很享受從構思直到開發完成的這一個過程,在這個過程中收獲的東西也很多。
不僅了解了Http相關的知識,還學習了正則與瀑布流和無限滾動,我會繼續以這種方式一直走下去....
如果您覺得本文有給您帶來一點收獲,不妨點個推薦,為我的付出支持一下,謝謝~
如果希望在技術的道路上能有更多的朋友,那就關注下我吧,讓我們一起在技術的路上奔跑