nodeJs初體驗——爬蟲

一,緣起

因爲菩提眼網站(http://www.putiyan.com)的搭建,須要將菩提眼新浪微博上(http://blog.sina.com.cn/baoqie)的內容遷移過來。html

二,首先,搭建nodejs環境。

能夠去nodejs官網來下載nodejs並安裝http://nodejs.cn/node

三,其次,搭建html靜態服務器。

經過npm安裝http模塊 npm install httpjquery

var http = require("http");
  http.createServer(function(req, res){
       // 設置字符編碼(去掉中文會亂碼)
      res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
      res.write('hello nodeJs');
      res.end();
  }).linsten(3000);

四,安裝爬蟲依賴(superagent超級代理,cheerio,eventproxy事件代理服務器,async異步流程控制,fs(File System))

安裝 npm install superagent; npm install cheerio; npm install eventproxy;
npm install async; npm install fs;npm

var http       = require("http"),
    fs            = require('fs'),
    superagent = require("superagent"),
    cheerio    = require("cheerio"),
    async      = require("async"),
    eventproxy = require('eventproxy');

var ep             = new eventproxy(),
    catchFirstUrl = 'http://www.cnblogs.com/',  //入口頁面 
    pageNum       = 16, //要爬取文章的頁數
    pageUrls       = [],  //存放收集文章頁面網站    
    startDate     = new Date(), //開始時間
    endDate       = false;  //結束時間
    blogArrs       = {
                    "title": "",
                    "content": "",
                    "time": ""
                  },
      blogArrs = [];


//存儲須要的爬的列表頁面
for(var i=11 ; i<= 16 ; i++){
    pageUrls.push('http://blog.sina.com.cn/s/articlelist_1392517237_0_' + i + '.html');
}
// 主start程序
function start(){
    function onRequest(req, res){
        // 設置字符編碼(去掉中文會亂碼)
        res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
        // 當全部 'BlogArticleHtml' 事件完成後的回調觸發下面事件
        ep.after('BlogArticleHtml', pageUrls.length*20, function(articleUrls){
          
              // 獲取 BlogPageUrl 頁面內全部文章連接
             for(var i = 0 ; i < articleUrls.length ; i++){
                res.write(articleUrls[i] +'<br/>');  
            } 

            console.log('articleUrls.length is'+ articleUrls.length +',content is :'+articleUrls);

            // 控制併發數
            var curCount = 0;
            var reptileMove = function(url,callback){
                // 延遲毫秒數
                var delay = parseInt((Math.random() * 30000000) % 1000, 10);
                curCount++;
                console.log('如今的併發數是', curCount, ',正在抓取的是', url, ',耗時' + delay + '毫秒');  
                  
                superagent.get(url)
                .end(function(err,sres){
                    // 常規的錯誤處理
                    if (err) {
                    console.log(err);
                    return;
                    }       

                    //sres.text 裏面存儲着請求返回的 html 內容
                    var $ = cheerio.load(sres.text);                

                    blogArr = {
                        "title": $('.titName').html(),
                        "content": $('.articalContent').html(),
                          "time": $('.articalTitle').find('.time').html().replace('(','').replace(')','')
                    }
                    
                    blogArrs.unshift(blogArr);
                });

                setTimeout(function() {
                    curCount--;
                    callback(null,url +'Call back content');
                }, delay);    
            };

            // 使用async控制異步抓取  
            // mapLimit(arr, limit, iterator, [callback])
            // 異步回調
            async.mapLimit(articleUrls, 5 ,function (url, callback) {
                  reptileMove(url, callback);
            }, function (err,result) {
                endDate = new Date();

                console.log('final:');
                console.log(result);                

                for(var i = 0; i < blogArrs.length; i++){
                    // 生成所須要的html代碼
                      var blogHtml = '<item>'
                                  +'<title>' + blogArrs[i].title +'</title>'
                                  +'<pubDate>Thu, 28 Apr 2016 11:17:16 +0000</pubDate>'
                                  +'<dc:creator><![CDATA[admin]]></dc:creator>'
                                  +'<content:encoded><![CDATA['+ blogArrs[i].content +']]></content:encoded>'
                                  +'<wp:post_date><![CDATA['+ blogArrs[i].time +']]></wp:post_date>'
                                  +'<wp:comment_status><![CDATA[open]]></wp:comment_status>'
                                  +'<wp:ping_status><![CDATA[open]]></wp:ping_status>'
                                  +'<wp:post_name><![CDATA[70]]></wp:post_name>'
                                  +'<wp:status><![CDATA[publish]]></wp:status>'
                                  +'<wp:post_type><![CDATA[post]]></wp:post_type>'
                                  +'<wp:post_password><![CDATA[]]></wp:post_password>'
                                  +'<wp:is_sticky>0</wp:is_sticky>'
                                 +'</item>';

                    // 往result.html中追加生成的代碼
                    fs.appendFile('result.html', blogHtml, function () {
                        console.log('追加內容完成');
                    });
                }

                res.write(''+ blogHtml)
                


            //統計結果
            res.write('<br/>');
            res.write('<br/>');
            res.write('/**<br/>');
            res.write(' * 爬蟲統計結果<br/>');
            res.write('**/<br/>');
            res.write('一、爬蟲開始時間:'+ startDate +'<br/>');
            res.write('二、爬蟲結束時間:'+ endDate +'<br/>');
            res.write('三、耗時:'+ (endDate - startDate) +'ms' +' --> '+ (Math.round((endDate - startDate)/1000/60*100)/100) +'min <br/>');
            res.write('四、爬蟲遍歷的文章數目:'+ pageNum*20 +'<br/>');
          });
        });
        
        // 輪詢 全部文章列表頁
        pageUrls.forEach(function(pageUrl){
            superagent.get(pageUrl)
            .end(function(err, pres){
                console.log('fetch ' + pageUrl + ' successful');
                res.write('fetch ' + pageUrl + ' successful<br/>');

                  // 常規的錯誤處理
                if (err) { console.log(err); }

                // pres.text 裏面存儲着請求返回的 html 內容,將它傳給 cheerio.load 以後
                // 就能夠獲得一個實現了 jquery 接口的變量,咱們習慣性地將它命名爲 `$`
                // 剩下就都是 jquery 的內容了
                var $ = cheerio.load(pres.text);
                var curPageUrls = $('.articleCell');
                for(var i = 0 ; i < curPageUrls.length ; i++){
                    var articleUrl = curPageUrls.eq(i).find('a').attr('href');
                    // 至關於一個計數器
                    ep.emit('BlogArticleHtml', articleUrl);
                }
            });
        })
    }

    http.createServer(onRequest).listen(3000);
}

exports.start= start;
相關文章
相關標籤/搜索