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 相关文章推荐
锋利的jQuery 要点归纳(一) jQuery选择器
Mar 21 Javascript
JQuery浮动DIV提示信息并自动隐藏的代码
Aug 29 Javascript
Javascript监视变量变化的方法
Jun 09 Javascript
如何解决谷歌浏览器下jquery无法获取图片的尺寸
Sep 10 Javascript
jquery验证手机号是否正确实例讲解
Nov 17 Javascript
基于JavaScript实现全屏透明遮罩div层锁屏效果
Jan 26 Javascript
Angularjs中ng-repeat-start与ng-repeat-end的用法实例介绍
Dec 31 Javascript
angularjs 实现带查找筛选功能的select下拉框实例
Jan 11 Javascript
利用 spin.js 生成等待效果(js 等待效果)
Jun 25 Javascript
javascript面向对象三大特征之多态实例详解
Jul 24 Javascript
使用layui日期控件laydate对开始和结束时间进行联动控制的方法
Sep 06 Javascript
微信小程序淘宝首页双排图片布局排版代码(推荐)
Oct 29 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
curl和libcurl的区别简介
2015/07/01 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
2016/11/21 PHP
php实现的二分查找算法示例
2017/06/20 PHP
php实现获取农历(阴历)、节日、节气的类与用法示例
2017/11/20 PHP
phpinfo无法显示的原因及解决办法
2019/02/15 PHP
很酷的javascript loading效果代码
2008/06/18 Javascript
javascript中attribute和property的区别详解
2014/06/05 Javascript
NodeJS使用jQuery选择器操作DOM
2015/02/13 NodeJs
ionic js 模型 $ionicModal 可以遮住用户主界面的内容框
2016/06/06 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
2016/07/15 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
jquery控制页面的展开和隐藏实现方法(推荐)
2016/10/15 Javascript
ES6 系列之 WeakMap的使用示例
2018/08/06 Javascript
在vue中使用echarts图表实例代码详解
2018/10/22 Javascript
vue微信分享出来的链接点开是首页问题的解决方法
2018/11/28 Javascript
详解可以用在VS Code中的正则表达式小技巧
2019/05/14 Javascript
Vue实例的对象参数options的几个常用选项详解
2019/11/08 Javascript
python通过ssh-powershell监控windows的方法
2015/06/02 Python
Swift中的协议(protocol)学习教程
2016/07/08 Python
快速入手Python字符编码
2016/08/03 Python
解决Mac安装scrapy失败的问题
2018/06/13 Python
在matplotlib中改变figure的布局和大小实例
2020/04/23 Python
Python如何测试stdout输出
2020/08/10 Python
Python wordcloud库安装方法总结
2020/12/31 Python
美国时装品牌:Nautica(诺帝卡)
2016/08/28 全球购物
Everlast官网:拳击、综合格斗和健身相关的体育用品
2020/08/03 全球购物
面向对象设计的原则是什么
2013/02/13 面试题
给排水专业应届生求职信
2013/10/12 职场文书
项目管理计划书
2014/01/09 职场文书
竞选班长演讲稿400字
2014/08/22 职场文书
教师岗位职责
2015/02/03 职场文书
综合素质评价个性与发展自我评价
2015/03/06 职场文书
观看焦裕禄观后感
2015/06/09 职场文书
农村老人去世追悼词
2015/06/23 职场文书
OpenCV中resize函数插值算法的实现过程(五种)
2021/06/05 Python