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获得选中文本内容的方法
Dec 02 Javascript
JavaScript 计算当天是本年本月的第几周
Mar 22 Javascript
JQuery中的ready函数冲突的解决方法
May 17 Javascript
jQuery弹出层始终垂直居中相对于屏幕或当前窗口
Apr 01 Javascript
Javascript图片上传前的本地预览实例
Jun 16 Javascript
JavaScript中的继承之类继承
May 01 Javascript
Bootstrap table两种分页示例
Dec 23 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
Mar 09 Javascript
深入探究node之Transform
Jul 20 Javascript
详解vue-cli快速构建vue应用并实现webpack打包
Dec 13 Javascript
node.js监听文件变化的实现方法
Apr 17 Javascript
JavaScript原型链详解
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
社区(php&amp;&amp;mysql)二
2006/10/09 PHP
实用函数8
2007/11/08 PHP
解析PHP中$_FILES的使用以及注意事项
2013/07/05 PHP
php中隐形字符65279(utf-8的BOM头)问题
2014/08/16 PHP
php实现统计IP数及在线人数的示例代码
2020/07/22 PHP
JavaScript中for-in遍历方式示例介绍
2014/02/11 Javascript
JavaScript比较两个对象是否相等的方法
2015/02/06 Javascript
深入分析下javascript中的[]()+!
2015/07/07 Javascript
Css3制作变形与动画效果
2015/07/24 Javascript
使用jquery+CSS3实现仿windows10开始菜单的下拉导航菜单特效
2015/09/24 Javascript
概述jQuery的元素筛选
2016/11/23 Javascript
详解微信小程序开发之下拉刷新 上拉加载
2016/11/24 Javascript
微信小程序中实现一对多发消息详解及实例代码
2017/02/14 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
angular4 如何在全局设置路由跳转动画的方法
2017/08/30 Javascript
详解Vue webapp项目通过HBulider打包原生APP
2018/06/29 Javascript
详解vue.js根据不同环境(正式、测试)打包到不同目录
2018/07/13 Javascript
js实现数字滚动特效
2019/12/16 Javascript
vue.js实现简单的计算器功能
2020/02/22 Javascript
基于react项目打包css引用路径错误解决方案
2020/10/28 Javascript
Python linecache.getline()读取文件中特定一行的脚本
2008/09/06 Python
Python下singleton模式的实现方法
2014/07/16 Python
跟老齐学Python之有容乃大的list(3)
2014/09/15 Python
python回溯法实现数组全排列输出实例分析
2015/03/17 Python
python 解决动态的定义变量名,并给其赋值的方法(大数据处理)
2018/11/10 Python
对python创建及引用动态变量名的示例讲解
2018/11/10 Python
PyCharm 解决找不到新打开项目的窗口问题
2021/01/15 Python
在使用非全零作为空指针内部表达的机器上, NULL是如何定义
2014/11/09 面试题
工程造价与管理专业应届生求职信
2013/11/23 职场文书
会计出纳员的自我评价
2014/01/15 职场文书
总经理岗位职责范本
2014/02/02 职场文书
2015年为民办实事工作总结
2015/05/26 职场文书
春节晚会开场白
2015/05/29 职场文书
如何写好一份优秀的工作总结?
2019/06/21 职场文书
学校就业保障协议书
2019/06/24 职场文书
使用refresh_token实现无感刷新页面
2022/04/26 Javascript