nodejs爬蟲筆記(一)---request與cheerio等模塊的應用


 

目標:爬取慕課網里面一個教程的視頻信息,並將其存入mysql數據庫。以http://www.imooc.com/learn/857為例。

 

一、工具

 

1.安裝nodejs:(操作系統環境:WiN 7 64位)

   在Windows環境下安裝相對簡單(ps:其他版本我也不太清楚,可以問度娘)

  http://nodejs.org/download/   鏈接中下載對應操作系統安裝文件(安裝最新版本就行)

  按照提示,一路下一步直到安裝成功后,在默認安裝路徑下可以看到(C:\Program Files\nodejs),默認路徑在安裝的時候可以修改。

  安裝成功后,在“命令提示符中”輸入:node -v 查看安裝版本,輸出版本即安裝成功

  

 

2.編碼工具:

 

  WebStorm下載地址: http://www.jetbrains.com/webstorm/Webstorm用起來很方便,但是我電腦比較卡,我最終還是選擇了Sublime,可以在各平台下保持個統一個開發工具,配置方法網上有很多(軟件無需注冊,使用過程中時不時會彈出需要注冊的窗口,取消即可)

 

   Sublime下載地址: http://www.sublimetext.com/    

      Sublime配置nodejs環境可參考http://www.cnblogs.com/zhongweiv/p/nodejs_environment.html

 

二、相關模塊

  • 獲取網頁內容(http\request\superagent等)
  • 篩選網頁信息(cheerio)
  • 輸出或存儲信息(console\fs\mongodb\mysql等)

1、使用 request 模塊來獲取網頁內容

request 是一個用來簡化 HTTP 請求操作的模塊,其功能強大而且使用方法簡單,以下 是一個通過 GET 方法來獲取某個URL的內容的例子:

 

var request = require('request');

// 通過 GET 請求來讀取 http://cnodejs.org/ 的內容
request('http://cnodejs.org/', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    // 輸出網頁內容
    console.log(body);
  }
});

 

如果是其他的請求方法,或者需要指定請求頭等信息,可以在第一個參數中傳入一個對象來 指定,比如:

 

var request = require('request');

request({
  url:    'http://cnodejs.org/',   // 請求的URL
  method: 'GET',                   // 請求方法
  headers: {                       // 指定請求頭
    'Accept-Language': 'zh-CN,zh;q=0.8',         // 指定 Accept-Language
    'Cookie': '__utma=4454.11221.455353.21.143;' // 指定 Cookie
  }
}, function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body) // 輸出網頁內容
  }
});

 

本文中僅用到了 request 模塊很少的部分,其具體的使用方法可以瀏覽該模塊的主頁來獲取詳細的使用說明:https://npmjs.org/package/request

2、使用 cheerio 模塊來提取網頁中的數據

cheerio 是一個 jQuery Core 的子集,其實現了 jQuery Core 中瀏覽器無關的 DOM 操作 API,以下是一個簡單的示例:

var cheerio = require('cheerio');

// 通過 load 方法把 HTML 代碼轉換成一個 jQuery 對象
var $ = cheerio.load('<h2 class="title">Hello world</h2>');

// 可以使用與 jQuery 一樣的語法來操作
$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

console.log($.html());
// 將輸出 <h2 class="title welcome">Hello there!</h2>

簡單來說,cheerio就是服務器端的jQuery,去掉了jQuery的一些效果類和請求類等等功能后,僅保留核心對dom操作的部分,因此能夠對dom進行和jQuery一樣方便的操作。它是我們篩選數據的利器——把多余的html標簽去掉,只留下我們想要的內容的重要工具。需要注意的是,cheerio 並不支持所有 jQuery 的查詢語法,比如 $('a:first') 會報錯 ,只能寫成  $('a').first() ,在使用的時候需要注意。jQuery的相關選擇器可以參考http://www.cnblogs.com/xiaxuexiaoab/p/7091527.html

cheerio 模塊的詳細使用方法可以訪問該模塊的主要來獲取: https://npmjs.org/package/cheerio

3、使用 mysql 模塊來將數據儲存到數據庫

我使用的是mysql連接池,具體的使用方法可以參考https://github.com/felixge/node-mysql

mysql 模塊內置了連接池機制,以下是一個簡單的使用示例:

var mysql = require('mysql');

// 創建數據庫連接池
var pool  = mysql.createPool({
  host:           'localhost', // 數據庫地址
  user:           'root',      // 數據庫用戶
  password:        '',         // 對應的密碼
  database:        'example',  // 數據庫名稱
  connectionLimit: 10          // 最大連接數,默認為10
});

// 在使用 SQL 查詢前,需要調用 pool.getConnection() 來取得一個連接
pool.getConnection(function(err, connection) {
  if (err) throw err;

  // connection 即為當前一個可用的數據庫連接
});

4、使用 async 模塊來簡化異步流程控制

async 是一個使用比較廣泛的 JavaScript 異步流程控制模塊,除了可以在 Node.js 上運行外,其還可以在瀏覽器端運行。 async模塊提供了約 20 多個實用的函數來 幫助我們理清在使用 Node.js 過程中各種復雜回調。

可以參考:http://blog.csdn.net/zzwwjjdj1/article/details/51857959

關於 async 模塊的詳細使用方法可以訪問該模塊的主頁來獲取: https://npmjs.org/package/async.

 

三、開始爬蟲

 1、初始化項目

在喜歡的目錄下創建一個文件夾,我在D盤創建文件夾並命名為crawler;在DOS下cd到該目錄,運行npm init 初始化,此時需要填寫一些項目信息,你可以根據情況填寫,當然也可以一路回車。創建完項目后,會生成一個package.json的文件。該文件包含了項目的基本信息。然后安裝第三方包:

npm install request cheerio mysql async -save

–save的目的是將項目對該包的依賴寫入到package.json文件中。此時,package.json文件如下:

{
  "name": "crawler",
  "version": "1.0.0",
  "description": "crawler and mysql",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "async": "^2.5.0",
    "cheerio": "^1.0.0-rc.1",
    "mysql": "^2.13.0",
    "request": "^2.81.0"
  }
}

 

 

2、分析頁面

打開http://www.imooc.com/learn/857,可以發現課程如下:

 

我習慣使用Google瀏覽器,打開網頁后點擊檢查,可以查看該網頁相關部分的html代碼如下:

    

 

 3、獲取視頻信息

我們需要從這段HTML中獲取視頻的名稱name,id,url,時長duration以及所屬章節title。利用jQuery的方法,可以通過$('.video li a')來獲取所有視頻的a標簽,然后從中提取name,duration,url和id,所屬章節的話要轉到a標簽的曾祖父。在crawler目錄下新建video.js,在sublime-text中編輯程序如下:

var request = require('request');
var cheerio = require('cheerio');


var url = 'http://www.imooc.com/learn/857';

function videocrawler(url,callback){
       //獲取頁面
    request(url,function(err,res){
        if(err){
            callback(err);
        }
        
        var $ = cheerio.load(res.body.toString()); //利用cheerio對頁面進行解析

        var videoList = [];
        
        $('.video li a').each(function(){
            var $title = $(this).parent().parent().parent().text().trim();
            var title = $title.split('\n');
            var text = $(this).text().trim();
            text = text.split('\n');
            //console.log(text);
            var time = text[1].match(/\((\d+\:\d+)\)/); 
            var item={
                title : title[0],
                url : 'http://www.imooc.com'+$(this).attr('href'),
                name : text[0],
                duration : time[1]
            };
            var s = item.url.match(/video\/(\d+)/);
            //console.log(s);
            if(Array.isArray(s)){
                item.id = s[1];
                videoList.push(item);
            }
        });
            
        callback(null,videoList);
    });
}

videocrawler(url,function(err,videoList){
       if(err){
           return console.log(err);
       }
       console.log(videoList);
});

 

配置好node.js環境后(配置參考http://www.cnblogs.com/zhongweiv/p/nodejs_environment.html), 點擊ctrl+s進行保存,再點擊ctrl+b運行(也可以在DOS下輸入node video運行)顯示如下:

我們已經得到了視頻相關信息,接下來我們將其存入mysql。

4、數據存入mysql

 新建數據庫muke,然后新建數據表video,在DOS下輸入use muke后,創建數據庫表:

CREATE TABLE `video` (
  `id` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `url` varchar(255) NOT NULL,
  `name` varchar(255) NOT NULL,
  `duration` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 然后在crawler文件夾下新建save.js,先利用sublime編輯代碼如下:

var mysql = require('mysql');
var async = require('async');

var pool = mysql.createPool({
    host : 'localhost',
    user : 'root',
    password : 'z2457098495924',
    database : 'muke'
});

pool.getConnection(function(err,connection){
    if(err){
        console.log(err);
    }
    connection.query('show tables',function(err,result){
         if(err){
             return console.log('show tables error:'+err.message);
         }
         return console.log(result);
    });
    connection.release();
});

 

 運行后輸出如下圖,其中content是muke數據庫下的另外一個表。

此時說明數據庫已經連接成功。接下來繼續編輯save.js如下:

var mysql = require('mysql');
var async = require('async');

var pool = mysql.createPool({
    host : 'localhost',
    user : 'root',
    password : 'z2457098495924',
    database : 'muke'
});


exports.videoSave = function(list,callback){
    
    pool.getConnection(function(err,connection){
        if(err){
            return callback(err);
        }
      var findsql = 'select * from video where id=?';
      var updatesql = 'update video set title=?,url=?,name=?,duration=? where id=?';
        var insertsql = 'insert into video(id,title,url,name,duration) values(?,?,?,?,?)';
        async.eachSeries(list,function(item,next){
        connection.query(findsql,[item.id],function(err,result){
            if(err){
                return next(err);
            }
            if(result.length>=1){
                connection.query(updatesql,[item.title,item.url,item.name,item.duration,item.id],next);
            }else{
                connection.query(insertsql,[item.id,item.title,item.url,item.name,item.duration],next);
            }
        });         
        },callback);
        connection.release();
    });
};

 

修改video.js如下

var request = require('request');
var cheerio = require('cheerio');

exports.videocrawler = function(url,callback){
    request(url,function(err,res){
        if(err){
            callback(err);
        }

        var $ = cheerio.load(res.body.toString());

        var videoList = [];
        
        $('.video li a').each(function(){
            var $title = $(this).parent().parent().parent().text().trim();
            var title = $title.split('\n');
            var text = $(this).text().trim();
            text = text.split('\n');
            //console.log(text);
            var time = text[1].match(/\((\d+\:\d+)\)/); 
            var item={
                title : title[0],
                url : 'http://www.imooc.com'+$(this).attr('href'),
                name : text[0],
                duration : time[1]
            };
            var s = item.url.match(/video\/(\d+)/);
            //console.log(s);
            if(Array.isArray(s)){
                item.id = s[1];
                videoList.push(item);
            }
        });
            
        callback(null,videoList);
    });
}

 

然后在crawler目錄下新建index.js文件,編輯代碼如下:

var async = require('async');var video = require('./video');
var save = require('./save');
var url = 'http://www.imooc.com/learn/857';
var videolist;

async.series([
        //獲取視頻信息
        function(done){
            video.videocrawler(url,function(err,list){
                videolist = list;
                done(err);
            });
        },
        //保存視頻信息
        function(done){
            save.videoSave(videolist,done);
        },

    ],function(err){
    if(err){
        console.log(err);
    }
    console.log('完成');
    process.exit(0);
})

 

 點擊運行后會輸出 ‘’完成‘’。然后利用可視化工具Navicat 查看video數據表可以看到信息已經存入。

 

四、總結

通過node爬蟲訓練,對request、cheerio、async、mysql等模塊有了初步的了解,也熟悉了下node爬蟲的基本過程,同時,我也體會到了NodeJs模塊化的便捷及魅力。爬蟲項目,其中關鍵就在於選擇器的設計。cheerio包的選擇器$,和jQuery選擇器規則幾乎是一樣的。選擇器可以參考http://www.cnblogs.com/xiaxuexiaoab/p/7091527.html.

歡迎評論,轉載請注明地址。

 

 


免責聲明!

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



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