Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法


Posted in Javascript onSeptember 20, 2017

接着这篇文章Node.js+jade抓取博客所有文章生成静态html文件的实例继续,在这篇文章中实现了采集与静态文件的生成,在实际的采集项目中, 应该是先入库再选择性的生成静态文件。

那么我选择的数据库是mongodb,为什么用这个数据库,因为这个数据库是基于集合,数据的操作基本是json,与dom模块cheerio具有非常大的亲和力,cheerio处理过滤出来的数据,可以直接插入mongodb,不需要经过任何的处理,非常的便捷,当然跟node.js的亲和力那就不用说了,更重要的是,性能很棒。这篇文章我就不具体写mongodb的基本用法,到时候会另起文章从0开始写mongodb基本常用用法.先看下入库的效果与生成静态文件的效果:

Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法

Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法

我在这个阶段,把爬虫分离成2个模块,采集入库( crawler.js ), 生成静态文件(makeHtml.js).

crawler.js:

var http = require('http');
var cheerio = require('cheerio');
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
var DB_URL = 'mongodb://localhost:27017/crawler';

var aList = []; //博客文章列表信息
var aUrl = []; //博客所有的文章url

var db = mongoose.createConnection(DB_URL);
db.on('connected', function (err) {
 if (err) {
  console.log(err);
 } else {
  console.log('db connected success');
 }
});
var Schema = mongoose.Schema;
var arcSchema = new Schema({
 id: Number, //文章id
 title: String, //文章标题
 url: String, //文章链接
 body: String, //文章内容
 entry: String, //摘要
 listTime: Date //发布时间
});
var Article = db.model('Article', arcSchema);

function saveArticle(arcInfo) {
 var arcModel = new Article(arcInfo);
 arcModel.save(function (err, result) {
  if (err) {
   console.log(err);
  } else {
   console.log(`${arcInfo['title']} 插入成功`);
  }
 });
}

function filterArticle(html) {
 var $ = cheerio.load(html);
 var arcDetail = {};
 var title = $("#cb_post_title_url").text();
 var href = $("#cb_post_title_url").attr("href");
 var re = /\/(\d+)\.html/;
 var id = href.match(re)[1];
 var body = $("#cnblogs_post_body").html();
 return {
  id: id,
  title: title,
  url: href,
  body: body
 };
}

function crawlerArc(url) {
 var html = '';
 var str = '';
 var arcDetail = {};
 http.get(url, function (res) {
  res.on('data', function (chunk) {
   html += chunk;
  });
  res.on('end', function () {
   arcDetail = filterArticle(html);
   saveArticle(arcDetail);
   if ( aUrl.length ) {
    setTimeout(function () {
     if (aUrl.length) {
      crawlerArc(aUrl.shift());
     }
    }, 100);
   }else {
    console.log( '采集任务完成' );
    return;
   }
  });
 });
}

function filterHtml(html) {
 var $ = cheerio.load(html);
 var arcList = [];
 var aPost = $("#content").find(".post-list-item");
 aPost.each(function () {
  var ele = $(this);
  var title = ele.find("h2 a").text();
  var url = ele.find("h2 a").attr("href");
  ele.find(".c_b_p_desc a").remove();
  var entry = ele.find(".c_b_p_desc").text();
  ele.find("small a").remove();
  var listTime = ele.find("small").text();
  var re = /\d{4}-\d{2}-\d{2}\s*\d{2}[:]\d{2}/;
  listTime = listTime.match(re)[0];

  arcList.push({
   title: title,
   url: url,
   entry: entry,
   listTime: listTime
  });
 });
 return arcList;
}

function nextPage(html) {
 var $ = cheerio.load(html);
 var nextUrl = $("#pager a:last-child").attr('href');
 if (!nextUrl) return getArcUrl(aList);
 var curPage = $("#pager .current").text();
 if (!curPage) curPage = 1;
 var nextPage = nextUrl.substring(nextUrl.indexOf('=') + 1);
 if (curPage < nextPage) crawler(nextUrl);
}

function crawler(url) {
 http.get(url, function (res) {
  var html = '';
  res.on('data', function (chunk) {
   html += chunk;
  });
  res.on('end', function () {
   aList.push(filterHtml(html));
   nextPage(html);
  });
 });
}

function getArcUrl(arcList) {
 for (var key in arcList) {
  for (var k in arcList[key]) {
   aUrl.push(arcList[key][k]['url']);
  }
 }
 crawlerArc(aUrl.shift());
}

var url = 'http://www.cnblogs.com/ghostwu/';
crawler(url);

其他的核心模块没有怎么改动,主要增加了数据库连接,数据库创建,集合创建( 集合相当于关系型数据库中的表 ),Schema( 相当于关系型数据库的表结构 ).

mongoose操作数据库( save:插入数据 ).分离了文件生成模块.

makeHtml.js文件

var fs = require('fs');
var jade = require('jade');

var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
var DB_URL = 'mongodb://localhost:27017/crawler';

var allArc = [];
var count = 0;

var db = mongoose.createConnection(DB_URL);
db.on('connected', function (err) {
 if (err) {
  console.log(err);
 } else {
  console.log('db connected success');
 }
});
var Schema = mongoose.Schema;
var arcSchema = new Schema({
 id: Number, //文章id
 title: String, //文章标题
 url: String, //文章链接
 body: String, //文章内容
 entry: String, //摘要
 listTime: Date //发布时间
});
var Article = db.model('Article', arcSchema);

function makeHtml(arcDetail) {
 str = jade.renderFile('./views/layout.jade', arcDetail);
 ++count;
 fs.writeFile('./html/' + count + '.html', str, function (err) {
  if (err) {
   console.log(err);
  }
  console.log( `${arcDetail['id']}.html创建成功` + count );
  if ( allArc.length ){
   setTimeout( function(){
    makeHtml( allArc.shift() );
   }, 100 );
  }
 });
}

function getAllArc(){
 Article.find( {}, function( err, arcs ){
  allArc = arcs;
  makeHtml( allArc.shift() );
 } ).sort( { 'id' : 1 } );
}
getAllArc();

以上这篇Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 新手24条实用建议[TUTS+]
Jun 21 Javascript
jQuery中fadeIn、fadeOut、fadeTo的使用方法(图片显示与隐藏)
May 08 Javascript
JS简单实现动画弹出层效果
May 05 Javascript
JavaScript面试开发常用的知识点总结
Aug 08 Javascript
JS对HTML表格进行增删改操作
Aug 22 Javascript
jQuery EasyUI tree增加搜索功能的实现方法
Apr 27 jQuery
基于js 本地存储(详解)
Aug 16 Javascript
node.js将MongoDB数据同步到MySQL的步骤
Dec 10 Javascript
基于vue v-for 循环复选框-默认勾选第一个的实现方法
Mar 03 Javascript
JS简单实现动态添加HTML标记的方法示例
Apr 08 Javascript
详解vue 路由跳转四种方式 (带参数)
Apr 28 Javascript
js瀑布流布局的实现
Jun 28 Javascript
jquery 一键复制到剪切板的实例
Sep 20 #jQuery
angularjs利用directive实现移动端自定义软键盘的示例
Sep 20 #Javascript
集合Bootstrap自定义confirm提示效果
Sep 19 #Javascript
微信小程序使用Socket的实例
Sep 19 #Javascript
vue基于Element构建自定义树的示例代码
Sep 19 #Javascript
Vue2.0父组件与子组件之间的事件发射与接收实例代码
Sep 19 #Javascript
详解ES6之async+await 同步/异步方案
Sep 19 #Javascript
You might like
浅析Dos下运行php.exe,出现没有找到php_mbstring.dll 错误的解决方法
2013/06/29 PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
2016/02/26 PHP
PHP入门教程之数学运算技巧总结
2016/09/11 PHP
php如何把表单内容提交到数据库
2019/07/08 PHP
php和html的区别点详细总结
2019/09/24 PHP
jQuery EasyUI中对表格进行编辑的实现代码
2010/06/10 Javascript
Javascript图像处理—平滑处理实现原理
2012/12/28 Javascript
javascript中的循环语句for语句深入理解
2014/04/04 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
JavaScript 限制文本框不可输入英文单双引号的方法
2016/12/20 Javascript
JS正则表达式修饰符中multiline(/m)用法分析
2016/12/27 Javascript
js实现文字无缝向上滚动
2017/02/16 Javascript
基于vue.js实现侧边菜单栏
2017/03/20 Javascript
前端自动化开发之Node.js的环境搭建教程
2017/04/01 Javascript
JS实现table表格内针对某列内容进行即时搜索筛选功能
2018/05/11 Javascript
详解JavaScript实现动态的轮播图效果
2019/04/29 Javascript
json数据格式常见操作示例
2019/06/13 Javascript
ES6基础之字符串和函数的拓展详解
2019/08/22 Javascript
layui的表单验证支持ajax判断用户名是否重复的实例
2019/09/06 Javascript
vue更改数组中的值实例代码详解
2020/02/07 Javascript
在Python中处理字符串之isdecimal()方法的使用
2015/05/20 Python
深入浅析Python中list的复制及深拷贝与浅拷贝
2018/09/03 Python
搞清楚 Python traceback的具体使用方法
2019/05/13 Python
pytorch-神经网络拟合曲线实例
2020/01/15 Python
实现Python3数组旋转的3种算法实例
2020/09/16 Python
python 实现图片批量压缩的示例
2020/12/18 Python
全球酒店预订网站:Hotels.com
2016/08/10 全球购物
香蕉共和国Banana Republic官网:美国GAP旗下偏贵族风格服饰品牌
2016/11/21 全球购物
中国领先的专业家电网购平台:国美在线
2016/12/25 全球购物
助人为乐模范事迹材料
2014/06/02 职场文书
跳蚤市场口号
2014/06/13 职场文书
运动会演讲稿300字
2014/08/25 职场文书
房地产经营管理专业自荐信
2014/09/02 职场文书
离婚撤诉申请书范本
2015/05/18 职场文书
“爱眼护眼,提前预防近视”倡议书3篇
2019/10/30 职场文书
Python echarts实现数据可视化实例详解
2022/03/03 Python