性感慕課-在線被爬

引言

在學習了 alsotang 大神的 《Node.js包教不包會》後的一個爬蟲小練習,期間也碰到挺多小問題,也學到了不少小東西。「單押×3」前端

這裏是大神的教程地址 github.com/alsotang/no…node

下面是本身的爬取效果圖git

spider2
)

同時推薦一個谷歌插件 JSONView,會將 JSON 格式的數據轉化成上面圖的格式github

imoocSpider練習源碼express

搭建服務器

首先,搭建一個 http 服務數組

var http = require('http');
var express = require('express');

var app = express();

http.createServer(app).listen(8080);

app.get('/', function(req, res) {
  //code here...
})
複製代碼

用的是 express 搭建的,固然也能夠用原生的,在這裏本身比較習慣用 express安全

在線爬蟲

在這裏用到的是 superagentcheerio 來爬取頁面,這裏有相關文檔能夠參考: superagent中文文檔cheerio,都是來自 cnode 社區,固然英語能力較好的也能夠參考原文檔。在這裏就只貼出這兩個服務器

爬取頁面連接 https://www.imooc.com/course/list?c=fe併發

咱們是要爬取慕課網前端開發八個頁面的課程中的一些信息,可是打開此連接發現每一個頁面只有課程的名稱,並無老師的名稱和一些課程的主要信息。所以咱們還須要獲取並根據每一個課程的 url 進行爬取。app

獲取課程詳情頁連接

那咱們先來爬取八個頁面的全部課程詳情頁的 url

經過點擊對應頁面的按鈕,發現每次都會發送一個新的 get 請求,請求的連接就是對應的頁面,而這裏的連接只有 page 屬性是不一樣的,所以咱們經過動態改變 page 就能夠模擬點擊對應頁來獲取對應頁的信息

var pages = 1;
var baseUrl = 'https://www.imooc.com/course/list/';

var params = {
  c: 'fe',
  page: page
};

superagent
  .get(baseUrl)
  .query(params)
  .end(function(err, content) {
    var topicUrls = [];
    var $ = cheerio.load(content.text);
    var courseCard = $('.course-card-container');
    courseCard.each(function(index, element) {
      var $element = $(element);
      var href = url.resolve(
        homeUrl,
        $element.find('.course-card').attr('href')
      );

      topicUrls.push(href);
    });
    console.log(topicUrls);
  });
複製代碼

這樣就能夠獲取到了第一個頁面的 25 個課程的詳情頁的 url,那要如何獲取八個頁面呢。

async

由於有些網站一般都會有安全限制,不會容許同一個域名有過大的高併發數,所以須要限制併發數,在這裏用咱們用到了 async 這個庫。這裏是其 github

咱們首先把前面代碼封裝成一個函數

var baseUrl = 'https://www.imooc.com/course/list/';
var fetchUrl = function(page, callback) {
    count++;
    console.log('當前併發數', count);

    var params = {
      c: 'fe',
      page: page
    };

    superagent
      .get(baseUrl)
      .query(params)
      .end(function(err, content) {
        var topicUrls = [];
        var $ = cheerio.load(content.text);
        var courseCard = $('.course-card-container');
        courseCard.each(function(index, element) {
          var $element = $(element);
          var href = url.resolve(
            homeUrl,
            $element.find('.course-card').attr('href')
          );

          topicUrls.push(href);
        });

        callback(err, topicUrls);
        count--;
        console.log('釋放併發數後當前併發數', count);
        
      });
  };
複製代碼

而後用 async 控制併發數和八個頁面的抓取

var pages = [1, 2, 3, 4, 5, 6, 7, 8];
async.mapLimit(
    pages, 
    5,
    function(page, callback) {
      fetchUrl(page, callback);
    },
    function(err, result) {
      if (err) console.log(err);

      console.log(result)
    }
  );
});
複製代碼

這樣全部的 url 就被打印出來,這裏要注意一下,async 會自動把第三個函數參數的返回值合併成一個數組給第四個函數參數的 result 參數。剛開始寫的時候我把 topicUrls 聲明在了全局,以致於返回成下面這組數據

spider1

爬取課程詳情頁的信息

在咱們有了全部課程詳情頁的 url 後,咱們開始爬取裏面的內容。首先定義一個函數

var fetchMsg = function(topicUrl, callback) {
    console.log('開啓新一輪抓取')
    superagent
      .get(topicUrl)
      .end(function(err, content){
        var Item = [];
        var $ = cheerio.load(content.text);
        var title = $('.hd .l').text().trim();//課程名字
        var teacher = $('.tit a').text().trim();//老師名字
        var level = $('.meta-value').eq(0).text().trim();//難度
        var time = $('.meta-value').eq(1).text().trim();//時長
        var grade = $('.meta-value').eq(3).text().trim();//評分

        Item.push({
          title: title,
          teacher: teacher,
          level: level,
          time: time,
          grade: grade,
          href: topicUrl
        })


        callback(null, Item);
      })
  };
複製代碼

而後用 async 控制併發爬取

//result 爲上文中的 result,下面的代碼也都是在上文中的第四個參數中

var topicUrls = result; //獲取全部 url ,可是大數組裏面有 8 個小數組

var Urls = [];
//將大數組合並
for(let i=0,l=topicUrls.length;i<l;i++){
  Urls = Urls.concat(topicUrls[i]);
}

async.mapLimit(
  Urls,
  5,
  function(url,callback){
    fetchMsg(url, callback);
  },
  function(err, result) {
    //避免亂碼
    res.writeHead(200, {'Content-Type': 'text/plain;charset=utf8'})
    res.end(JSON.stringify(result));
  }
複製代碼

這裏要注意一個小問題,就是 result 獲取到的 url 結構是一個大數組裏麪包含八個小數組,所以須要將其小數組先合併成一個大數組。

最後

項目源碼

原文地址

天天探索一點點,天天進步一點點。

相關文章
相關標籤/搜索