node實現多網頁爬蟲
阿新 • • 發佈:2018-12-16
本案例以慕課網為例
在命令列安裝cheerio
npm install cheerio
在命令列安裝bluebird
npm install bluebird
//爬蟲,優雅的非同步程式設計 // 載入http模組 var http = require('https') //bluebird是一個第三方的Promise實現 var Promise = require('bluebird') // Cheerio 是一個Node.js的庫, 它可以從html的片斷中構建DOM結構,然後提供像jquery一樣的cs var cheerio = require('cheerio') // 定義爬蟲的目標地址 var baseUrl = 'https://www.imooc.com/learn/' //var url = 'https://www.imooc.com/learn/348' //提供具體頁面數值,可多個頁面爬取資料 var courseIds=[348] //過濾資料 function filterChapters(html) { // 沿用JQuery風格 var $ = cheerio.load(html) // 通過類名獲取章節資訊 var chapters = $('.chapter') // 課程資料,該資料是一個數組 var courseData = [] var courseTitle = $('.hd').find('h2').text().replace(/\s/g,'') var courseNumber = $($('.static-item')[2]).find('.meta-value').text().replace(/\s/g,'') /* 章節資訊遍歷 */ chapters.each(function(index,value) { // 獲取單獨的每一章 var chapter = $(this) // 獲取strong標籤裡面的文字,trim()去除空格,split()分隔成陣列,最終只獲取章節標題 var chapterTitle = chapter.find('h3').text().replace(/\s/g,'') // 獲取video標籤下的子標籤li的內容 var videos = chapter.find('.video').children('li') var chapterData = { chapterTitle: chapterTitle, videos: [] } videos.each(function(item) { var video = $(this) var videoTitle = video.text().replace(/\s/g,'').split('開始學習')[0] var id=video.find('a').attr('href').split('/')[2].replace(/\s/g,''); //可能要修改 var videoData={ title:videoTitle, id:id } chapterData.videos.push(videoData); }) courseData.push(chapterData) }) var courseObjectData={ courseTitle:courseTitle, courseNumber:courseNumber, courseData:courseData } return courseObjectData } //將得到的資料展示出來 function printCourseInfo(coursesData) { coursesData.forEach(function(courseData) { console.log(courseData.courseNumber + '人學過' + courseData.courseTitle + '\n') }) coursesData.forEach(function(courseData) { console.log('###' + courseData.courseTitle + '\n') courseData.courseData.forEach(function(item) { var chapterTitle = item.chapterTitle console.log(chapterTitle + '\n') item.videos.forEach(function(video) { console.log(' 【' + video.id + '】 ' + video.title + '\n') }) }) }) } /* 使用http模組來得到html文件 */ function getPageAsync(url) { return new Promise(function(resolve, reject) { //正確時執行resolve,錯誤時執行reject console.log('正在爬取' + url) http.get(url, function(res) { var html = '' res.on('data', function(data) { html += data }) res.on('end', function() { resolve(html) // var courseData = filterChapters(html) // printCourseInfo(courseData) }) res.on('error', function(e) { reject(e) console.log('獲取課程資料出錯') }) }) }) } var fetchCourseArray = [] courseIds.forEach(function(id) { fetchCourseArray.push(getPageAsync(baseUrl + id)); //把得到的每個地址放到fetchCourseArray }) Promise .all(fetchCourseArray) .then(function(pages) { var coursesData = [] pages.forEach(function(html) { var courseData = filterChapters(html) coursesData.push(courseData) }) coursesData.sort(function(a, b) { return a.number < b.number }) printCourseInfo(coursesData) })