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 特殊字符串
Feb 25 Javascript
javascript 无提示关闭窗口脚本
Aug 17 Javascript
jQuery学习笔记 更改jQuery对象
Sep 19 Javascript
jquery焦点图片切换(数字标注/手动/自动播放/横向滚动)
Jan 24 Javascript
jquery.blockUI.js上传滚动等待效果实现思路及代码
Mar 18 Javascript
js实现精美的图片跟随鼠标效果实例
May 16 Javascript
javascript+canvas实现刮刮卡抽奖效果
Jul 29 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
编写高性能Javascript代码的N条建议
Oct 12 Javascript
JavaScript ES6中的简写语法总结与使用技巧
Dec 30 Javascript
vue element upload实现图片本地预览
Aug 20 Javascript
原生js实现俄罗斯方块
Oct 20 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
WML,Apache,和 PHP 的介绍
2006/10/09 PHP
php 中英文语言转换类代码
2011/08/11 PHP
PHP 自定义错误处理函数trigger_error()
2013/03/26 PHP
深入php var_dump()函数的详解
2013/06/05 PHP
php日历制作代码分享
2014/01/20 PHP
PHP批量删除、清除UTF-8文件BOM头的代码实例
2014/04/14 PHP
php上传大文件设置方法
2016/04/14 PHP
PHP实现负载均衡下的session共用功能
2018/04/17 PHP
js实现屏蔽默认快捷键调用自定义事件示例
2013/06/18 Javascript
js控制表单操作的常用代码小结
2013/08/15 Javascript
JS简单实现文件上传实例代码(无需插件)
2013/11/15 Javascript
js判断某个方法是否存在实例代码
2015/01/10 Javascript
纯Javascript实现ping功能的方法
2015/03/20 Javascript
浅谈Jquery为元素绑定事件
2015/04/27 Javascript
jQuery实现带玻璃流光质感的手风琴特效
2015/11/20 Javascript
Bootstrap入门书籍之(五)导航条、分页导航
2016/02/17 Javascript
jQuery实现的纵向下拉菜单实例详解【附demo源码下载】
2016/07/09 Javascript
基于JSON格式数据的简单jQuery幻灯片插件(jquery-slider)
2016/08/10 Javascript
浅谈js中字符和数组一些基本算法题
2016/08/15 Javascript
node.js请求HTTPS报错:UNABLE_TO_VERIFY_LEAF_SIGNATURE\的解决方法
2016/12/18 Javascript
boostrapTable的refresh和refreshOptions区别浅析
2017/01/22 Javascript
对于Javascript 执行上下文的全面了解
2017/09/05 Javascript
vue-cli初始化项目中使用less的方法
2018/08/09 Javascript
js重写alert事件(避免alert弹框标题出现网址)
2020/12/04 Javascript
举例讲解Python面相对象编程中对象的属性与类的方法
2016/01/19 Python
浅谈python import引入不同路径下的模块
2017/07/11 Python
Python提取支付宝和微信支付二维码的示例代码
2019/02/15 Python
英国高街电视:High Street TV
2018/05/22 全球购物
Foot Locker英国官网:美国知名运动产品零售商
2019/02/21 全球购物
高校自主招生自荐信
2013/12/09 职场文书
工程质量月活动方案
2014/02/19 职场文书
黄金搭档广告词
2014/03/21 职场文书
违反交通法规检讨书
2014/09/10 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
幼儿教师年度个人总结
2015/02/05 职场文书
Vue vee-validate插件的简单使用
2021/06/22 Vue.js