Node.js+jade抓取博客所有文章生成静态html文件的实例


Posted in Javascript onSeptember 19, 2017

这篇文章,我们就把上文中采集到的所有文章列表的信息整理一下,开始采集文章并且生成静态html文件了.先看下我的采集效果,我的博客目前77篇文章,1分钟不到就全部采集生成完毕了,这里我截了部分的图片,文件名用文章的id生成的,生成的文章,我写了一个简单的静态模板,所有的文章都是根据这个模板生成的.

项目结构:

Node.js+jade抓取博客所有文章生成静态html文件的实例

Node.js+jade抓取博客所有文章生成静态html文件的实例

Node.js+jade抓取博客所有文章生成静态html文件的实例

好了,接下来,我们就来讲解下,这篇文章主要实现的功能:

1,抓取文章,主要抓取文章的标题,内容,超链接,文章id(用于生成静态html文件)

2,根据jade模板生成html文件

一、抓取文章如何实现?

非常简单,跟上文抓取文章列表的实现差不多

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 );
      str = jade.renderFile('./views/layout.jade', arcDetail );
      fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
        if( err ) {
          console.log( err );
        }
        console.log( 'success:' + url );
        if ( aUrl.length ) crawlerArc( aUrl.shift() );
      } );
    });
  });
}

参数url就是文章的地址,把文章的内容抓取完毕之后,调用filterArticle( html ) 过滤出需要的文章信息(id, 标题,超链接,内容),然后用jade的renderFile这个api,实现模板内容的替换,

模板内容替换完之后,肯定就需要生成html文件了, 所以用writeFile写入文件,写入文件时候,用id作为html文件名称。这就是生成一篇静态html文件的实现,

接下来就是循环生成静态html文件了, 就是下面这行:

if ( aUrl.length ) crawlerArc( aUrl.shift() );

aUrl保存的是我的博客所有文章的url, 每次采集完一篇文章之后,就把当前文章的url删除,让下一篇文章的url出来,继续采集

完整的实现代码server.js:

var fs = require( 'fs' );
var http = require( 'http' );
var cheerio = require( 'cheerio' );
var jade = require( 'jade' );

var aList = [];
var aUrl = [];

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,
    href : 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 );
      str = jade.renderFile('./views/layout.jade', arcDetail );
      fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
        if( err ) {
          console.log( err );
        }
        console.log( 'success:' + url );
        if ( aUrl.length ) crawlerArc( aUrl.shift() );
      } );
    });
  });
}

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 );

layout.jade文件:

doctype html
html
  head
    meta(charset='utf-8')
    title jade+node.js express
    link(rel="stylesheet", href='./css/bower_components/bootstrap/dist/css/bootstrap.min.css')
  body
    block header
      div.container
        div.well.well-lg
          h3 ghostwu的博客
          p js高手之路
    block container
      div.container
        h3
          a(href="#{href}" rel="external nofollow" ) !{title}
        p !{body}
    block footer
      div.container
        footer 版权所有 - by ghostwu

后续的打算:

1,采用mongodb入库

2,支持断点采集

3,采集图片

4,采集小说

等等....

以上这篇Node.js+jade抓取博客所有文章生成静态html文件的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript中的事件处理
Jan 16 Javascript
Tab页界面,用jQuery及Ajax技术实现
Sep 21 Javascript
jquery ajax 登录验证实现代码
Sep 23 Javascript
jquery uaMatch源代码
Feb 14 Javascript
javascript实现简单的二级联动
Mar 19 Javascript
JS和css实现检测移动设备方向的变化并判断横竖屏幕
May 25 Javascript
JavaScript设计模式经典之工厂模式
Feb 24 Javascript
Angular的MVC和作用域
Dec 26 Javascript
在vue项目中,将juery设置为全局变量的方法
Sep 25 Javascript
微信小程序实现上传word、txt、Excel、PPT等文件功能
May 23 Javascript
Vue根据条件添加click事件的方式
Nov 09 Javascript
前端vue+elementUI如何实现记住密码功能
Sep 20 Javascript
Node.js中Bootstrap-table的两种分页的实现方法
Sep 18 #Javascript
Node.js 使用递归实现遍历文件夹中所有文件
Sep 18 #Javascript
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
Sep 18 #Javascript
为什么我们要做三份 Webpack 配置文件
Sep 18 #Javascript
分析javascript中9 个常见错误阻碍你进步
Sep 18 #Javascript
十个免费的web前端开发工具详细整理
Sep 18 #Javascript
Redux 和 Mobx的选择问题:让你不再困惑!
Sep 18 #Javascript
You might like
php中判断字符串是否全是中文或含有中文的实现代码
2011/09/16 PHP
PHP实现取得HTTP请求的原文
2014/08/18 PHP
PHP中的随机性 你觉得自己幸运吗?
2016/01/22 PHP
PHP实现二维数组去重功能示例
2017/01/12 PHP
PHP实现判断数组是一维、二维或几维的方法
2017/02/06 PHP
修改jQuery.Autocomplete插件 支持中文输入法 避免TAB、ENTER键失效、导致表单提交
2009/10/11 Javascript
自写的jQuery异步加载数据添加事件
2014/05/15 Javascript
jQuery学习笔记之toArray()
2014/06/09 Javascript
JQuery1.8 判断元素是否绑定事件的方法
2014/07/10 Javascript
ECMAScript5(ES5)中bind方法使用小结
2015/05/07 Javascript
jQuery插件Timelinr 实现时间轴特效
2015/10/04 Javascript
JavaScript如何实现在文本框(密码框)输入提示语
2015/12/25 Javascript
BootStrap selectpicker
2016/06/20 Javascript
BootStrap Validator使用注意事项(必看篇)
2016/09/28 Javascript
使用BootStrap进行轮播图的制作
2017/01/06 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
原生js实现简单的链式操作
2017/07/04 Javascript
VUE v-model表单数据双向绑定完整示例
2019/01/21 Javascript
前后端常见的几种鉴权方式(小结)
2019/08/04 Javascript
jQuery实现简易QQ聊天框
2020/02/10 jQuery
[01:15]《辉夜杯》北京网鱼队巡礼
2015/10/26 DOTA
python实现2048小游戏
2015/03/30 Python
Python解决抛小球问题 求小球下落经历的距离之和示例
2018/02/01 Python
Python HTML解析模块HTMLParser用法分析【爬虫工具】
2019/04/05 Python
python使用opencv在Windows下调用摄像头实现解析
2019/11/26 Python
基于Python3.7.1无法导入Numpy的解决方式
2020/03/09 Python
pycharm最新激活码有效期至2100年(亲测可用)
2021/02/05 Python
英国婚礼商城:Wedding Mall
2019/11/02 全球购物
荷兰睡眠专家:Beter Bed
2020/11/23 全球购物
杭州联环马网络笔试题面试题
2013/08/04 面试题
护理专科毕业自荐信范文
2014/04/21 职场文书
授权委托书范本(单位)
2014/09/28 职场文书
政风行风评议心得体会
2014/10/21 职场文书
降价通知函
2015/04/23 职场文书
mysql 子查询的使用
2022/04/28 MySQL
springboot 全局异常处理和统一响应对象的处理方式
2022/06/28 Java/Android