Node.js爬虫初探
首先,一个爬虫应该做到什么
网络爬虫,即Web Spider。从网站一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其他链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到把这个网站的所有网页都抓取完为止。
如果把互联网当作一个网站,那么网络爬虫就可以用这个原理把互联网上所有的网页都抓取下来。
这样看来网络爬虫就是一个爬行程序,一个抓取网页的程序。网络爬虫的基本操作是抓取网页。
那么一个网络爬虫就至少要做到三件事情:
- 获取网页内容(包括图片文字链接…)(http/request/superagent/…)
- 筛选网页信息(cheeio)
- 输出或储存信息(console/fs/mongodb/…)
获取页面内容
- Nodejs自带-http模块(异步)
- 第三方-request模块(异步)
- 第三方-superagent模块(异步)
- 第三方-sync-request模块(同步)
第一个程序——只有12行的bing首页标题爬取
程序正文
var request = require("request");
var cheerio = require("cheerio");
request('https://www.bing.com',function(err,result){
if(err){
console.log("请求错误:"+err);
return;
}
//console.log(result.body)
var page=cheerio.load(result.body);
console.log(page('title').text());
});
上面这个爬虫是我的第一个爬虫,只能爬到bing首页的标题,功能十分简单。
但是它完成了上面说的一个简单的爬虫应该做到的三个事情,一个是获取页面信息,这里使用request实现,一个是筛选页面信息,使用cheerio实现,一个是输出或储存信息,这里使用console实现。
紧接着我写了第二个爬虫,换用了sync-request模块
第二个爬虫——豆瓣电影详情页爬取
引入模块
这个爬虫会用到三个模块:
- cheerio(做爬虫少不了这个)
- sync-request
- fs
var cheerio = require('cheerio');
var request = require('sync-request');
var fs = require('fs');
sync-request这个模块是一个同步获取的模块,优点是能够直接将获取的内容输出给变量,简单方便。缺点就是如果内容很多,速度将会变慢,而且也没有错误判断机制。不过这里我门就是要尝试使用这个同步获取 so 接着往下写
获取网页内容
url = "https://movie.douban.com/subject/26425063/?from=showing"; //豆瓣电影-无双
var html = '';
html = request('GET', url).getBody().toString();
用cheerio筛选有用信息
function handleDB(html) {
var $ = cheerio.load(html);
//引入cheerio的方法。这样的引入方法可以很好的结合jQuery的用法(ps.jQuery我还刚学=^=)
var info = $('#info');
//获取电影名
var movieName = $('#content>h1>span').filter(function (i, el) {
return $(this).attr('property') === 'v:itemreviewed';
}).text();
//获取影片导演名
var directories = '- 导演:' + $('#info span a').filter(function (i, el) {
return $(this).attr('rel') === 'v:directedBy';
}).text();
//获取影片演员
var starsName = '- 主演:';
$('.actor .attrs a').each(function (i, elem) {
starsName += $(this).text() + '/';
});
//获取片长
var runTime = '- 片长:' + $('#info span').filter(function (i, el) {
return $(this).attr('property') === 'v:runtime';
}).text();
//获取影片类型
//同样是多个信息处理方式和演员不同
var kind = $('#info span').filter(function (i, el) {
return $(this).attr('property') === 'v:genre';
}).text();
//处理影片类型数据
var kLength = kind.length;
var kinds = '- 影片类型:';
for (i = 0; i < kLength; i += 2) {
kinds += kind.slice(i, i + 2) + '/';
}
//获取电影评分和电影评分人数
//豆瓣
var DBScore = $('.ll.rating_num').text();
var DBVotes = $('a.rating_people>span').text().replace(/\B(?=(\d{3})+$)/g, ',');
var DB = '- 豆瓣评分:' + DBScore + '/10' + '(' + 'form' + DBVotes + 'users' + ')';
//IMDBLink
IMDBLink = $('#info').children().last().prev().attr('href');
var data = movieName + '\r\n' + directories + '\r\n' + starsName + '\r\n' + runTime + '\r\n' + kinds + '\r\n' + DB + '\r\n';
//输出文件
fs.appendFile('dbmovie.txt', data, 'utf-8', function (err) {
if (err) throw err;
else console.log('大体信息写入成功' + '\r\n' + data);
});
}
这里豆瓣界面上的电影信息和评分就获取到了,但是豆瓣提供了对应的IMDB链接,所有我们需要再取IMDB页面中获取相应的评分和人数。
IMDB页面获取评分
function handleIMDB(Link) {
var $ = cheerio.load(Link);
// 获取IMDB评分
var IMDBScore = $('.ratingValue strong span').filter(function (i, el) {
return $(this).attr('itemprop') === 'ratingValue';
}).text();
// 获取IMDB评分人数
var IMDBVotes = $('.small').filter(function (i, el) {
return $(this).attr('itemprop') === 'ratingCount';
}).text();
// 字符串拼接
var IMDB = '- IMDB评分:' + IMDBScore + '/10' + '(' + 'from' + IMDBVotes + 'users' + ')' + '\r\n';
// 输出文件
fs.appendFile('dbmovie.txt', IMDB, 'utf-8', function (err) {
if (err) throw err;
else console.log('IMDB信息写入成功' + '\r\n' + IMDB)
});
}
这里用的fs.appendFile(file, data[, options], callback)
是一个异步输出文件的方法,它的作用是追加文件内容。如果这个文件不存在就会新建一个,并写入追加内容。其中:
- file->文件名
- data->要写入的内容
- options->选项,可以指定输出的文件编码格式
- callback->回调函数
其中callback中会传递一个error参数用于反馈错误所用。
到这里这个爬虫已经可以爬取豆瓣电影详情页的信息了。