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 插件 web2.0分格的分页脚本,可用于ajax无刷新分页
Dec 25 Javascript
HTML代码中标签的全部属性 中文注释说明
Mar 26 Javascript
jQuery DIV弹出效果实现代码
Jul 03 Javascript
JavaScript调用客户端的可执行文件(示例代码)
Nov 28 Javascript
JavaScript实现生成GUID(全局统一标识符)
Sep 05 Javascript
使用javascript获取页面名称
Dec 23 Javascript
jquery实现点击页面计算点击次数
Jan 23 Javascript
JavaScript继承模式粗探
Jan 12 Javascript
解析浏览器端的AJAX缓存机制
Jun 21 Javascript
vue中计算属性(computed)、methods和watched之间的区别
Jul 27 Javascript
最通俗易懂的javascript变量提升详解
Aug 05 Javascript
vue 实现单选框设置默认选中值
Nov 07 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
ftp类(example.php)
2006/10/09 PHP
一个简单计数器的源代码
2006/10/09 PHP
PHP中读写文件实现代码
2011/10/20 PHP
解析PHP中的正则表达式以及模式匹配
2013/06/19 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
2014/01/07 PHP
详解php用curl调用接口方法,get和post两种方式
2017/01/13 PHP
PHP程序守护进程化实现方法详解
2020/07/16 PHP
html数组字符串拼接的最快方法
2009/09/16 Javascript
JavaScript浏览器选项卡效果
2010/08/25 Javascript
探寻Javascript执行效率问题
2014/11/12 Javascript
js实现数字每三位加逗号的方法
2015/02/05 Javascript
用jQuery实现圆点图片轮播效果
2017/03/19 Javascript
详解js正则表达式验证时间格式xxxx-xx-xx形式
2018/02/09 Javascript
jquery实现的简单轮播图功能【适合新手】
2018/08/17 jQuery
vue过滤器用法实例分析
2019/03/15 Javascript
基于Vue2-Calendar改进的日历组件(含中文使用说明)
2019/04/14 Javascript
详解ES6 export default 和 import语句中的解构赋值
2019/05/28 Javascript
js实现简单分页导航栏效果
2019/06/28 Javascript
微信小程序 wx:for遍历循环使用实例解析
2019/09/09 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
Python multiprocessing模块中的Pipe管道使用实例
2015/04/11 Python
Python设计模式之状态模式原理与用法详解
2019/01/15 Python
不到20行实现Python代码即可制作精美证件照
2020/04/24 Python
Python numpy大矩阵运算内存不足如何解决
2020/11/19 Python
关于box-sizing的全面理解
2016/07/28 HTML / CSS
网页中的电话号码如何实现一键直呼效果_附示例
2016/03/15 HTML / CSS
综合实践教学反思
2014/01/31 职场文书
入党自我评价范文
2014/02/02 职场文书
反邪教宣传工作方案
2014/05/07 职场文书
贷款委托书
2014/08/01 职场文书
企业贷款委托书格式
2014/09/12 职场文书
2015年学生会部门工作总结
2015/04/21 职场文书
少年犯观后感
2015/06/11 职场文书
初中政教处工作总结
2015/08/12 职场文书
导游词之太湖
2019/10/08 职场文书
Python实战之实现简易的学生选课系统
2021/05/25 Python