网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
网络爬虫基本就由如下部分组成:程序入口
请求模块
数据解释
下面我们来看一下如何使用nodejs实现网络爬虫。
程序入口
开始配置和初始化commander
首先要在package.json添加如下节点,表示注册了一个命令行 "grab"。"bin": {
"grab": "bin/grab.js"
},
接着在grab.js开始定义commander,最后我们就可以这样执行命令行:"grab baidu ",当然可以用bd简写代替baidu,知乎的定义和百度是一样,这里不再重复介绍了。program
// .allowUnknownOption()//不报错误
.version('0.0.1').usage('这是我的网络爬虫程序
请求模块
https模块发起请求主要有两种方式,这里稍微封装了下:
1、get方式,主要针对的是简单的请求,只需要传递url发起get请求。知乎的调用这个就可以了。function get(url, callback) {
return https.get(url,
function(response) {
var body = '';
response.on('data',
function(data) {
body += data;
});
response.on('end',
function() {
callback(body);
});
});
}
2、querst方式,不但可以发起get请求,也可以发起post请求,还可以修改端口,请求header。这个主要是针对限制比较多的百度爬虫。function request(options, callback) {
// var postData = qs.stringify({});
var body, req = https.request(options, (res) = >{
console.log('STATUS: ' + res.statusCode);
// console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data',
function(chunk) {
body += chunk;
});
res.on('end',
function() {
callback(body)
});
});
req.on('error',
function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
// req.write(postData);
req.end();
}
function baiduRequset(pageNo, pageSize, keyword) {
var path = '/s?' + qs.stringify({
ie: 'utf-8',
f: 8,
rsv_bp: 1,
tn: 'baidu',
rn: pageSize,
pn: pageNo * pageSize,
wd: keyword
}),
options = {
hostname: 'www.baidu.com',
port: 443,
path: path,
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
}
};
request(options,
function(body) {
saveFile(pageNo, keyword, body);
showBaiduResult(pageNo, body);
});
}
数据解释
抓取数据之后,我们需要做的就是调用cheerio,以jquery获取dom内容的方式获取结果,并显示出来,当然也可以保存文件或数据库。/**
* 显示结果
* @param {[type]} pageNo [description]
* @param {[type]} body [description]
* @return {[type]} [description]
*/
function showBaiduResult(pageNo, body) {
var title, summary, link, reg = /]+>/g,
$ = cheerio.load(body, {
decodeEntities: false
});
$('#content_left .result').each(function(i, item) {
var $a = $(item).find('h3 a');
title = $a.html();
link = $a.attr('href');
summary = $(item).find('.c-abstract').html();
if (title) {
console.log(`第$ {
pageNo + 1
}页第$ {
i + 1
}条`);
console.log(`link: $ {
link
}`.green);
// console.log(`title: ${title}`);
console.log('title: ');
ouputColor(title);
if (summary) {
// console.log(`summary: ${summary}`);
console.log('summary: ');
ouputColor(summary);
}
}
console.log('------------------------------');
console.log('');
});
}
// 知乎
exports.zhihuSearch = function(keyword, cb) {
get('https://www.zhihu.com/search?type=content&q=' + keyword,
function(content) {
var title, summary;
var $ = cheerio.load(content, {
decodeEntities: false
});
saveFile(0, keyword, content);
$('.list .item').each(function(i, item) {
title = $(item).find('.js-title-link').html();
summary = $(item).find('.summary').html();
if (title) {
// title=(''+title).replace(/]+>/g,'');
// summary=(''+summary).replace(/<.>/g,'');
console.log('title: ');
ouputColor(title);
if (summary) {
console.log('summary: ');
ouputColor(summary);
}
}
console.log('------------------------------');
console.log('');
});
});
};
执行爬虫
功能完成后,先试验一下抓取知乎的内容grab zh webgl
抓取到的html文件保存在download文件夹,同时在命令行显示抓取结果。