最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js+jade抓取博客所有文章生成靜態(tài)html文件的實(shí)例

 更新時(shí)間:2017年09月19日 07:59:35   作者:ghostwu  
下面小編就為大家?guī)?lái)一篇Node.js+jade抓取博客所有文章生成靜態(tài)html文件的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

這篇文章,我們就把上文中采集到的所有文章列表的信息整理一下,開(kāi)始采集文章并且生成靜態(tài)html文件了.先看下我的采集效果,我的博客目前77篇文章,1分鐘不到就全部采集生成完畢了,這里我截了部分的圖片,文件名用文章的id生成的,生成的文章,我寫(xiě)了一個(gè)簡(jiǎn)單的靜態(tài)模板,所有的文章都是根據(jù)這個(gè)模板生成的.

項(xiàng)目結(jié)構(gòu):

好了,接下來(lái),我們就來(lái)講解下,這篇文章主要實(shí)現(xiàn)的功能:

1,抓取文章,主要抓取文章的標(biāo)題,內(nèi)容,超鏈接,文章id(用于生成靜態(tài)html文件)

2,根據(jù)jade模板生成html文件

一、抓取文章如何實(shí)現(xiàn)?

非常簡(jiǎn)單,跟上文抓取文章列表的實(shí)現(xiàn)差不多

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

參數(shù)url就是文章的地址,把文章的內(nèi)容抓取完畢之后,調(diào)用filterArticle( html ) 過(guò)濾出需要的文章信息(id, 標(biāo)題,超鏈接,內(nèi)容),然后用jade的renderFile這個(gè)api,實(shí)現(xiàn)模板內(nèi)容的替換,

模板內(nèi)容替換完之后,肯定就需要生成html文件了, 所以用writeFile寫(xiě)入文件,寫(xiě)入文件時(shí)候,用id作為html文件名稱。這就是生成一篇靜態(tài)html文件的實(shí)現(xiàn),

接下來(lái)就是循環(huán)生成靜態(tài)html文件了, 就是下面這行:

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

aUrl保存的是我的博客所有文章的url, 每次采集完一篇文章之后,就把當(dāng)前文章的url刪除,讓下一篇文章的url出來(lái),繼續(xù)采集

完整的實(shí)現(xiàn)代碼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 版權(quán)所有 - by ghostwu

后續(xù)的打算:

1,采用mongodb入庫(kù)

2,支持?jǐn)帱c(diǎn)采集

3,采集圖片

4,采集小說(shuō)

等等....

以上這篇Node.js+jade抓取博客所有文章生成靜態(tài)html文件的實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • node.js連接mongoose數(shù)據(jù)庫(kù)方法詳解

    node.js連接mongoose數(shù)據(jù)庫(kù)方法詳解

    之前我們都是通過(guò)shell來(lái)完成對(duì)數(shù)據(jù)庫(kù)的各種操作的,在開(kāi)發(fā)中大部分時(shí)候我們都需要通過(guò)程序來(lái)完成對(duì)數(shù)據(jù)庫(kù)的操作。而Mongoose就是一個(gè)讓我們可以通過(guò)Node來(lái)操作MongoDB的模塊
    2022-08-08
  • 我的Node.js學(xué)習(xí)之路(一)

    我的Node.js學(xué)習(xí)之路(一)

    這是一篇專門(mén)Node.js初學(xué)者學(xué)習(xí)筆記。該筆記將通過(guò)具體實(shí)例,教你一步步開(kāi)始Node.js之旅。
    2014-07-07
  • iOS + node.js使用Socket.IO框架進(jìn)行實(shí)時(shí)通信示例

    iOS + node.js使用Socket.IO框架進(jìn)行實(shí)時(shí)通信示例

    本篇文章主要介紹了iOS + node.js使用Socket.IO框架進(jìn)行實(shí)時(shí)通信示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • node中使用es6/7/8(支持性與性能)

    node中使用es6/7/8(支持性與性能)

    這篇文章主要介紹了node中使用es6/7/8(支持性與性能),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-03-03
  • node.js做一個(gè)簡(jiǎn)單的爬蟲(chóng)案例教程

    node.js做一個(gè)簡(jiǎn)單的爬蟲(chóng)案例教程

    這篇文章主要介紹了node.js做一個(gè)簡(jiǎn)單的爬蟲(chóng)案例教程,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 使用pm2管理node項(xiàng)目的流程步驟

    使用pm2管理node項(xiàng)目的流程步驟

    pm2?是?nodejs?的進(jìn)程管理器,默認(rèn)支持負(fù)載均衡,能夠守護(hù)進(jìn)程,還支持查看應(yīng)用運(yùn)行時(shí)的性能,資源占用情況等,本文給大家介紹了使用pm2管理node項(xiàng)目的流程步驟,需要的朋友可以參考下
    2025-03-03
  • 使用GruntJS構(gòu)建Web程序之合并壓縮篇

    使用GruntJS構(gòu)建Web程序之合并壓縮篇

    前一篇講述了如何使用concat和uglify命令實(shí)現(xiàn)JavaScript資源的合并,壓縮。這篇講述下css資源的合并和壓縮。
    2014-06-06
  • 基于node.js實(shí)現(xiàn)爬蟲(chóng)的講解

    基于node.js實(shí)現(xiàn)爬蟲(chóng)的講解

    今天小編就為大家分享一篇關(guān)于基于node.js實(shí)現(xiàn)爬蟲(chóng)的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-02-02
  • 淺談node的事件機(jī)制

    淺談node的事件機(jī)制

    本篇文章主要介紹了node的事件機(jī)制,本文通過(guò)實(shí)現(xiàn)一個(gè)簡(jiǎn)易的、具有發(fā)布/訂閱模式的事件機(jī)制,以此來(lái)理清EventEmitter類的實(shí)現(xiàn)思路,有興趣的可以了解一下
    2017-10-10
  • 詳解如何在Node.js中使用中間件處理請(qǐng)求

    詳解如何在Node.js中使用中間件處理請(qǐng)求

    在Node.js中,處理中間件是處理HTTP請(qǐng)求和響應(yīng)的一個(gè)常見(jiàn)方式,甚至扮演著至關(guān)重要的角色,本文將介紹如何在Node.js中使用中間件來(lái)處理請(qǐng)求,感興趣的可以了解下
    2025-02-02

最新評(píng)論

延庆县| 博白县| 潞城市| 沈阳市| 曲沃县| 普洱| 梅河口市| 古浪县| 治县。| 淮南市| 金山区| 孟村| 商河县| 梧州市| 蒙阴县| 和田县| 罗田县| 明溪县| 永寿县| 新余市| 资中县| 沅陵县| 江北区| 西乡县| 民丰县| 翼城县| 修武县| 石屏县| 科技| 晴隆县| 台湾省| 张家口市| 商河县| 安阳县| 大冶市| 西昌市| 澄江县| 准格尔旗| 瑞安市| 仙居县| 高台县|