[js高手之路]Node.js+jade抓取博客全部文章生成靜態html文件

這個週末,惡補了一下jade模板引擎,就爲生成靜態html文件,這篇文章須要知道jade以及看過個人上篇文章,我先給出他們的參考連接:css

[js高手之路]Node.js模板引擎教程-jade速學與實戰1-基本用法html

[js高手之路]Node.js模板引擎教程-jade速學與實戰2-流程控制,轉義與非轉義node

[js高手之路]Node.js模板引擎教程-jade速學與實戰3-mixinmongodb

[js高手之路]Node.js模板引擎教程-jade速學與實戰4-模板引用,繼承,插件使用express

[js高手之路]Node.js實現簡易的爬蟲-抓取博客全部文章列表信息bootstrap

在上面分享的這篇文章中,我抓取了博客的全部文章列表. 並無採集入庫,也沒有作別的處理。這篇文章,咱們就把上文中採集到的全部文章列表的信息整理一下,開始採集文章而且生成靜態html文件了.先看下個人採集效果,個人博客目前77篇文章,1分鐘不到就所有采集生成完畢了,這裏我截了部分的圖片,文件名用文章的id生成的,生成的文章,我寫了一個簡單的靜態模板,全部的文章都是根據這個模板生成的.api

項目結構:post

 

 

 好了,接下來,咱們就來說解下,這篇文章主要實現的功能:ui

1,抓取文章,主要抓取文章的標題,內容,超連接,文章id(用於生成靜態html文件)this

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

1、抓取文章如何實現?

很是簡單,跟上文抓取文章列表的實現差很少

 1 function crawlerArc( url ){
 2     var html = '';
 3     var str = '';
 4     var arcDetail = {};
 5     http.get(url, function (res) {
 6         res.on('data', function (chunk) {
 7             html += chunk;
 8         });
 9         res.on('end', function () {
10             arcDetail = filterArticle( html );
11             str = jade.renderFile('./views/layout.jade', arcDetail );
12             fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
13                 if( err ) {
14                     console.log( err );
15                 }
16                 console.log( 'success:' + url );
17                 if ( aUrl.length ) crawlerArc( aUrl.shift() );
18             } );
19         });
20     });
21 }

參數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:

  1 var fs = require( 'fs' );
  2 var http = require( 'http' );
  3 var cheerio = require( 'cheerio' );
  4 var jade = require( 'jade' );
  5 
  6 var aList = [];
  7 var aUrl = [];
  8 
  9 function filterArticle(html) {
 10     var $ = cheerio.load( html );
 11     var arcDetail = {};
 12     var title = $( "#cb_post_title_url" ).text();
 13     var href = $( "#cb_post_title_url" ).attr( "href" );
 14     var re = /\/(\d+)\.html/;
 15     var id = href.match( re )[1];
 16     var body = $( "#cnblogs_post_body" ).html();
 17     return {
 18         id : id,
 19         title : title,
 20         href : href,
 21         body : body
 22     };
 23 }
 24 
 25 function crawlerArc( url ){
 26     var html = '';
 27     var str = '';
 28     var arcDetail = {};
 29     http.get(url, function (res) {
 30         res.on('data', function (chunk) {
 31             html += chunk;
 32         });
 33         res.on('end', function () {
 34             arcDetail = filterArticle( html );
 35             str = jade.renderFile('./views/layout.jade', arcDetail );
 36             fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
 37                 if( err ) {
 38                     console.log( err );
 39                 }
 40                 console.log( 'success:' + url );
 41                 if ( aUrl.length ) crawlerArc( aUrl.shift() );
 42             } );
 43         });
 44     });
 45 }
 46 
 47 function filterHtml(html) {
 48     var $ = cheerio.load(html);
 49     var arcList = [];
 50     var aPost = $("#content").find(".post-list-item");
 51     aPost.each(function () {
 52         var ele = $(this);
 53         var title = ele.find("h2 a").text();
 54         var url = ele.find("h2 a").attr("href");
 55         ele.find(".c_b_p_desc a").remove();
 56         var entry = ele.find(".c_b_p_desc").text();
 57         ele.find("small a").remove();
 58         var listTime = ele.find("small").text();
 59         var re = /\d{4}-\d{2}-\d{2}\s*\d{2}[:]\d{2}/;
 60         listTime = listTime.match(re)[0];
 61 
 62         arcList.push({
 63             title: title,
 64             url: url,
 65             entry: entry,
 66             listTime: listTime
 67         });
 68     });
 69     return arcList;
 70 }
 71 
 72 function nextPage( html ){
 73     var $ = cheerio.load(html);
 74     var nextUrl = $("#pager a:last-child").attr('href');
 75     if ( !nextUrl ) return getArcUrl( aList );
 76     var curPage = $("#pager .current").text();
 77     if( !curPage ) curPage = 1;
 78     var nextPage = nextUrl.substring( nextUrl.indexOf( '=' ) + 1 );
 79     if ( curPage < nextPage ) crawler( nextUrl );
 80 }
 81 
 82 function crawler(url) {
 83     http.get(url, function (res) {
 84         var html = '';
 85         res.on('data', function (chunk) {
 86             html += chunk;
 87         });
 88         res.on('end', function () {
 89             aList.push( filterHtml(html) );
 90             nextPage( html );
 91         });
 92     });
 93 }
 94 
 95 function getArcUrl( arcList ){
 96     for( var key in arcList ){
 97         for( var k in arcList[key] ){
 98             aUrl.push( arcList[key][k]['url'] );
 99         }
100     }
101     crawlerArc( aUrl.shift() );
102 }
103 
104 var url = 'http://www.cnblogs.com/ghostwu/';
105 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}") !{title}
                p !{body}
        block footer
            div.container
                footer 版權全部 - by ghostwu

後續的打算:

1,採用mongodb入庫

2,支持斷點採集

3,採集圖片

4,採集小說

等等....

相關文章
相關標籤/搜索