目標:爬取慕課網里面一個教程的視頻信息,並將其存入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.
歡迎評論,轉載請注明地址。