Node.js多是最適合寫簡易小爬蟲的語言,速度極快、代碼極少

「凡是能用JS 寫出來的,最終都會用JS 寫」,這是一個很是著名的定律,用在爬蟲這裏再合適不過了。javascript

一說到爬蟲不少人都會想到python,的確,python語法簡潔,還有scrapy這一類強大的工具可使用。java

可是若是隻是想寫一個小爬蟲,爬取論壇裏的幾張帖子,帖子裏面的幾個樓層,而後合成一篇文章。這點小數據量使用scrapy就有點殺雞用牛刀了,並且還得設置一堆東西,很是麻煩,不夠靈活。python

而JavaScript就很是適合這一類小爬蟲,首先是自帶異步架構,能同時爬取多張網頁內容,效率上來講比python高多了,我用兩個語言寫過爬取代理ip的爬蟲,當JavaScript爬完時嚇了我一跳,這速度快極了。git

固然,python也能夠經過開啓多線程、多協程來實現同時爬取多張網頁,可是這就比默認就異步的JavaScript麻煩多了。github

因此,若是想簡單、高效地寫個小爬蟲,非JavaScript莫屬。npm

有多快多簡單呢?如今就來寫個豆瓣top250的爬蟲,爬取10張網頁,250部電影的名字、評分和封面地址;數組

1.如何安裝

要經過js寫爬蟲,須要用到三個模塊,request、cheerio和fs,其中fs內置了,只須要安裝前兩個便可,安裝命令:多線程

npm install request cheerio
複製代碼

2.獲取網頁內容

request能夠連接網頁,爬取內容,這裏咱們只須要給它傳遞兩個參數就行,一個爲url(網址),另外一個爲回調函數; request會向回調函數傳遞三個參數,分別是error(錯誤信息),response(響應信息),body(網頁內容):架構

var request = require('request')
var cheerio = require('cheerio')
var fs = require('fs')
var movies = []

var requstMovie = function(url){
	request('https://movie.douban.com/top250',function(error, response, body)){
		//res.statusCode 爲200則表示連接成功
		if(error === null && response.statusCode === 200){
			console.log('連接成功')
			//使用cheerio來解析body(網頁內容),提取咱們想要的信息
			var e = cheerio.load(body)
			
			//經過分析網頁結構,咱們發現豆瓣每部電影都經過item屬性隔開
			var movieDiv = e('.item')
	
			//經過for循環來提取每部電影裏的信息
			for (let i = 0; i < movieDiv.length; i++) {
					//takeMovie函數能提取電影名稱、評分和封面
	                let movieInfo = takeMovie(movieDiv[i])
	                log('正在爬取' + movieInfo.name)
	                //將提取到的電影放入數組
	                movies.push(movieInfo)
	            }
		}
	})
}
複製代碼

3.提取電影信息

經過建立一個類來包含咱們想要的屬性,在每次調用takeMovie函數提取信息時都會初始化這個類,而後賦值給相應的屬性; 以後放入movies數組裏;app

//電影的類
var movie = function(){
    this.id = 0
    this.name = ''
    this.score = 0
    this.pic = ''
}

var takeMovie = function(div){
    var e = cheerio.load(div)
    //將類初始化
    var m = new movie()
    m.name = e('.title').text()
    m.score = e('.rating_num').text()
    var pic = e('.pic')
    //cheerio若是要提取某個屬性的內容,能夠經過attr()
    m.pic = pic.find('img').attr('src')
    m.id = pic.find('em').text()
    return m
}
複製代碼

4.爬取全部top250

如今要爬取全部的top250信息,總共有10張網頁,每張包含25部電影信息,建立一個函數來生成每張網頁的網址,而後經過request進行爬取:

var top250Url = function(){
    let l = ['https://movie.douban.com/top250']
    var urlContinue = 'https://movie.douban.com/top250?start='
    let cont = 25
    for (let i = 0; i < 10; i++) {
        l.push(urlContinue+cont)
        cont += 25
    }
    return l
}

//爬取全部網頁
var __main = function(){
    var url = top250Url()
    for (let i = 0; i < url.length; i++) {
        requstMovie(url[i])
    }
}

__main()
複製代碼

5.異步架構的坑

當咱們爬取完全部的網頁後就會發現,movies裏的電影信息並不按咱們爬取的順序,這也是異步架構一個須要注意的大坑; 在爬取第一張網頁時,JavaScript不會等處處理結束才接着爬第二張,有時候各個網頁返回的速度有所差別,會形成先爬取的不必定會先出結果,所以在電影排序上會出現混亂; 因此咱們還須要對爬取下來的內容從新進行排序,而後保存:

//sortMovie回調函數能比較兩個對象屬性大小
var sortMovie = function(id){
    return function(obj ,obj1){
        var value = obj[id]
        var value1 = obj1[id]
        return value - value1
    }
}

//保存文件
var saveMovie = function(movies){
    var path = 'movie.txt'
    var data = JSON.stringify(movies, null, 2)
    fs.appendFile(path, data, function(error){
        if(error == null){
            log('保存成功!')
        } else {
            log('保存失敗',error)
        }
    })
}
複製代碼

咱們須要等到全部網頁都爬取分析完才執行sortMovie和saveMovie函數,因爲JavaScript是異步,即便這兩個函數放在最底部也會在分析完以前執行; 通常會經過Promise來控制異步,可是爲了方便,這裏咱們經過if來判斷,在每次爬取網頁後,都會判斷movies裏是否包含250條信息,若是有則說明所有爬取到了:

var requstMovie = function(url){
    request(url, function(error, response, body){
        if (error === null && response.statusCode === 200){
            var e = cheerio.load(body)
            var movieDiv = e('.item')
            for (let i = 0; i < movieDiv.length; i++) {
                let movieInfo = takeMovie(movieDiv[i])
                log('正在爬取' + movieInfo.name)
                movies.push(movieInfo)
            }
            //判斷movies數量
            if (movies.length === 250){
            	//經過sort將數組內每兩個元素放入比較函數
                var sortM = movies.sort(sortMovie('id'))
                //保存文件
                saveMovie(sortM)
            }
        } else {
            log('爬取失敗', error)
        }
    })
    
}
複製代碼

到這裏,爬蟲已經寫完了,來運行一下:

完整代碼能夠經過github查看:DoubanMovies.JS

也能夠訪問個人網站,獲取更多文章:Nothlu.com

相關文章
相關標籤/搜索