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实现禁止后退的方法
Dec 27 Javascript
jQuery弹出(alert)select选择的值
Apr 21 Javascript
Jquery在指定DIV加载HTML示例代码
Feb 17 Javascript
JS控制弹出新页面窗口位置和大小的方法
Mar 02 Javascript
JS日期格式化之javascript Date format
Oct 01 Javascript
node.js入门实例helloworld详解
Dec 23 Javascript
React实现双向绑定示例代码
Sep 19 Javascript
Javascript中for循环语句的几种写法总结对比
Jan 23 Javascript
利用Blob进行文件上传的完整步骤
Aug 02 Javascript
关于vue v-for循环解决img标签的src动态绑定问题
Sep 18 Javascript
vue封装swiper代码实例解析
Oct 08 Javascript
JavaScript 中for/of,for/in 的详细介绍
Nov 17 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最常用的2种设计模式工厂模式和单例模式介绍
2012/08/14 PHP
javascript中巧用“闭包”实现程序的暂停执行功能
2007/04/04 Javascript
通过JavaScript使Div居中并随网页大小改变而改变
2013/06/24 Javascript
编写高效jQuery代码的4个原则和5个技巧
2014/04/24 Javascript
字段太多jquey快速清空表单内容方法
2014/08/21 Javascript
node.js中的dns.getServers方法使用说明
2014/12/08 Javascript
js实现点击切换TAB标签实例
2015/08/21 Javascript
30分钟快速掌握Bootstrap框架
2016/05/24 Javascript
javascript判断firebug是否开启的方法
2016/11/23 Javascript
JS jQuery使用正则表达式去空字符的简单实现代码
2017/05/20 jQuery
js实现动态改变radio状态的方法
2018/02/28 Javascript
vue里input根据value改变背景色的实例
2018/09/29 Javascript
element ui table(表格)实现点击一行展开功能
2018/12/04 Javascript
JQuery animate动画应用示例
2019/05/14 jQuery
Vue路由管理器Vue-router的使用方法详解
2020/02/05 Javascript
[08:47]2018国际邀请赛 OG战队举杯时刻
2018/08/29 DOTA
Python类的继承和多态代码详解
2017/12/27 Python
Python实现读取字符串按列分配后按行输出示例
2018/04/17 Python
Django配置celery(非djcelery)执行异步任务和定时任务
2018/07/16 Python
关于python字符串方法分类详解
2019/08/20 Python
在Pytorch中计算卷积方法的区别详解(conv2d的区别)
2020/01/03 Python
Python 如何批量更新已安装的库
2020/05/26 Python
通过实例解析python and和or使用方法
2020/11/14 Python
哄娃神器4moms商店:美国婴童用品品牌
2019/03/07 全球购物
离婚协议书范本样本
2014/08/19 职场文书
班子个人四风问题整改措施
2014/10/04 职场文书
死者家属慰问信
2015/03/24 职场文书
亮剑观后感300字
2015/06/05 职场文书
2016党员党章学习心得体会
2016/01/14 职场文书
导游词之天下银坑景区
2019/11/21 职场文书
css3实现的加载动画效果
2021/04/07 HTML / CSS
如何用JavaScript检测当前浏览器是无头浏览器
2021/04/27 Javascript
Django cookie和session的应用场景及如何使用
2021/04/29 Python
GO语言字符串处理函数之处理Strings包
2022/04/14 Golang
Windows server 2012 配置Telnet以及用法详解
2022/04/28 Servers
MySQL数据库表约束讲解
2022/06/21 MySQL