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入门教程(11) js事件处理
Jan 31 Javascript
IE 当eval遇上function的处理
Aug 09 Javascript
JQuery动画和停止动画实例代码
Mar 01 Javascript
ComboBox 和 DateField 在IE下消失的解决方法
Aug 30 Javascript
Jquery Ajax解析XML数据(同步及异步调用)简单实例
Feb 12 Javascript
JavaScript数组函数unshift、shift、pop、push使用实例
Aug 27 Javascript
JS中的form.submit()不能提交表单的错误原因
Oct 08 Javascript
js实现Select下拉框具有输入功能的方法
Feb 06 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
Oct 10 Javascript
微信小程序之小豆瓣图书实例
Nov 30 Javascript
详解angular2实现ng2-router 路由和嵌套路由
Mar 24 Javascript
从组件封装看Vue的作用域插槽的实现
Feb 12 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
PHP下MAIL的另一解决方案
2006/10/09 PHP
js面向对象 多种创建对象方法小结
2012/05/21 Javascript
javascript学习笔记(十八) 获得页面中的元素代码
2012/06/20 Javascript
js 获取坐标 通过JS得到当前焦点(鼠标)的坐标属性
2013/01/04 Javascript
js正文内容高亮效果的实现方法
2013/06/30 Javascript
jquery遍历checkbox介绍
2014/02/21 Javascript
非常实用的12个jquery代码片段
2015/11/02 Javascript
js实现下拉列表选中某个值的方法(3种方法)
2015/12/17 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
Javascript仿京东放大镜的效果
2017/03/01 Javascript
如何在 Vue.js 中使用第三方js库
2017/04/25 Javascript
Vue内容分发slot(全面解析)
2017/08/19 Javascript
JavaScript实现HTML5游戏断线自动重连的方法
2017/09/18 Javascript
vue-cli项目根据线上环境分别打出测试包和生产包
2018/05/23 Javascript
jQuery实现菜单的显示和隐藏功能示例
2018/07/24 jQuery
解决angularjs service中依赖注入$scope报错的问题
2018/10/02 Javascript
微信小程序自定义toast的实现代码
2018/11/16 Javascript
基于layui内置模块(element常用元素的操作)
2019/09/20 Javascript
node.js使用fs读取文件出错的解决方案
2019/10/23 Javascript
JS实现随机抽选获奖者
2019/11/07 Javascript
jQuery-App输入框实现实时搜索
2020/11/19 jQuery
js实现鼠标拖曳效果
2020/12/30 Javascript
[00:47]DOTA2荣耀之路6:玩不了啦!
2018/05/30 DOTA
python的绘图工具matplotlib使用实例
2014/07/03 Python
Python编程实现双链表,栈,队列及二叉树的方法示例
2017/11/01 Python
python 读取文件并替换字段的实例
2018/07/12 Python
selenium处理元素定位点击无效问题
2019/06/12 Python
记一次python 爬虫爬取深圳租房信息的过程及遇到的问题
2020/11/24 Python
python 使用csv模块读写csv格式文件的示例
2020/12/02 Python
应届生求职信写作技巧
2013/10/24 职场文书
多媒体教室标语
2014/06/26 职场文书
学习优秀党务工作者先进事迹材料思想报告
2014/09/17 职场文书
综治维稳工作汇报
2014/10/27 职场文书
2014年检察院个人工作总结
2014/12/09 职场文书
高中生个性发展自我评价
2015/03/09 职场文书
《正面管教》读后有感:和善而坚定的旅程
2019/12/19 职场文书