上周写了一个node+experss的爬虫小入门。今天继续来学习一下,写一个爬虫2.0版本。
这次我们不再爬博客园了,咋玩点新的,爬爬电影天堂。因为每个周末都会在电影天堂下载一部电影来看看。
talk is cheap,show me the code!
抓取页面分析
我们的目标:
1、抓取电影天堂首页,获取左侧最新电影的169条链接
2、抓取169部新电影的迅雷下载链接,并且并发异步抓取。
具体分析如下:
1、我们不需要抓取迅雷的所有东西,只需要下载最新发布的电影即可,比如下面的左侧栏。一共有170个,除去第一个(因为第一个里面有200部电影),一共有169部电影。
2、除了抓取首页的东西,我们还要抓取点进去之后,每部电影的迅雷下载链接
环境搭建
1、需要的东西:node环境、express、cherrio 这三个都是上一篇文章有介绍的,所以这里不再做介绍:点击查看
2、需要安装的新东西:
superagent:
作用:跟request差不多,我们可以用它来获取get/post等请求,并且可以设置相关的请求头信息,相比较使用内置的模块,要简单很多。
用法:
var superagent = require('superagent'); superagent .get('/some-url') .end(function(err, res){ // Do something });
superagent-charset:
作用:解决编码问题,因为电影天堂的编码是gb2312,爬取下来的中文会乱码掉。
用法:
var superagent = require('superagent'); var charset = require('superagent-charset'); charset(superagent); superagent .get('/some-url') .charset('gb2312') //这里设置编码 .end(function(err, res){ // Do something });
async:
作用:Async是一个流程控制工具包,提供了直接而强大的异步功能,在这里作为处理并发来调用。
用法:这里需要用到的是:async.mapLimit(arr, limit, iterator, callback)
mapLimit可以同时发起多个异步操作,然后一起等待callback的返回,返回一个就再发起下一个。
arr是一个数组,limit并发数,将arr中的每一项依次拿给iterator去执行,执行结果传给最后的callback
eventproxy:
作用:eventproxy 起到了计数器的作用,它来帮你管理到底异步操作是否完成,完成之后,它会自动调用你提供的处理函数,并将抓取到的数据当参数传过来。
例如我首先抓取到电影天堂首页侧栏的链接,才可以接着抓取链接里面的内容。具体作用可以点这里
用法:
var ep = new EventProxy(); ep.after('got_file', files.length, function (list) { // 在所有文件的异步执行结束后将被执行 // 所有文件的内容都存在list数组中 }); for (var i = 0; i < files.length; i++) { fs.readFile(files[i], 'utf-8', function (err, content) { // 触发结果事件 ep.emit('got_file', content); }); } //注意got_file这两个名字必须对应
开始爬虫
主要的程序在app.js这里,所以看的话可以主要看app.js即可
1、首先定义一些全局变量,该引入的库引进来
var cheerio = require('cheerio'); //可以像jquer一样操作界面 var charset = require('superagent-charset'); //解决乱码问题: var superagent = require('superagent'); //发起请求 charset(superagent); var async = require('async'); //异步抓取 var express = require('express'); var eventproxy = require('eventproxy'); //流程控制 var ep = eventproxy(); var app = express(); var baseUrl = 'http://www.dytt8.net'; //迅雷首页链接 var newMovieLinkArr=[]; //存放新电影的url var errLength=[]; //统计出错的链接数 var highScoreMovieArr=[] //高评分电影
2、开始爬取首页迅雷首页:
//先抓取迅雷首页 (function (page) { superagent .get(page) .charset('gb2312') .end(function (err, sres) { // 常规的错误处理 if (err) { console.log('抓取'+page+'这条信息的时候出错了') return next(err); } var $ = cheerio.load(sres.text); // 170条电影链接,注意去重 getAllMovieLink($); highScoreMovie($); /* *流程控制语句 *当首页左侧的链接爬取完毕之后,我们就开始爬取里面的详情页 */ ep.emit('get_topic_html', 'get '+page+' successful'); }); })(baseUrl);
在这里,我们先抓取首页的东西,把首页抓取到的页面内容传给 getAllMovieLink和highScoreMovie这两个函数来处理,
getAllMovieLink获取到了左侧栏除了第1部的电影的169电影。
highScoreMovie为左侧栏第一个链接,里面的都是评分比较高的电影。