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 相关文章推荐
IE6,IE7,IE8下使用Javascript记录光标选中范围(已补全)
Aug 28 Javascript
javascript实现图片切换的幻灯片效果源代码
Dec 12 Javascript
javascript数组去重的方法汇总
Apr 14 Javascript
freemarker判断对象是否为空的方法
Aug 13 Javascript
简单了解Backbone.js的Model模型以及View视图的源码
Feb 14 Javascript
全面了解JS中的匿名函数
Jun 29 Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
Jul 07 Javascript
vue使用Element组件时v-for循环里的表单项验证方法
Jun 28 Javascript
微信小程序实现无限滚动列表
May 29 Javascript
fastadmin中调用js的方法
May 14 Javascript
JS sort排序详细使用方法示例解析
Sep 27 Javascript
详解JavaScript中的链式调用
Nov 27 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
实现“上一页”和“下一页按钮
2006/10/09 PHP
PHP 递归效率分析
2009/11/24 PHP
PHP求最大子序列和的算法实现
2011/06/24 PHP
linux下使用crontab实现定时PHP计划任务失败的原因分析
2014/07/05 PHP
学习PHP Cookie处理函数
2016/08/09 PHP
浅谈PHP定义命令空间的几个注意点(推荐)
2016/10/29 PHP
php使用crypt()函数进行加密
2017/06/08 PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
2020/02/21 PHP
关于onScroll事件在IE6下每次滚动触发三次bug说明
2011/09/21 Javascript
JavaScript生成GUID的多种算法小结
2013/08/18 Javascript
js实现遮罩层弹出框的方法
2015/01/15 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
JS判断数组那点事
2017/10/10 Javascript
如何开发出更好的JavaScript模块
2017/12/22 Javascript
微信小程序如何获取用户手机号
2018/01/26 Javascript
vue使用ajax获取后台数据进行显示的示例
2018/08/09 Javascript
详解如何解决Vue和vue-template-compiler版本之间的问题
2018/09/17 Javascript
微信小程序实现时间预约功能
2018/11/27 Javascript
[55:45]DOTA2上海特级锦标赛D组败者赛 Liquid VS COL第一局
2016/02/28 DOTA
使用Python神器对付12306变态验证码
2016/01/05 Python
Python Xml文件添加字节属性的方法
2018/03/31 Python
Python使用pandas处理CSV文件的实例讲解
2018/06/22 Python
python ipset管理 增删白名单的方法
2019/01/14 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
2019/01/26 Python
在Python中居然可以定义两个同名通参数的函数
2019/01/31 Python
将Python文件打包成.EXE可执行文件的方法
2019/08/11 Python
python用pip install时安装失败的一系列问题及解决方法
2020/02/24 Python
Django项目uwsgi+Nginx保姆级部署教程实现
2020/04/19 Python
Idea安装python显示无SDK问题解决方案
2020/08/12 Python
美国标志性加大尺码时装品牌:Ashley Stewart
2016/12/15 全球购物
美国名表在线商城:Ashford(支持中文)
2019/09/24 全球购物
What is the purpose of Void class? Void类的作用是什么?
2016/10/31 面试题
护理自荐信范文
2013/10/05 职场文书
民主生活会发言材料
2014/10/20 职场文书
2014年合同管理工作总结
2014/12/02 职场文书
Java详细解析==和equals的区别
2022/04/07 Java/Android