网络爬虫 (又被称为网页蜘蛛, 网络机器人, 在 FOAF 社区中间, 更经常的称为网页追逐者), 是一种按照一定的规则, 自动地抓取万维网信息的程序或者脚本. 另外一些不常使用的名字还有蚂蚁, 自动索引, 模拟程序或者蠕虫.
网络爬虫基本就由如下部分组成:
程序入口
请求模块
数据解释
下面我们来看一下如何使用 Node.JS 实现网络爬虫.
程序入口
开始配置和初始化 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 文件夹, 同时在命令行显示抓取结果.
来源: http://www.css88.com/qa/node-js/12054.html