上面的代码中,我们弄了一个计数器,当它执行完之后,我们就可以执行与‘get_topic_html‘名字对应的流程了,从而可以保证在执行完首页的抓取工作之后,再执行次级页面的抓取工作。
ep.emit('get_topic_html', 'get '+page+' successful');highScoreMovie方法如下,其实我们这里的作用不大,只是我统计一下高评分电影首页的信息,懒的继续抓取了
//评分8分以上影片 200余部!,这里只是统计数据,不再进行抓取 function highScoreMovie($){ var url='http://www.dytt8.net'+$('.co_content2 ul a').eq(0).attr('href'); console.log(url); superagent .get(url) .charset('gb2312') .end(function (err, sres) { // 常规的错误处理 if (err) { console.log('抓取'+url+'这条信息的时候出错了') } var $ = cheerio.load(sres.text); var elemP=$('#Zoom p'); var elemA=$('#Zoom a'); for (var k = 1; k < elemP.length; k++) { var Hurl=elemP.eq(k).find('a').text(); if(highScoreMovieArr.indexOf(Hurl) ==-1){ highScoreMovieArr.push(Hurl); }; } }); }
3、分离出左侧栏的信息,
如下图,首页中,详情页的链接都在这里$('.co_content2 ul a')。
因此我们将左侧栏这里的详情页链接都遍历出来,保存在一个newMovieLinkArr这个数组里面。
getAllMovieLink方法如下:
// 获取首页中左侧栏的所有链接 function getAllMovieLink($){ var linkElem=$('.co_content2 ul a'); for(var i=1;i<170;i++){ var url='http://www.dytt8.net'+linkElem.eq(i).attr('href'); // 注意去重 if(newMovieLinkArr.indexOf(url) ==-1){ newMovieLinkArr.push(url); }; } }
4、对获取到的电影详情页进行爬虫,提取有用信息,比如电影的下载链接,这个是我们所关心的。
// 命令 ep 重复监听 emit事件(get_topic_html),当get_topic_html爬取完毕之后执行 ep.after('get_topic_html', 1, function (eps) { var concurrencyCount = 0; var num=-4; //因为是5个并发,所以需要减4 // 利用callback函数将结果返回去,然后在结果中取出整个结果数组。 var fetchUrl = function (myurl, callback) { var fetchStart = new Date().getTime(); concurrencyCount++; num+=1 console.log('现在的并发数是', concurrencyCount, ',正在抓取的是', myurl); superagent .get(myurl) .charset('gb2312') //解决编码问题 .end(function (err, ssres) { if (err) { callback(err, myurl + ' error happened!'); errLength.push(myurl); return next(err); } var time = new Date().getTime() - fetchStart; console.log('抓取 ' + myurl + ' 成功', ',耗时' + time + '毫秒'); concurrencyCount--; var $ = cheerio.load(ssres.text); // 对获取的结果进行处理函数 getDownloadLink($,function(obj){ res.write('<br/>'); res.write(num+'、电影名称--> '+obj.movieName); res.write('<br/>'); res.write('迅雷下载链接--> '+obj.downLink); res.write('<br/>'); res.write('详情链接--> <a href='https://www.jb51.net/+myurl+' target="_blank">'https://www.jb51.net/+myurl+'<a/>'); res.write('<br/>'); res.write('<br/>'); }); var result = { movieLink: myurl }; callback(null, result); }); }; // 控制最大并发数为5,在结果中取出callback返回来的整个结果数组。 // mapLimit(arr, limit, iterator, [callback]) async.mapLimit(newMovieLinkArr, 5, function (myurl, callback) { fetchUrl(myurl, callback); }, function (err, result) { // 爬虫结束后的回调,可以做一些统计结果 console.log('抓包结束,一共抓取了-->'+newMovieLinkArr.length+'条数据'); console.log('出错-->'+errLength.length+'条数据'); console.log('高评分电影:==》'+highScoreMovieArr.length); return false; }); });
首先是async.mapLimit对所有详情页做了一个并发,并发数为5,然后再爬取详情页,爬详情页的过程其实和爬首页的过程是一样的,所以这里不做过多的介绍,然后将有用的信息打印到页面上。
5、执行命令之后的图如下所示:
浏览器界面:
这样,我们爬虫的稍微升级版就就完成啦。可能文章写的不是很清楚,我已经把代码上传到了github上,可以将代码运行一遍,这样的话比较容易理解。后面如果有时间,可能会再搞一个爬虫的升级版本,比如将爬到的信息存入mongodb,然后再在另一个页面展示。而爬虫的程序加个定时器,定时去抓取。
备注:如果运行在浏览器中的中文乱码的话,可以将谷歌的编码设置为utf-8来解决;
代码地址:https://github.com/xianyulaodi/mySpider2
有误之处,欢迎指出
您可能感兴趣的文章: