Nodejs,不一樣的爬蟲實踐

linjiazhen 9年前發布 | 13K 次閱讀 Node.js Node.js 開發

來自: http://www.famanoder.com/bokes/56b0ff763b9d992825f0a1bb

做前端以來,對我成長幫助最大的恐怕也就是各位大俠們的博客了, ,慢慢的也在我心里種下了顆種子:我也要寫博客!哪怕我文筆差,技術菜,難以望其項背,我也要追隨大神們的腳步,寫寫博客,處處留香。摸爬滾打,終是成長;學習分享,與君共勉!小前端初學Nodejs,搭了個 簡單的博客 ,捉襟見肘,望大俠路過指導!好了,此處有廣告之嫌,進入正題。

關于Nodejs的爬蟲程序,百度一大把,是的,我也是百度到的,然后到github上看了看cheerio模塊;乍一看,這不就是Jquery嘛,沒想到Jquery都能牛到后端操作DOM了啊,恩。。。可以先這么認為和理解吧,因為cheerio確實可以像jquery操作DOM一樣操作從遠程爬取過來的頁面;頓時邪念四起:我要把我喜歡的博客全抓到我的博客站點上去、我要不KX上網而是把谷歌抓過來訪問。。。然后就有了我博客上的 “爬呀爬” 版塊,都是爬取的國內頂尖的前端團隊嘔心瀝血寫的博客, ,保留了作者信息和版權,當然,如果他們看到了,罵我一頓,叫我刪掉,我肯定會屁顛屁顛刪掉的;

還有就是怎么通過我的站點訪問谷歌了,比如:http://www.famanoder.com?url=http://google.com的請求,我res.send(googleBody);恩 ,這樣是可以的,可是問題在于:相對路徑的資源返回404了,因為相對路徑域名取的是我的站點,而我的站點沒有對應的目錄和資源,自然404了;這時cheerio可就很有用了,在res.send之前可以對body進行些DOM操作啊,貌似有點復雜啊,我正則還不行。。。為了讓爬取過來的谷歌可以點擊,鏈接沒有404,還需要做一步,就是通過cheerio將所有相對路徑補上http://www.famanoder.com?url=http://google.com,絕對路徑補上http://www.famanoder.com?url=來將爬取的目標站點所有資源都通過我的博客站點請求;

很高興,一個小小的爬蟲讓我我又知道了三個很好用的模塊:request、superagent、cheerio

request和superagent差不多,過年后做個橫向的比較,爭取進一步理解http模塊;

先看看request怎么抓頁面的吧,江湖中人不多廢話了,看代碼:

if (req.query.url) {
        var iurl = decodeURIComponent(req.query.url);
        var thaturl = url.parse(iurl).protocol +url.parse(iurl).host;
        var body=[],size=0;
        request.get({
          url: iurl,
          headers: {

      }
    })
    .on('response', function (response) {
      res.set(response.headers);
      response.setEncoding='utf8';
      response.on('data',function(chunk){
        body.push(chunk);
        size+=chunk.length;
      });
    })
    .on('error', function (err) {
      console.log(err);
    })
    .on('end',function(){

//buffer 防止丟包的情況,如果數據過多,會抓不全的。。。。。 var data = Buffer.concat(body , size); var html = data.toString(); var $=cheerio.load(html); //只是個栗子,具體情況還會要url.parse解析所有href、src再處理 $('a').each(function(){ $(this).attr('href','

    //.pipe(res);
}</pre> 

除了丟包,一般不會有什么問題了,可能就是unicode中文的亂碼了,也有很多模塊可以處理,不過用JS弄也不錯,謝謝某大俠的代碼,找半天了,值得收藏:

function reconvert(str){ 
          str = str.replace(/(\\u)(\w{4})/gi,function($0){
                  return (String.fromCharCode(parseInt((escape($0).replace(/(%5Cu)(\w{4})/g,"$2")),16)));
           });         
         str = str.replace(/(&#x)(\w{4});/gi,function($0){
                  return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{4})(%3B)/g,"$2"),16));
           });            
        return str;
}

對了,抓取來的body是不能直接操作的,不信試一試,不用cheerio而是直接toString再replace什么的,都是無用功;

好吧,到這我一口氣爬取了上百篇大神們的博客, ,還是有些繁瑣的,巴拉巴拉,我想還是弄個定時任務吧,每天到點就爬一頁,取最新的留下;這里也有兩個模塊供選擇:schedule、later,還是下次做個橫向的比較吧,期待。schedule這個單詞在學校時就沒寫對過,今天終于寫對了,原諒我,又掉底子了。。。看看定時任務吧:

var registTask=function(hour,minute,taskname,fn){
    var rule = new schedule.RecurrenceRule();
    //每天這個時刻定時執行任務
  rule.dayOfWeek = [0, new schedule.Range(1, 6)];
  rule.hour = hour;
  rule.minute = minute;
  var j = schedule.scheduleJob(rule, function(){
    console.log("開始爬取:"+taskname);
        fn&&fn();
  });
}
registTask(23,30,'TaoBaoFED',function(){
    getTaoBaoFEDBokes(1);
        //呵呵,每天23:30爬一頁
});

差不多這就是“爬呀爬” 這個小玩意,對于一個業余的noder來說,又走了一小步,也挺好玩的;馬上就過年了,又要老一歲了啊,不過也很快就到春天了,祝大家猴年大吉,四季如春!

</div>

 本文由用戶 linjiazhen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!