使用nodejs抓取博客園內容---Promise模塊探索


最近在學習NodeJs。從nodejs語言本身,看了朴靈的《深入淺出NodeJs》,《Node即學即用》。個人感覺朴靈的這本書適合node入門后乃至中級程序員去閱讀。而后者則可以完全當做初級入門教材使用。當然我認為最快捷的學習路徑是看視頻。這里推薦  慕課網的node視頻,講的還是非常不錯的。雖然說nodej是Javascript在服務端的一種表現,嚴格來說算不上說是一種新的語言。連官方也說,其強大的性能來源於google的v8引擎。換句話說,以前Javascript在客戶端的瀏覽器里運行。PC機器為瀏覽器預留了一大塊內存空間,在瀏覽器建立了一個JavaScript解釋器,也就是V8引擎。只是Ryna Dahl把這個引擎移動到了服務端。

了解完這個這個前提之后,就能揭開NodeJs的神秘面紗了。至於NodeJs於JavaScript在表現上有何異同,大家可以去參考相對基礎的文章去了解基礎知識。如果JavaScript還不太了解,還是建議閱讀《JavaScript權威指南》(犀牛書雖然特別大部頭,但是讀起來特別爽快,就好像Javascipt大牛跟你面對面交流似得,好像他就知道你這里不懂,真是貼心到想哭)。學完了nodejs和一些核心包,以及數據庫框架,終於准備動手做一些東西了。在做的過程中也對nodejs有了更深的了解,其中最大的坑也就是nodejs的異步執行,這也是nodejs的最大特點。后來了解到Promise這個Es6的新特性。可以讓代碼的流程執行的更加清晰明了。

推薦http://www.cnblogs.com/lvdabao/p/es6-promise-1.html

下面是使用nodejs抓取博客園前10頁所有的文章標題和文章對應的鏈接。代碼中有詳細注釋,有問題的可以評論區討論。

  1 var http = require('http');   //引入nodejs的http模塊,該模塊用於構建http服務和作為HttpClient使用。
  2 var promise = require('promise'); //對異步編程進行流程控制,更加符合后端程序員的編程習慣。
  3 var cheerio = require('cheerio'); //可以理解為服務端的Jquery。使用方法和客戶端一樣。
  4 
  5 var url = 'http://www.cnblogs.com/#p'; //要抓取的網址。博客園的頁數是通過添加錨點的,后面有拼接
  6 
  7 
  8 //Promise 在任何情況下都處於以下三種狀態中的一種:
  9 //未完成(unfulfilled)、已完成(resolved)和拒絕(rejected)
 10 //事件已完成則使用成功的callback(resolve)返回自身,失敗了則
 11 //選擇使用callback(reject)來返回失敗的自身。
 12 
 13 function getPageList(url){
 14     //return Promise對象
 15     return new Promise(function(resolve,reject) {
 16         http.get(url,function(res) {
 17             var body = '';
 18 
 19             //當接受到數據的時候,http是執行范圍請求的。所以每個范圍請求就是一個chunk。
 20             res.on('data', function(chunk) {
 21                 //buffer是一種node處理二進制信息的格式,不必理會。
 22                 res.setEncoding('utf8'); //設置buffer字符集
 23                 body += chunk;           //拼接buffer
 24             });
 25 
 26             //當整個http請求結束的時候
 27             res.on('end', function() {
 28                 var $ = cheerio.load(body);  //將html變為jquery對象。
 29                 var articleList = $('.post_item');
 30                 var  articleArr = [];
 31                 articleList.each(function() {
 32                     var curEle = $(this);
 33                     var title  = curEle.find('.post_item_body h3').text();  //獲取標題
 34                     var href = curEle.find('.post_item_body h3 a').attr('href'); //文章鏈接
 35                     articleArr.push({
 36                         title:title,
 37                         href:href
 38                     });
 39                    
 40 
 41                 });
 42                 
 43                 //成功的狀態使用resolve回調函數。
 44                 resolve(articleArr);
 45 
 46             });
 47 
 48             //當執行http請求失敗的時候,返回錯誤信息
 49             res.on('error', function(e) {
 50                 reject(e.message);
 51             });
 52 
 53 
 54 
 55         })
 56     })
 57 }
 58 
 59 
 60 //請求博客園前10頁的數據。將所有的請求預先放置在集合內。
 61 var list = [];
 62 for(var i=1;i<=10;i++) {
 63     var url = url+i;
 64     list.push(getPageList(url));
 65 
 66 }
 67 
 68 //調用Promise的下面的all方法。參數是一個事件集合。
 69 //Promise將會進行異步執行。但是最后的返回時機要根據最耗時的那個請求為標准。
 70 //then(),可以接受兩個參數(callback).第一個參數是成功(resolved)的回調。
 71 //第二個參數是執行上個操作失敗(rejected)的回調。
 72 Promise
 73     .all(list)
 74     .then(function(data) {
 75         console.dir(data);
 76     })

 以下是結果:

 

 

 

此前工作繁忙,這段時間空下來了。從今天起,將會陸續介紹nodejs或者是其他方面的東西。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM